Merge branch 'master' into transparent_windows

This commit is contained in:
Cem Karan 2016-05-05 10:21:49 -04:00
commit 6b43754ba8
87 changed files with 5757 additions and 2973 deletions

View File

@ -1,22 +1,22 @@
branches: branches:
only: only:
- ci - ci
- master - master
skip_tags: true skip_tags: true
environment: environment:
matrix: matrix:
- BUILD_SHARED_LIBS: ON - BUILD_SHARED_LIBS: ON
- BUILD_SHARED_LIBS: OFF - BUILD_SHARED_LIBS: OFF
matrix: matrix:
fast_finish: true fast_finish: true
build_script: build_script:
- mkdir build - mkdir build
- cd build - cd build
- cmake -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% .. - cmake -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% ..
- cmake --build . - cmake --build .
notifications: notifications:
- provider: Email - provider: Email
to: to:
- ci@glfw.org - ci@glfw.org
- on_build_failure: true - on_build_failure: true
- on_build_success: false - on_build_success: false

View File

@ -1,106 +1,106 @@
# Contribution Guide # Contribution Guide
This file is a work in progress and you can report errors or submit patches for This file is a work in progress and you can report errors or submit patches for
it the same as any other file. it the same as any other file.
## Reporting a bug ## Reporting a bug
If GLFW is behaving unexpectedly, make sure you have set an error callback. If GLFW is behaving unexpectedly, make sure you have set an error callback.
GLFW will often tell you the cause of an issue via this callback. GLFW will often tell you the cause of an issue via this callback.
If GLFW is crashing or triggering asserts, make sure that all your object If GLFW is crashing or triggering asserts, make sure that all your object
handles and other pointers are valid. handles and other pointers are valid.
Always include the __operating system name and version__ (i.e. `Windows Always include the __operating system name and version__ (i.e. `Windows
7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW, 7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW,
include the __GLFW release version__ (i.e. `3.1.2`), otherwise include the include the __GLFW release version__ (i.e. `3.1.2`), otherwise include the
__GLFW commit ID__ (i.e. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git. __GLFW commit ID__ (i.e. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
If possible, please also include the __GLFW version string__ (`3.2.0 X11 EGL If possible, please also include the __GLFW version string__ (`3.2.0 X11 EGL
clock_gettime /dev/js XI Xf86vm`), as described clock_gettime /dev/js XI Xf86vm`), as described
[here](http://www.glfw.org/docs/latest/intro.html#intro_version_string). [here](http://www.glfw.org/docs/latest/intro.html#intro_version_string).
### Reporting a compile or link bug ### Reporting a compile or link bug
__Note:__ GLFW needs many system APIs to do its job. See the [Building __Note:__ GLFW needs many system APIs to do its job. See the [Building
applications](http://www.glfw.org/docs/latest/build.html) guide for more applications](http://www.glfw.org/docs/latest/build.html) guide for more
information. information.
In addition to the information above, always include the complete build log from In addition to the information above, always include the complete build log from
your compiler and linker. Issue posts are editable so it can always be your compiler and linker. Issue posts are editable so it can always be
shortened later. shortened later.
### Reporting a context creation bug ### Reporting a context creation bug
__Note:__ Windows ships with graphics drivers that do not support OpenGL. If __Note:__ Windows ships with graphics drivers that do not support OpenGL. If
GLFW says that your machine lacks support for OpenGL, it very likely does. GLFW says that your machine lacks support for OpenGL, it very likely does.
Install drivers from the computer manufacturer or graphics card manufacturer Install drivers from the computer manufacturer or graphics card manufacturer
([Nvidia](http://www.geforce.com/drivers), ([Nvidia](http://www.geforce.com/drivers),
[AMD](http://support.amd.com/en-us/download), [AMD](http://support.amd.com/en-us/download),
[Intel](https://www-ssl.intel.com/content/www/us/en/support/detect.html)) to [Intel](https://www-ssl.intel.com/content/www/us/en/support/detect.html)) to
fix this. fix this.
__Note:__ AMD only supports OpenGL ES on Windows via EGL. EGL support is not __Note:__ AMD only supports OpenGL ES on Windows via EGL. EGL support is not
enabled in GLFW by default. You need to [enable EGL when enabled in GLFW by default. You need to [enable EGL when
compiling](http://www.glfw.org/docs/latest/compile.html) GLFW to use this. compiling](http://www.glfw.org/docs/latest/compile.html) GLFW to use this.
The `glfwinfo` tool is included in the GLFW source tree as `tests/glfwinfo.c` The `glfwinfo` tool is included in the GLFW source tree as `tests/glfwinfo.c`
and is built along with the library. It lets you request any kind of context and is built along with the library. It lets you request any kind of context
and framebuffer format supported by the GLFW API without having to recompile. and framebuffer format supported by the GLFW API without having to recompile.
If context creation fails in your application, please verify that it also fails If context creation fails in your application, please verify that it also fails
with this tool before reporting it as a bug. with this tool before reporting it as a bug.
In addition to the information above (OS and GLFW version), always include the In addition to the information above (OS and GLFW version), always include the
__GPU model and driver version__ (i.e. `GeForce GTX660 with 352.79`) when __GPU model and driver version__ (i.e. `GeForce GTX660 with 352.79`) when
reporting this kind of bug. reporting this kind of bug.
### Reporting a monitor or video mode bug ### Reporting a monitor or video mode bug
__Note:__ On headless systems on some platforms, no monitors are reported. This __Note:__ On headless systems on some platforms, no monitors are reported. This
causes glfwGetPrimaryMonitor to return `NULL`, which not all applications are causes glfwGetPrimaryMonitor to return `NULL`, which not all applications are
prepared for. prepared for.
__Note:__ Some third-party tools report more video modes than those approved of __Note:__ Some third-party tools report more video modes than those approved of
by the OS. For safety and compatbility, GLFW only reports video modes the OS by the OS. For safety and compatbility, GLFW only reports video modes the OS
wants programs to use. This is not a bug. wants programs to use. This is not a bug.
The `monitors` tool is included in the GLFW source tree as `tests/monitors.c` The `monitors` tool is included in the GLFW source tree as `tests/monitors.c`
and is built along with the library. lists all information about connected and is built along with the library. lists all information about connected
monitors made available by GLFW. monitors made available by GLFW.
In addition to the information above (OS and GLFW version), please also include In addition to the information above (OS and GLFW version), please also include
the output of the `monitors` tool when reporting this kind of bug. If it the output of the `monitors` tool when reporting this kind of bug. If it
doesn't work at all, please mention this. doesn't work at all, please mention this.
### Reporting a window event bug ### Reporting a window event bug
__Note:__ While GLFW tries to provide the exact same behavior between platforms, __Note:__ While GLFW tries to provide the exact same behavior between platforms,
the exact ordering of related window events will sometimes differ. the exact ordering of related window events will sometimes differ.
The `events` tool is included in the GLFW source tree as `tests/events.c` and is The `events` tool is included in the GLFW source tree as `tests/events.c` and is
built along with the library. It prints all information provided to every built along with the library. It prints all information provided to every
callback supported by GLFW as events occur. Each event is listed with the time callback supported by GLFW as events occur. Each event is listed with the time
and a unique number to make discussions about event logs easier. The tool has and a unique number to make discussions about event logs easier. The tool has
command-line options for creating multiple windows and full screen windows. command-line options for creating multiple windows and full screen windows.
### Reporting a documentation bug ### Reporting a documentation bug
If you found the error in the generated documentation then it's fine to just If you found the error in the generated documentation then it's fine to just
link to that webpage. You don't need to figure out which documentation source link to that webpage. You don't need to figure out which documentation source
file the text comes from. file the text comes from.
## Contributing a bug fix ## Contributing a bug fix
There should be text here, but there isn't. There should be text here, but there isn't.
## Contributing a feature ## Contributing a feature
This is not (yet) the text you are looking for. This is not (yet) the text you are looking for.

6
.gitignore vendored
View File

@ -13,11 +13,13 @@ Debug
Release Release
MinSizeRel MinSizeRel
RelWithDebInfo RelWithDebInfo
*.xcodeproj
# CMake files # CMake files
Makefile Makefile
CMakeCache.txt CMakeCache.txt
CMakeFiles CMakeFiles
CMakeScripts
cmake_install.cmake cmake_install.cmake
cmake_uninstall.cmake cmake_uninstall.cmake
@ -30,6 +32,10 @@ src/glfw_config.h
src/glfw3.pc src/glfw3.pc
src/glfw3Config.cmake src/glfw3Config.cmake
src/glfw3ConfigVersion.cmake src/glfw3ConfigVersion.cmake
src/wayland-pointer-constraints-unstable-v1-client-protocol.h
src/wayland-pointer-constraints-unstable-v1-protocol.c
src/wayland-relative-pointer-unstable-v1-client-protocol.h
src/wayland-relative-pointer-unstable-v1-protocol.c
# Compiled binaries # Compiled binaries
src/libglfw.so src/libglfw.so

View File

@ -1,16 +0,0 @@
# Find EGL
#
# EGL_INCLUDE_DIR
# EGL_LIBRARY
# EGL_FOUND
find_path(EGL_INCLUDE_DIR NAMES EGL/egl.h PATHS /opt/vc/include)
set(EGL_NAMES ${EGL_NAMES} egl EGL libEGL)
find_library(EGL_LIBRARY NAMES ${EGL_NAMES} PATHS /opt/vc/lib)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(EGL DEFAULT_MSG EGL_LIBRARY EGL_INCLUDE_DIR)
mark_as_advanced(EGL_INCLUDE_DIR EGL_LIBRARY)

View File

@ -1,16 +0,0 @@
# Find GLESv1
#
# GLESv1_INCLUDE_DIR
# GLESv1_LIBRARY
# GLESv1_FOUND
find_path(GLESv1_INCLUDE_DIR NAMES GLES/gl.h PATHS /opt/vc/include)
set(GLESv1_NAMES ${GLESv1_NAMES} GLESv1_CM libGLES_CM)
find_library(GLESv1_LIBRARY NAMES ${GLESv1_NAMES} PATHS /opt/vc/lib)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GLESv1 DEFAULT_MSG GLESv1_LIBRARY GLESv1_INCLUDE_DIR)
mark_as_advanced(GLESv1_INCLUDE_DIR GLESv1_LIBRARY)

View File

@ -1,16 +0,0 @@
# Find GLESv2
#
# GLESv2_INCLUDE_DIR
# GLESv2_LIBRARY
# GLESv2_FOUND
find_path(GLESv2_INCLUDE_DIR NAMES GLES2/gl2.h PATHS /opt/vc/include)
set(GLESv2_NAMES ${GLESv2_NAMES} GLESv2 libGLESv2)
find_library(GLESv2_LIBRARY NAMES ${GLESv2_NAMES} PATHS /opt/vc/lib)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GLESv2 DEFAULT_MSG GLESv2_LIBRARY GLESv2_INCLUDE_DIR)
mark_as_advanced(GLESv2_INCLUDE_DIR GLESv2_LIBRARY)

View File

@ -6,9 +6,17 @@
if (WIN32) if (WIN32)
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
"$ENV{VULKAN_SDK}/Include"
"$ENV{VK_SDK_PATH}/Include") "$ENV{VK_SDK_PATH}/Include")
find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS if (CMAKE_CL_64)
"$ENV{VK_SDK_PATH}/Bin") find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS
"$ENV{VULKAN_SDK}/Bin"
"$ENV{VK_SDK_PATH}/Bin")
else()
find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS
"$ENV{VULKAN_SDK}/Bin32"
"$ENV{VK_SDK_PATH}/Bin32")
endif()
else() else()
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
"$ENV{VULKAN_SDK}/include") "$ENV{VULKAN_SDK}/include")

View File

@ -1,66 +0,0 @@
# Try to find Wayland on a Unix system
#
# This will define:
#
# WAYLAND_FOUND - True if Wayland is found
# WAYLAND_LIBRARIES - Link these to use Wayland
# WAYLAND_INCLUDE_DIR - Include directory for Wayland
# WAYLAND_DEFINITIONS - Compiler flags for using Wayland
#
# In addition the following more fine grained variables will be defined:
#
# WAYLAND_CLIENT_FOUND WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES
# WAYLAND_SERVER_FOUND WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES
# WAYLAND_EGL_FOUND WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES
#
# Copyright (c) 2013 Martin Gräßlin <mgraesslin@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
IF (NOT WIN32)
IF (WAYLAND_INCLUDE_DIR AND WAYLAND_LIBRARIES)
# In the cache already
SET(WAYLAND_FIND_QUIETLY TRUE)
ENDIF ()
# Use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
FIND_PACKAGE(PkgConfig)
PKG_CHECK_MODULES(PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl wayland-cursor)
SET(WAYLAND_DEFINITIONS ${PKG_WAYLAND_CFLAGS})
FIND_PATH(WAYLAND_CLIENT_INCLUDE_DIR NAMES wayland-client.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
FIND_PATH(WAYLAND_SERVER_INCLUDE_DIR NAMES wayland-server.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
FIND_PATH(WAYLAND_EGL_INCLUDE_DIR NAMES wayland-egl.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
FIND_PATH(WAYLAND_CURSOR_INCLUDE_DIR NAMES wayland-cursor.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
FIND_LIBRARY(WAYLAND_CLIENT_LIBRARIES NAMES wayland-client HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
FIND_LIBRARY(WAYLAND_SERVER_LIBRARIES NAMES wayland-server HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
FIND_LIBRARY(WAYLAND_EGL_LIBRARIES NAMES wayland-egl HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
FIND_LIBRARY(WAYLAND_CURSOR_LIBRARIES NAMES wayland-cursor HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
set(WAYLAND_INCLUDE_DIR ${WAYLAND_CLIENT_INCLUDE_DIR} ${WAYLAND_SERVER_INCLUDE_DIR} ${WAYLAND_EGL_INCLUDE_DIR} ${WAYLAND_CURSOR_INCLUDE_DIR})
set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_EGL_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES})
list(REMOVE_DUPLICATES WAYLAND_INCLUDE_DIR)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CLIENT DEFAULT_MSG WAYLAND_CLIENT_LIBRARIES WAYLAND_CLIENT_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_SERVER DEFAULT_MSG WAYLAND_SERVER_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_EGL DEFAULT_MSG WAYLAND_EGL_LIBRARIES WAYLAND_EGL_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CURSOR DEFAULT_MSG WAYLAND_CURSOR_LIBRARIES WAYLAND_CURSOR_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIR)
MARK_AS_ADVANCED(
WAYLAND_INCLUDE_DIR WAYLAND_LIBRARIES
WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES
WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES
WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES
WAYLAND_CURSOR_INCLUDE_DIR WAYLAND_CURSOR_LIBRARIES
)
ENDIF ()

View File

@ -0,0 +1,26 @@
find_package(PkgConfig)
pkg_check_modules(WaylandProtocols QUIET wayland-protocols>=${WaylandProtocols_FIND_VERSION})
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols
OUTPUT_VARIABLE WaylandProtocols_PKGDATADIR
RESULT_VARIABLE _pkgconfig_failed)
if (_pkgconfig_failed)
message(FATAL_ERROR "Missing wayland-protocols pkgdatadir")
endif()
string(REGEX REPLACE "[\r\n]" "" WaylandProtocols_PKGDATADIR "${WaylandProtocols_PKGDATADIR}")
find_package_handle_standard_args(WaylandProtocols
FOUND_VAR
WaylandProtocols_FOUND
REQUIRED_VARS
WaylandProtocols_PKGDATADIR
VERSION_VAR
WaylandProtocols_VERSION
HANDLE_COMPONENTS
)
set(WAYLAND_PROTOCOLS_FOUND ${WaylandProtocols_FOUND})
set(WAYLAND_PROTOCOLS_PKGDATADIR ${WaylandProtocols_PKGDATADIR})
set(WAYLAND_PROTOCOLS_VERSION ${WaylandProtocols_VERSION})

View File

@ -1,3 +1,5 @@
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
project(GLFW C) project(GLFW C)
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8.12)
@ -33,13 +35,11 @@ if (APPLE)
option(GLFW_USE_CHDIR "Make glfwInit chdir to Contents/Resources" ON) option(GLFW_USE_CHDIR "Make glfwInit chdir to Contents/Resources" ON)
option(GLFW_USE_MENUBAR "Populate the menu bar on first window creation" ON) option(GLFW_USE_MENUBAR "Populate the menu bar on first window creation" ON)
option(GLFW_USE_RETINA "Use the full resolution of Retina displays" ON) option(GLFW_USE_RETINA "Use the full resolution of Retina displays" ON)
else()
option(GLFW_USE_EGL "Use EGL for context creation" OFF)
endif() endif()
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
option(GLFW_USE_WAYLAND "Use Wayland for context creation (implies EGL as well)" OFF) option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
option(GLFW_USE_MIR "Use Mir for context creation (implies EGL as well)" OFF) option(GLFW_USE_MIR "Use Mir for window creation" OFF)
endif() endif()
if (MSVC) if (MSVC)
@ -57,12 +57,6 @@ else()
set(GLFW_LIB_NAME glfw3) set(GLFW_LIB_NAME glfw3)
endif() endif()
if (GLFW_USE_WAYLAND)
set(GLFW_USE_EGL ON)
elseif (GLFW_USE_MIR)
set(GLFW_USE_EGL ON)
endif()
set(CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules") set(CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
@ -71,10 +65,6 @@ find_package(Vulkan)
if (GLFW_BUILD_DOCS) if (GLFW_BUILD_DOCS)
set(DOXYGEN_SKIP_DOT TRUE) set(DOXYGEN_SKIP_DOT TRUE)
find_package(Doxygen) find_package(Doxygen)
if (GLFW_DOCUMENT_INTERNALS)
set(GLFW_INTERNAL_DOCS "${GLFW_SOURCE_DIR}/src/internal.h ${GLFW_SOURCE_DIR}/docs/internal.dox")
endif()
endif() endif()
#-------------------------------------------------------------------- #--------------------------------------------------------------------
@ -131,19 +121,9 @@ endif()
if (WIN32) if (WIN32)
set(_GLFW_WIN32 1) set(_GLFW_WIN32 1)
message(STATUS "Using Win32 for window creation") message(STATUS "Using Win32 for window creation")
if (GLFW_USE_EGL)
set(_GLFW_EGL 1)
message(STATUS "Using EGL for context creation")
else()
set(_GLFW_WGL 1)
message(STATUS "Using WGL for context creation")
endif()
elseif (APPLE) elseif (APPLE)
set(_GLFW_COCOA 1) set(_GLFW_COCOA 1)
message(STATUS "Using Cocoa for window creation") message(STATUS "Using Cocoa for window creation")
set(_GLFW_NSGL 1)
message(STATUS "Using NSGL for context creation")
elseif (UNIX) elseif (UNIX)
if (GLFW_USE_WAYLAND) if (GLFW_USE_WAYLAND)
set(_GLFW_WAYLAND 1) set(_GLFW_WAYLAND 1)
@ -155,14 +135,6 @@ elseif (UNIX)
set(_GLFW_X11 1) set(_GLFW_X11 1)
message(STATUS "Using X11 for window creation") message(STATUS "Using X11 for window creation")
endif() endif()
if (GLFW_USE_EGL)
set(_GLFW_EGL 1)
message(STATUS "Using EGL for context creation")
else()
set(_GLFW_GLX 1)
message(STATUS "Using GLX for context creation")
endif()
else() else()
message(FATAL_ERROR "No supported platform was detected") message(FATAL_ERROR "No supported platform was detected")
endif() endif()
@ -234,21 +206,6 @@ if (_GLFW_X11)
list(APPEND glfw_LIBRARIES "${X11_Xinerama_LIB}") list(APPEND glfw_LIBRARIES "${X11_Xinerama_LIB}")
list(APPEND glfw_PKG_DEPS "xinerama") list(APPEND glfw_PKG_DEPS "xinerama")
# Check for XInput (high-resolution cursor motion)
if (X11_Xinput_FOUND)
list(APPEND glfw_INCLUDE_DIRS "${X11_Xinput_INCLUDE_PATH}")
list(APPEND glfw_PKG_DEPS "xi")
if (X11_Xinput_LIB)
list(APPEND glfw_LIBRARIES "${X11_Xinput_LIB}")
else()
# Backwards compatibility (bug in CMake 2.8.7)
list(APPEND glfw_LIBRARIES Xi)
endif()
set(_GLFW_HAS_XINPUT TRUE)
endif()
# Check for Xf86VidMode (fallback gamma control) # Check for Xf86VidMode (fallback gamma control)
if (X11_xf86vmode_FOUND) if (X11_xf86vmode_FOUND)
list(APPEND glfw_INCLUDE_DIRS "${X11_xf86vmode_INCLUDE_PATH}") list(APPEND glfw_INCLUDE_DIRS "${X11_xf86vmode_INCLUDE_PATH}")
@ -286,11 +243,17 @@ endif()
# Use Wayland for window creation # Use Wayland for window creation
#-------------------------------------------------------------------- #--------------------------------------------------------------------
if (_GLFW_WAYLAND) if (_GLFW_WAYLAND)
find_package(ECM REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH})
find_package(Wayland REQUIRED) find_package(Wayland REQUIRED)
find_package(WaylandScanner REQUIRED)
find_package(WaylandProtocols 1.1 REQUIRED)
list(APPEND glfw_PKG_DEPS "wayland-egl") list(APPEND glfw_PKG_DEPS "wayland-egl")
list(APPEND glfw_INCLUDE_DIRS "${WAYLAND_INCLUDE_DIR}") list(APPEND glfw_INCLUDE_DIRS "${Wayland_INCLUDE_DIR}")
list(APPEND glfw_LIBRARIES "${WAYLAND_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}") list(APPEND glfw_LIBRARIES "${Wayland_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
find_package(XKBCommon REQUIRED) find_package(XKBCommon REQUIRED)
list(APPEND glfw_PKG_DEPS "xkbcommon") list(APPEND glfw_PKG_DEPS "xkbcommon")
@ -317,7 +280,7 @@ endif()
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Use Cocoa for window creation and NSOpenGL for context creation # Use Cocoa for window creation and NSOpenGL for context creation
#-------------------------------------------------------------------- #--------------------------------------------------------------------
if (_GLFW_COCOA AND _GLFW_NSGL) if (_GLFW_COCOA)
if (GLFW_USE_MENUBAR) if (GLFW_USE_MENUBAR)
set(_GLFW_USE_MENUBAR 1) set(_GLFW_USE_MENUBAR 1)
@ -378,10 +341,6 @@ write_basic_package_version_file(src/glfw3ConfigVersion.cmake
VERSION ${GLFW_VERSION_FULL} VERSION ${GLFW_VERSION_FULL}
COMPATIBILITY SameMajorVersion) COMPATIBILITY SameMajorVersion)
if (GLFW_BUILD_DOCS)
configure_file(docs/Doxyfile.in docs/Doxyfile @ONLY)
endif()
configure_file(src/glfw_config.h.in src/glfw_config.h @ONLY) configure_file(src/glfw_config.h.in src/glfw_config.h @ONLY)
configure_file(src/glfw3.pc.in src/glfw3.pc @ONLY) configure_file(src/glfw3.pc.in src/glfw3.pc @ONLY)

View File

@ -12,7 +12,7 @@ for creating windows, contexts and surfaces, reading input, handling events, etc
Version 3.2 is _not yet described_. Version 3.2 is _not yet described_.
If you are new to GLFW, you may find the If you are new to GLFW, you may find the
[introductory tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW [tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW
3 useful. If you have used GLFW 2 in the past, there is a 3 useful. If you have used GLFW 2 in the past, there is a
[transition guide](http://www.glfw.org/docs/latest/moving.html) for moving to [transition guide](http://www.glfw.org/docs/latest/moving.html) for moving to
the GLFW 3 API. the GLFW 3 API.
@ -52,8 +52,8 @@ GLFW itself needs only the headers and libraries for your window system. It
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL) or does not need the headers for any context creation API (WGL, GLX, EGL, NSGL) or
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them. rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
GLFW bundles a number of dependencies in the `deps/` directory. These are only The examples and test programs depend on a number of tiny libraries. These are
used by the tests and examples and are not required to build the library. located in the `deps/` directory.
- [getopt\_port](https://github.com/kimgr/getopt_port/) for examples - [getopt\_port](https://github.com/kimgr/getopt_port/) for examples
with command-line options with command-line options
@ -63,46 +63,75 @@ used by the tests and examples and are not required to build the library.
[glad](https://github.com/Dav1dde/glad) for examples using modern OpenGL [glad](https://github.com/Dav1dde/glad) for examples using modern OpenGL
- [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in - [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in
examples examples
- [Vulkan headers](https://www.khronos.org/registry/vulkan/) for Vulkan tests
The Vulkan example additionally requires the Vulkan SDK to be installed, or it The Vulkan example additionally requires the Vulkan SDK to be installed, or it
will not be included in the build. will not be included in the build.
The documentation is generated with [Doxygen](http://doxygen.org/). If CMake
does not find Doxygen, the documentation will not be generated.
## Changelog ## Changelog
- Added `glfwVulkanSupported`, `glfwGetRequiredInstanceExtensions`, - Added `glfwVulkanSupported`, `glfwGetRequiredInstanceExtensions`,
`glfwGetInstanceProcAddress`, `glfwGetPhysicalDevicePresentationSupport` and `glfwGetInstanceProcAddress`, `glfwGetPhysicalDevicePresentationSupport` and
`glfwCreateWindowSurface` for platform independent Vulkan support `glfwCreateWindowSurface` for platform independent Vulkan support
- Added `glfwSetWindowMonitor` for switching between windowed and full screen
modes and updating the monitor and desired video mode of full screen windows
- Added `glfwMaximizeWindow` and `GLFW_MAXIMIZED` for window maximization
- Added `glfwFocusWindow` for giving windows input focus
- Added `glfwSetWindowSizeLimits` and `glfwSetWindowAspectRatio` for setting - Added `glfwSetWindowSizeLimits` and `glfwSetWindowAspectRatio` for setting
absolute and relative window size limits absolute and relative window size limits
- Added `glfwGetKeyName` for querying the layout-specific name of printable - Added `glfwGetKeyName` for querying the layout-specific name of printable
keys keys
- Added `glfwWaitEventsTimeout` for waiting for events for a set amount of time
- Added `glfwSetWindowIcon` for setting the icon of a window
- Added `glfwGetTimerValue` and `glfwGetTimerFrequency` for raw timer access
- Added `glfwSetJoystickCallback` and `GLFWjoystickfun` for joystick connection
and disconnection events
- Added `GLFW_NO_API` for creating window without contexts - Added `GLFW_NO_API` for creating window without contexts
- Added `GLFW_CONTEXT_NO_ERROR` context hint for `GL_KHR_no_error` support - Added `GLFW_CONTEXT_NO_ERROR` context hint for `GL_KHR_no_error` support
- Added `GLFW_INCLUDE_VULKAN` for including the Vulkan header - Added `GLFW_INCLUDE_VULKAN` for including the Vulkan header
- Added `GLFW_CONTEXT_CREATION_API`, `GLFW_NATIVE_CONTEXT_API` and
`GLFW_EGL_CONTEXT_API` for run-time context creation API selection
- Added `GLFW_TRUE` and `GLFW_FALSE` as client API independent boolean values - Added `GLFW_TRUE` and `GLFW_FALSE` as client API independent boolean values
- Added `glfwGetGLXWindow` to query the `GLXWindow` of a window
- Added icons to examples on Windows and OS X - Added icons to examples on Windows and OS X
- Relaxed rules for native access header macros - Relaxed rules for native access header macros
- Removed dependency on external OpenGL or OpenGL ES headers - Removed dependency on external OpenGL or OpenGL ES headers
- Removed `_GLFW_USE_OPENGL`, `_GLFW_USE_GLESV1` and `_GLFW_USE_GLESV2` - Removed `_GLFW_USE_OPENGL`, `_GLFW_USE_GLESV1`, `_GLFW_USE_GLESV2`,
configuration macros `_GLFW_WGL`, `_GLFW_NSGL`, `_GLFW_GLX` and `_GLFW_EGL` configuration macros
- [Win32] Added support for Windows 8.1 per-monitor DPI - [Win32] Added support for Windows 8.1 per-monitor DPI
- [Win32] Replaced winmm with XInput and DirectInput for joystick input
- [Win32] Bugfix: Window creation would segfault if video mode setting required - [Win32] Bugfix: Window creation would segfault if video mode setting required
the system to be restarted the system to be restarted
- [Win32] Bugfix: MinGW import library lacked the `lib` prefix - [Win32] Bugfix: MinGW import library lacked the `lib` prefix
- [Win32] Bugfix: Monitor connection and disconnection events were not reported - [Win32] Bugfix: Monitor connection and disconnection events were not reported
when no windows existed when no windows existed
- [Win32] Bugfix: Activating or deactivating displays in software did not
trigger monitor callback
- [Win32] Bugfix: No monitors were listed on headless and VMware guest systems
- [Win32] Bugfix: Pressing Ctrl+Pause would report `GLFW_KEY_UNKNOWN`
- [Win32] Bugfix: Window size events would be reported in wrong order when
restoring a full screen window
- [Cocoa] Made joystick polling more efficient
- [Cocoa] Removed support for OS X 10.6 - [Cocoa] Removed support for OS X 10.6
- [Cocoa] Bugfix: Full screen windows on secondary monitors were mispositioned - [Cocoa] Bugfix: Full screen windows on secondary monitors were mispositioned
- [Cocoa] Bugfix: Connecting a joystick that reports no name would segfault - [Cocoa] Bugfix: Connecting a joystick that reports no name would segfault
- [Cocoa] Bugfix: Modifier flags cache was not updated when window became key
- [Cocoa] Bugfix: Dead key character composition did not work
- [Cocoa] Bugfix: The CGL context was not released until the autorelease pool
was drained by another function
- [X11] Bugfix: Monitor connection and disconnection events were not reported - [X11] Bugfix: Monitor connection and disconnection events were not reported
- [X11] Bugfix: Decoding of UTF-8 text from XIM could continue past the end - [X11] Bugfix: Decoding of UTF-8 text from XIM could continue past the end
- [X11] Bugfix: An XKB structure was leaked during `glfwInit` - [X11] Bugfix: An XKB structure was leaked during `glfwInit`
- [X11] Bugfix: XInput2 `XI_Motion` events interfered with the Steam overlay
- [POSIX] Bugfix: An unrelated TLS key could be deleted by `glfwTerminate` - [POSIX] Bugfix: An unrelated TLS key could be deleted by `glfwTerminate`
- [Linux] Made joystick polling more efficient
- [WGL] Changed extension loading to only be performed once - [WGL] Changed extension loading to only be performed once
- [WGL] Removed dependency on external WGL headers - [WGL] Removed dependency on external WGL headers
- [GLX] Replaced legacy renderable with `GLXWindow` - [GLX] Added `glfwGetGLXWindow` to query the `GLXWindow` of a window
- [GLX] Replaced legacy drawable with `GLXWindow`
- [GLX] Removed dependency on external GLX headers - [GLX] Removed dependency on external GLX headers
- [GLX] Bugfix: NetBSD does not provide `libGL.so.1` - [GLX] Bugfix: NetBSD does not provide `libGL.so.1`
- [EGL] Added `_GLFW_USE_EGLPLATFORM_H` configuration macro for controlling - [EGL] Added `_GLFW_USE_EGLPLATFORM_H` configuration macro for controlling
@ -119,7 +148,7 @@ can find the latest version of GLFW, as well as news, documentation and other
information about the project. information about the project.
If you have questions related to the use of GLFW, we have a If you have questions related to the use of GLFW, we have a
[support forum](https://sourceforge.net/p/glfw/discussion/247562/), and the IRC [support forum](http://discourse.glfw.org/), and the IRC
channel `#glfw` on [Freenode](http://freenode.net/). channel `#glfw` on [Freenode](http://freenode.net/).
If you have a bug to report, a patch to submit or a feature you'd like to If you have a bug to report, a patch to submit or a feature you'd like to
@ -155,6 +184,7 @@ skills.
- Paul R. Deppe - Paul R. Deppe
- Michael Dickens - Michael Dickens
- Роман Донченко - Роман Донченко
- Mario Dorn
- Jonathan Dummer - Jonathan Dummer
- Ralph Eastwood - Ralph Eastwood
- Siavash Eliasi - Siavash Eliasi
@ -169,6 +199,7 @@ skills.
- heromyth - heromyth
- Lucas Hinderberger - Lucas Hinderberger
- Paul Holden - Paul Holden
- IntellectualKitty
- Aaron Jacobs - Aaron Jacobs
- Toni Jovanoski - Toni Jovanoski
- Arseny Kapoulkine - Arseny Kapoulkine
@ -205,6 +236,7 @@ skills.
- Peoro - Peoro
- Braden Pellett - Braden Pellett
- Arturo J. Pérez - Arturo J. Pérez
- Orson Peters
- Emmanuel Gil Peyrot - Emmanuel Gil Peyrot
- Cyril Pichard - Cyril Pichard
- Pieroman - Pieroman
@ -218,6 +250,7 @@ skills.
- SephiRok - SephiRok
- Steve Sexton - Steve Sexton
- Systemcluster - Systemcluster
- Yoshiki Shibukawa
- Dmitri Shuralyov - Dmitri Shuralyov
- Daniel Skorupski - Daniel Skorupski
- Bradley Smith - Bradley Smith
@ -229,6 +262,7 @@ skills.
- TTK-Bandit - TTK-Bandit
- Sergey Tikhomirov - Sergey Tikhomirov
- A. Tombs - A. Tombs
- Ioannis Tsakpinis
- Samuli Tuomola - Samuli Tuomola
- urraka - urraka
- Jari Vetoniemi - Jari Vetoniemi
@ -237,6 +271,7 @@ skills.
- Simon Voordouw - Simon Voordouw
- Torsten Walluhn - Torsten Walluhn
- Patrick Walton - Patrick Walton
- Xo Wang
- Jay Weisskopf - Jay Weisskopf
- Frank Wille - Frank Wille
- yuriks - yuriks

1
deps/tinycthread.h vendored
View File

@ -78,6 +78,7 @@ freely, subject to the following restrictions:
/* Platform specific includes */ /* Platform specific includes */
#if defined(_TTHREAD_POSIX_) #if defined(_TTHREAD_POSIX_)
#include <sys/time.h>
#include <pthread.h> #include <pthread.h>
#elif defined(_TTHREAD_WIN32_) #elif defined(_TTHREAD_WIN32_)
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN

View File

@ -4,29 +4,22 @@
/* /*
** Copyright (c) 2014-2015 The Khronos Group Inc. ** Copyright (c) 2014-2015 The Khronos Group Inc.
** **
** Permission is hereby granted, free of charge, to any person obtaining a ** Licensed under the Apache License, Version 2.0 (the "License");
** copy of this software and/or associated documentation files (the ** you may not use this file except in compliance with the License.
** "Materials"), to deal in the Materials without restriction, including ** You may obtain a copy of the License at
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
** **
** The above copyright notice and this permission notice shall be included ** http://www.apache.org/licenses/LICENSE-2.0
** in all copies or substantial portions of the Materials.
** **
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ** Unless required by applicable law or agreed to in writing, software
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ** distributed under the License is distributed on an "AS IS" BASIS,
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY ** See the License for the specific language governing permissions and
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, ** limitations under the License.
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/ */
#ifndef __VK_PLATFORM_H__ #ifndef VK_PLATFORM_H_
#define __VK_PLATFORM_H__ #define VK_PLATFORM_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
@ -124,4 +117,4 @@ extern "C"
#include <xcb/xcb.h> #include <xcb/xcb.h>
#endif #endif
#endif // __VK_PLATFORM_H__ #endif

136
deps/vulkan/vulkan.h vendored
View File

@ -1,5 +1,5 @@
#ifndef __vulkan_h_ #ifndef VULKAN_H_
#define __vulkan_h_ 1 #define VULKAN_H_ 1
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -8,24 +8,17 @@ extern "C" {
/* /*
** Copyright (c) 2015-2016 The Khronos Group Inc. ** Copyright (c) 2015-2016 The Khronos Group Inc.
** **
** Permission is hereby granted, free of charge, to any person obtaining a ** Licensed under the Apache License, Version 2.0 (the "License");
** copy of this software and/or associated documentation files (the ** you may not use this file except in compliance with the License.
** "Materials"), to deal in the Materials without restriction, including ** You may obtain a copy of the License at
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
** **
** The above copyright notice and this permission notice shall be included ** http://www.apache.org/licenses/LICENSE-2.0
** in all copies or substantial portions of the Materials.
** **
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ** Unless required by applicable law or agreed to in writing, software
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ** distributed under the License is distributed on an "AS IS" BASIS,
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY ** See the License for the specific language governing permissions and
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, ** limitations under the License.
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/ */
/* /*
@ -40,12 +33,18 @@ extern "C" {
#define VK_MAKE_VERSION(major, minor, patch) \ #define VK_MAKE_VERSION(major, minor, patch) \
(((major) << 22) | ((minor) << 12) | (patch)) (((major) << 22) | ((minor) << 12) | (patch))
// Vulkan API version supported by this file // DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead.
#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 3) //#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0)
// Vulkan 1.0 version number
#define VK_API_VERSION_1_0 VK_MAKE_VERSION(1, 0, 0)
#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) #define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22)
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff) #define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff) #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
// Version of this file
#define VK_HEADER_VERSION 11
#define VK_NULL_HANDLE 0 #define VK_NULL_HANDLE 0
@ -142,6 +141,7 @@ typedef enum VkResult {
VK_ERROR_OUT_OF_DATE_KHR = -1000001004, VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001, VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
VK_ERROR_VALIDATION_FAILED_EXT = -1000011001, VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
VK_ERROR_INVALID_SHADER_NV = -1000012000,
VK_RESULT_BEGIN_RANGE = VK_ERROR_FORMAT_NOT_SUPPORTED, VK_RESULT_BEGIN_RANGE = VK_ERROR_FORMAT_NOT_SUPPORTED,
VK_RESULT_END_RANGE = VK_INCOMPLETE, VK_RESULT_END_RANGE = VK_INCOMPLETE,
VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_FORMAT_NOT_SUPPORTED + 1), VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_FORMAT_NOT_SUPPORTED + 1),
@ -209,7 +209,7 @@ typedef enum VkStructureType {
VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000, VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000, VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000,
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000, VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = 1000011000, VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000,
VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO, VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO, VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO,
VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1), VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1),
@ -679,6 +679,7 @@ typedef enum VkDynamicState {
typedef enum VkFilter { typedef enum VkFilter {
VK_FILTER_NEAREST = 0, VK_FILTER_NEAREST = 0,
VK_FILTER_LINEAR = 1, VK_FILTER_LINEAR = 1,
VK_FILTER_CUBIC_IMG = 1000015000,
VK_FILTER_BEGIN_RANGE = VK_FILTER_NEAREST, VK_FILTER_BEGIN_RANGE = VK_FILTER_NEAREST,
VK_FILTER_END_RANGE = VK_FILTER_LINEAR, VK_FILTER_END_RANGE = VK_FILTER_LINEAR,
VK_FILTER_RANGE_SIZE = (VK_FILTER_LINEAR - VK_FILTER_NEAREST + 1), VK_FILTER_RANGE_SIZE = (VK_FILTER_LINEAR - VK_FILTER_NEAREST + 1),
@ -701,8 +702,8 @@ typedef enum VkSamplerAddressMode {
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3,
VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4,
VK_SAMPLER_ADDRESS_MODE_BEGIN_RANGE = VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_BEGIN_RANGE = VK_SAMPLER_ADDRESS_MODE_REPEAT,
VK_SAMPLER_ADDRESS_MODE_END_RANGE = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_END_RANGE = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
VK_SAMPLER_ADDRESS_MODE_RANGE_SIZE = (VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE - VK_SAMPLER_ADDRESS_MODE_REPEAT + 1), VK_SAMPLER_ADDRESS_MODE_RANGE_SIZE = (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER - VK_SAMPLER_ADDRESS_MODE_REPEAT + 1),
VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF
} VkSamplerAddressMode; } VkSamplerAddressMode;
@ -808,6 +809,8 @@ typedef enum VkFormatFeatureFlagBits {
VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0x00000400, VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0x00000400,
VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800, VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000,
VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkFormatFeatureFlagBits; } VkFormatFeatureFlagBits;
typedef VkFlags VkFormatFeatureFlags; typedef VkFlags VkFormatFeatureFlags;
@ -820,6 +823,7 @@ typedef enum VkImageUsageFlagBits {
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020,
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040,
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080,
VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkImageUsageFlagBits; } VkImageUsageFlagBits;
typedef VkFlags VkImageUsageFlags; typedef VkFlags VkImageUsageFlags;
@ -829,6 +833,7 @@ typedef enum VkImageCreateFlagBits {
VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004, VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008,
VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010,
VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkImageCreateFlagBits; } VkImageCreateFlagBits;
typedef VkFlags VkImageCreateFlags; typedef VkFlags VkImageCreateFlags;
@ -840,6 +845,7 @@ typedef enum VkSampleCountFlagBits {
VK_SAMPLE_COUNT_16_BIT = 0x00000010, VK_SAMPLE_COUNT_16_BIT = 0x00000010,
VK_SAMPLE_COUNT_32_BIT = 0x00000020, VK_SAMPLE_COUNT_32_BIT = 0x00000020,
VK_SAMPLE_COUNT_64_BIT = 0x00000040, VK_SAMPLE_COUNT_64_BIT = 0x00000040,
VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkSampleCountFlagBits; } VkSampleCountFlagBits;
typedef VkFlags VkSampleCountFlags; typedef VkFlags VkSampleCountFlags;
@ -848,6 +854,7 @@ typedef enum VkQueueFlagBits {
VK_QUEUE_COMPUTE_BIT = 0x00000002, VK_QUEUE_COMPUTE_BIT = 0x00000002,
VK_QUEUE_TRANSFER_BIT = 0x00000004, VK_QUEUE_TRANSFER_BIT = 0x00000004,
VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008, VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008,
VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkQueueFlagBits; } VkQueueFlagBits;
typedef VkFlags VkQueueFlags; typedef VkFlags VkQueueFlags;
@ -857,11 +864,13 @@ typedef enum VkMemoryPropertyFlagBits {
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004,
VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008, VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008,
VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010, VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010,
VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkMemoryPropertyFlagBits; } VkMemoryPropertyFlagBits;
typedef VkFlags VkMemoryPropertyFlags; typedef VkFlags VkMemoryPropertyFlags;
typedef enum VkMemoryHeapFlagBits { typedef enum VkMemoryHeapFlagBits {
VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001, VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001,
VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkMemoryHeapFlagBits; } VkMemoryHeapFlagBits;
typedef VkFlags VkMemoryHeapFlags; typedef VkFlags VkMemoryHeapFlags;
typedef VkFlags VkDeviceCreateFlags; typedef VkFlags VkDeviceCreateFlags;
@ -885,6 +894,7 @@ typedef enum VkPipelineStageFlagBits {
VK_PIPELINE_STAGE_HOST_BIT = 0x00004000, VK_PIPELINE_STAGE_HOST_BIT = 0x00004000,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000,
VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkPipelineStageFlagBits; } VkPipelineStageFlagBits;
typedef VkFlags VkPipelineStageFlags; typedef VkFlags VkPipelineStageFlags;
typedef VkFlags VkMemoryMapFlags; typedef VkFlags VkMemoryMapFlags;
@ -894,6 +904,7 @@ typedef enum VkImageAspectFlagBits {
VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002, VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002,
VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004, VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004,
VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008, VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008,
VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkImageAspectFlagBits; } VkImageAspectFlagBits;
typedef VkFlags VkImageAspectFlags; typedef VkFlags VkImageAspectFlags;
@ -901,16 +912,19 @@ typedef enum VkSparseImageFormatFlagBits {
VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0x00000001, VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0x00000001,
VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 0x00000002, VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 0x00000002,
VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 0x00000004, VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 0x00000004,
VK_SPARSE_IMAGE_FORMAT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkSparseImageFormatFlagBits; } VkSparseImageFormatFlagBits;
typedef VkFlags VkSparseImageFormatFlags; typedef VkFlags VkSparseImageFormatFlags;
typedef enum VkSparseMemoryBindFlagBits { typedef enum VkSparseMemoryBindFlagBits {
VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001, VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001,
VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkSparseMemoryBindFlagBits; } VkSparseMemoryBindFlagBits;
typedef VkFlags VkSparseMemoryBindFlags; typedef VkFlags VkSparseMemoryBindFlags;
typedef enum VkFenceCreateFlagBits { typedef enum VkFenceCreateFlagBits {
VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001, VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001,
VK_FENCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkFenceCreateFlagBits; } VkFenceCreateFlagBits;
typedef VkFlags VkFenceCreateFlags; typedef VkFlags VkFenceCreateFlags;
typedef VkFlags VkSemaphoreCreateFlags; typedef VkFlags VkSemaphoreCreateFlags;
@ -929,6 +943,7 @@ typedef enum VkQueryPipelineStatisticFlagBits {
VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0x00000100, VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0x00000100,
VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0x00000200, VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0x00000200,
VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400, VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400,
VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkQueryPipelineStatisticFlagBits; } VkQueryPipelineStatisticFlagBits;
typedef VkFlags VkQueryPipelineStatisticFlags; typedef VkFlags VkQueryPipelineStatisticFlags;
@ -937,6 +952,7 @@ typedef enum VkQueryResultFlagBits {
VK_QUERY_RESULT_WAIT_BIT = 0x00000002, VK_QUERY_RESULT_WAIT_BIT = 0x00000002,
VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004, VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004,
VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008, VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008,
VK_QUERY_RESULT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkQueryResultFlagBits; } VkQueryResultFlagBits;
typedef VkFlags VkQueryResultFlags; typedef VkFlags VkQueryResultFlags;
@ -944,6 +960,7 @@ typedef enum VkBufferCreateFlagBits {
VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0x00000001, VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0x00000001,
VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002, VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004, VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
VK_BUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkBufferCreateFlagBits; } VkBufferCreateFlagBits;
typedef VkFlags VkBufferCreateFlags; typedef VkFlags VkBufferCreateFlags;
@ -957,6 +974,7 @@ typedef enum VkBufferUsageFlagBits {
VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040, VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040,
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080,
VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100,
VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkBufferUsageFlagBits; } VkBufferUsageFlagBits;
typedef VkFlags VkBufferUsageFlags; typedef VkFlags VkBufferUsageFlags;
typedef VkFlags VkBufferViewCreateFlags; typedef VkFlags VkBufferViewCreateFlags;
@ -968,6 +986,7 @@ typedef enum VkPipelineCreateFlagBits {
VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001, VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001,
VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002, VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002,
VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004, VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkPipelineCreateFlagBits; } VkPipelineCreateFlagBits;
typedef VkFlags VkPipelineCreateFlags; typedef VkFlags VkPipelineCreateFlags;
typedef VkFlags VkPipelineShaderStageCreateFlags; typedef VkFlags VkPipelineShaderStageCreateFlags;
@ -979,8 +998,9 @@ typedef enum VkShaderStageFlagBits {
VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008, VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008,
VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010, VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010,
VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020, VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020,
VK_SHADER_STAGE_ALL_GRAPHICS = 0x1F, VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F,
VK_SHADER_STAGE_ALL = 0x7FFFFFFF, VK_SHADER_STAGE_ALL = 0x7FFFFFFF,
VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkShaderStageFlagBits; } VkShaderStageFlagBits;
typedef VkFlags VkPipelineVertexInputStateCreateFlags; typedef VkFlags VkPipelineVertexInputStateCreateFlags;
typedef VkFlags VkPipelineInputAssemblyStateCreateFlags; typedef VkFlags VkPipelineInputAssemblyStateCreateFlags;
@ -992,7 +1012,8 @@ typedef enum VkCullModeFlagBits {
VK_CULL_MODE_NONE = 0, VK_CULL_MODE_NONE = 0,
VK_CULL_MODE_FRONT_BIT = 0x00000001, VK_CULL_MODE_FRONT_BIT = 0x00000001,
VK_CULL_MODE_BACK_BIT = 0x00000002, VK_CULL_MODE_BACK_BIT = 0x00000002,
VK_CULL_MODE_FRONT_AND_BACK = 0x3, VK_CULL_MODE_FRONT_AND_BACK = 0x00000003,
VK_CULL_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkCullModeFlagBits; } VkCullModeFlagBits;
typedef VkFlags VkCullModeFlags; typedef VkFlags VkCullModeFlags;
typedef VkFlags VkPipelineMultisampleStateCreateFlags; typedef VkFlags VkPipelineMultisampleStateCreateFlags;
@ -1004,6 +1025,7 @@ typedef enum VkColorComponentFlagBits {
VK_COLOR_COMPONENT_G_BIT = 0x00000002, VK_COLOR_COMPONENT_G_BIT = 0x00000002,
VK_COLOR_COMPONENT_B_BIT = 0x00000004, VK_COLOR_COMPONENT_B_BIT = 0x00000004,
VK_COLOR_COMPONENT_A_BIT = 0x00000008, VK_COLOR_COMPONENT_A_BIT = 0x00000008,
VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkColorComponentFlagBits; } VkColorComponentFlagBits;
typedef VkFlags VkColorComponentFlags; typedef VkFlags VkColorComponentFlags;
typedef VkFlags VkPipelineDynamicStateCreateFlags; typedef VkFlags VkPipelineDynamicStateCreateFlags;
@ -1014,6 +1036,7 @@ typedef VkFlags VkDescriptorSetLayoutCreateFlags;
typedef enum VkDescriptorPoolCreateFlagBits { typedef enum VkDescriptorPoolCreateFlagBits {
VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001,
VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkDescriptorPoolCreateFlagBits; } VkDescriptorPoolCreateFlagBits;
typedef VkFlags VkDescriptorPoolCreateFlags; typedef VkFlags VkDescriptorPoolCreateFlags;
typedef VkFlags VkDescriptorPoolResetFlags; typedef VkFlags VkDescriptorPoolResetFlags;
@ -1022,6 +1045,7 @@ typedef VkFlags VkRenderPassCreateFlags;
typedef enum VkAttachmentDescriptionFlagBits { typedef enum VkAttachmentDescriptionFlagBits {
VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0x00000001, VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0x00000001,
VK_ATTACHMENT_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkAttachmentDescriptionFlagBits; } VkAttachmentDescriptionFlagBits;
typedef VkFlags VkAttachmentDescriptionFlags; typedef VkFlags VkAttachmentDescriptionFlags;
typedef VkFlags VkSubpassDescriptionFlags; typedef VkFlags VkSubpassDescriptionFlags;
@ -1044,22 +1068,26 @@ typedef enum VkAccessFlagBits {
VK_ACCESS_HOST_WRITE_BIT = 0x00004000, VK_ACCESS_HOST_WRITE_BIT = 0x00004000,
VK_ACCESS_MEMORY_READ_BIT = 0x00008000, VK_ACCESS_MEMORY_READ_BIT = 0x00008000,
VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000, VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000,
VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkAccessFlagBits; } VkAccessFlagBits;
typedef VkFlags VkAccessFlags; typedef VkFlags VkAccessFlags;
typedef enum VkDependencyFlagBits { typedef enum VkDependencyFlagBits {
VK_DEPENDENCY_BY_REGION_BIT = 0x00000001, VK_DEPENDENCY_BY_REGION_BIT = 0x00000001,
VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkDependencyFlagBits; } VkDependencyFlagBits;
typedef VkFlags VkDependencyFlags; typedef VkFlags VkDependencyFlags;
typedef enum VkCommandPoolCreateFlagBits { typedef enum VkCommandPoolCreateFlagBits {
VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001,
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002,
VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkCommandPoolCreateFlagBits; } VkCommandPoolCreateFlagBits;
typedef VkFlags VkCommandPoolCreateFlags; typedef VkFlags VkCommandPoolCreateFlags;
typedef enum VkCommandPoolResetFlagBits { typedef enum VkCommandPoolResetFlagBits {
VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001,
VK_COMMAND_POOL_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkCommandPoolResetFlagBits; } VkCommandPoolResetFlagBits;
typedef VkFlags VkCommandPoolResetFlags; typedef VkFlags VkCommandPoolResetFlags;
@ -1067,23 +1095,27 @@ typedef enum VkCommandBufferUsageFlagBits {
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001,
VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002, VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002,
VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004, VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004,
VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkCommandBufferUsageFlagBits; } VkCommandBufferUsageFlagBits;
typedef VkFlags VkCommandBufferUsageFlags; typedef VkFlags VkCommandBufferUsageFlags;
typedef enum VkQueryControlFlagBits { typedef enum VkQueryControlFlagBits {
VK_QUERY_CONTROL_PRECISE_BIT = 0x00000001, VK_QUERY_CONTROL_PRECISE_BIT = 0x00000001,
VK_QUERY_CONTROL_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkQueryControlFlagBits; } VkQueryControlFlagBits;
typedef VkFlags VkQueryControlFlags; typedef VkFlags VkQueryControlFlags;
typedef enum VkCommandBufferResetFlagBits { typedef enum VkCommandBufferResetFlagBits {
VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001,
VK_COMMAND_BUFFER_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkCommandBufferResetFlagBits; } VkCommandBufferResetFlagBits;
typedef VkFlags VkCommandBufferResetFlags; typedef VkFlags VkCommandBufferResetFlags;
typedef enum VkStencilFaceFlagBits { typedef enum VkStencilFaceFlagBits {
VK_STENCIL_FACE_FRONT_BIT = 0x00000001, VK_STENCIL_FACE_FRONT_BIT = 0x00000001,
VK_STENCIL_FACE_BACK_BIT = 0x00000002, VK_STENCIL_FACE_BACK_BIT = 0x00000002,
VK_STENCIL_FRONT_AND_BACK = 0x3, VK_STENCIL_FRONT_AND_BACK = 0x00000003,
VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkStencilFaceFlagBits; } VkStencilFaceFlagBits;
typedef VkFlags VkStencilFaceFlags; typedef VkFlags VkStencilFaceFlags;
@ -3140,10 +3172,10 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)
typedef enum VkColorSpaceKHR { typedef enum VkColorSpaceKHR {
VK_COLORSPACE_SRGB_NONLINEAR_KHR = 0, VK_COLORSPACE_SRGB_NONLINEAR_KHR = 0,
VK_COLORSPACE_BEGIN_RANGE = VK_COLORSPACE_SRGB_NONLINEAR_KHR, VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLORSPACE_SRGB_NONLINEAR_KHR,
VK_COLORSPACE_END_RANGE = VK_COLORSPACE_SRGB_NONLINEAR_KHR, VK_COLOR_SPACE_END_RANGE_KHR = VK_COLORSPACE_SRGB_NONLINEAR_KHR,
VK_COLORSPACE_RANGE_SIZE = (VK_COLORSPACE_SRGB_NONLINEAR_KHR - VK_COLORSPACE_SRGB_NONLINEAR_KHR + 1), VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLORSPACE_SRGB_NONLINEAR_KHR - VK_COLORSPACE_SRGB_NONLINEAR_KHR + 1),
VK_COLORSPACE_MAX_ENUM = 0x7FFFFFFF VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF
} VkColorSpaceKHR; } VkColorSpaceKHR;
typedef enum VkPresentModeKHR { typedef enum VkPresentModeKHR {
@ -3151,10 +3183,10 @@ typedef enum VkPresentModeKHR {
VK_PRESENT_MODE_MAILBOX_KHR = 1, VK_PRESENT_MODE_MAILBOX_KHR = 1,
VK_PRESENT_MODE_FIFO_KHR = 2, VK_PRESENT_MODE_FIFO_KHR = 2,
VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3, VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3,
VK_PRESENT_MODE_BEGIN_RANGE = VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_BEGIN_RANGE_KHR = VK_PRESENT_MODE_IMMEDIATE_KHR,
VK_PRESENT_MODE_END_RANGE = VK_PRESENT_MODE_FIFO_RELAXED_KHR, VK_PRESENT_MODE_END_RANGE_KHR = VK_PRESENT_MODE_FIFO_RELAXED_KHR,
VK_PRESENT_MODE_RANGE_SIZE = (VK_PRESENT_MODE_FIFO_RELAXED_KHR - VK_PRESENT_MODE_IMMEDIATE_KHR + 1), VK_PRESENT_MODE_RANGE_SIZE_KHR = (VK_PRESENT_MODE_FIFO_RELAXED_KHR - VK_PRESENT_MODE_IMMEDIATE_KHR + 1),
VK_PRESENT_MODE_MAX_ENUM = 0x7FFFFFFF VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF
} VkPresentModeKHR; } VkPresentModeKHR;
@ -3168,6 +3200,7 @@ typedef enum VkSurfaceTransformFlagBitsKHR {
VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040, VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040,
VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080, VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080,
VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100, VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100,
VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkSurfaceTransformFlagBitsKHR; } VkSurfaceTransformFlagBitsKHR;
typedef VkFlags VkSurfaceTransformFlagsKHR; typedef VkFlags VkSurfaceTransformFlagsKHR;
@ -3176,6 +3209,7 @@ typedef enum VkCompositeAlphaFlagBitsKHR {
VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002, VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002,
VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0x00000004, VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0x00000004,
VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008, VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008,
VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkCompositeAlphaFlagBitsKHR; } VkCompositeAlphaFlagBitsKHR;
typedef VkFlags VkCompositeAlphaFlagsKHR; typedef VkFlags VkCompositeAlphaFlagsKHR;
@ -3237,7 +3271,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(
#define VK_KHR_swapchain 1 #define VK_KHR_swapchain 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR)
#define VK_KHR_SWAPCHAIN_SPEC_VERSION 67 #define VK_KHR_SWAPCHAIN_SPEC_VERSION 68
#define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain" #define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain"
typedef VkFlags VkSwapchainCreateFlagsKHR; typedef VkFlags VkSwapchainCreateFlagsKHR;
@ -3325,9 +3359,10 @@ typedef enum VkDisplayPlaneAlphaFlagBitsKHR {
VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0x00000002, VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0x00000002,
VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0x00000004, VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0x00000004,
VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0x00000008, VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0x00000008,
VK_DISPLAY_PLANE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkDisplayPlaneAlphaFlagBitsKHR; } VkDisplayPlaneAlphaFlagBitsKHR;
typedef VkFlags VkDisplayModeCreateFlagsKHR;
typedef VkFlags VkDisplayPlaneAlphaFlagsKHR; typedef VkFlags VkDisplayPlaneAlphaFlagsKHR;
typedef VkFlags VkDisplayModeCreateFlagsKHR;
typedef VkFlags VkDisplaySurfaceCreateFlagsKHR; typedef VkFlags VkDisplaySurfaceCreateFlagsKHR;
typedef struct VkDisplayPropertiesKHR { typedef struct VkDisplayPropertiesKHR {
@ -3392,7 +3427,7 @@ typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)(VkPhys
typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties); typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties);
typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneSupportedDisplaysKHR)(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays); typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneSupportedDisplaysKHR)(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays);
typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModePropertiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties); typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModePropertiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties);
typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayModeKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR*pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode); typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayModeKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode);
typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities); typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities);
typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayPlaneSurfaceKHR)(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayPlaneSurfaceKHR)(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
@ -3667,11 +3702,17 @@ VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR(
#endif #endif
#endif /* VK_USE_PLATFORM_WIN32_KHR */ #endif /* VK_USE_PLATFORM_WIN32_KHR */
#define VK_KHR_sampler_mirror_clamp_to_edge 1
#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION 1
#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge"
#define VK_EXT_debug_report 1 #define VK_EXT_debug_report 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 1 #define VK_EXT_DEBUG_REPORT_SPEC_VERSION 2
#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report" #define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
#define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
typedef enum VkDebugReportObjectTypeEXT { typedef enum VkDebugReportObjectTypeEXT {
@ -3704,11 +3745,19 @@ typedef enum VkDebugReportObjectTypeEXT {
VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26, VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26,
VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27,
VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = 28, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = 28,
VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
} VkDebugReportObjectTypeEXT; } VkDebugReportObjectTypeEXT;
typedef enum VkDebugReportErrorEXT { typedef enum VkDebugReportErrorEXT {
VK_DEBUG_REPORT_ERROR_NONE_EXT = 0, VK_DEBUG_REPORT_ERROR_NONE_EXT = 0,
VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT = 1, VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT = 1,
VK_DEBUG_REPORT_ERROR_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_ERROR_NONE_EXT,
VK_DEBUG_REPORT_ERROR_END_RANGE_EXT = VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT,
VK_DEBUG_REPORT_ERROR_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT - VK_DEBUG_REPORT_ERROR_NONE_EXT + 1),
VK_DEBUG_REPORT_ERROR_MAX_ENUM_EXT = 0x7FFFFFFF
} VkDebugReportErrorEXT; } VkDebugReportErrorEXT;
@ -3718,6 +3767,7 @@ typedef enum VkDebugReportFlagBitsEXT {
VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 0x00000004, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 0x00000004,
VK_DEBUG_REPORT_ERROR_BIT_EXT = 0x00000008, VK_DEBUG_REPORT_ERROR_BIT_EXT = 0x00000008,
VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0x00000010, VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0x00000010,
VK_DEBUG_REPORT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
} VkDebugReportFlagBitsEXT; } VkDebugReportFlagBitsEXT;
typedef VkFlags VkDebugReportFlagsEXT; typedef VkFlags VkDebugReportFlagsEXT;
@ -3768,6 +3818,16 @@ VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
const char* pMessage); const char* pMessage);
#endif #endif
#define VK_NV_glsl_shader 1
#define VK_NV_GLSL_SHADER_SPEC_VERSION 1
#define VK_NV_GLSL_SHADER_EXTENSION_NAME "VK_NV_glsl_shader"
#define VK_IMG_filter_cubic 1
#define VK_IMG_FILTER_CUBIC_SPEC_VERSION 1
#define VK_IMG_FILTER_CUBIC_EXTENSION_NAME "VK_IMG_filter_cubic"
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,5 +1,33 @@
add_custom_target(docs ALL ${DOXYGEN_EXECUTABLE} set(glfw_DOCS_SOURCES
WORKING_DIRECTORY ${GLFW_BINARY_DIR}/docs "${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h"
"${GLFW_SOURCE_DIR}/docs/main.dox"
"${GLFW_SOURCE_DIR}/docs/news.dox"
"${GLFW_SOURCE_DIR}/docs/moving.dox"
"${GLFW_SOURCE_DIR}/docs/quick.dox"
"${GLFW_SOURCE_DIR}/docs/compile.dox"
"${GLFW_SOURCE_DIR}/docs/build.dox"
"${GLFW_SOURCE_DIR}/docs/intro.dox"
"${GLFW_SOURCE_DIR}/docs/context.dox"
"${GLFW_SOURCE_DIR}/docs/monitor.dox"
"${GLFW_SOURCE_DIR}/docs/window.dox"
"${GLFW_SOURCE_DIR}/docs/input.dox"
"${GLFW_SOURCE_DIR}/docs/vulkan.dox"
"${GLFW_SOURCE_DIR}/docs/rift.dox"
"${GLFW_SOURCE_DIR}/docs/compat.dox")
if (GLFW_DOCUMENT_INTERNALS)
list(APPEND glfw_DOCS_SOURCES "${GLFW_SOURCE_DIR}/src/internal.h")
endif()
foreach(arg ${glfw_DOCS_SOURCES})
set(GLFW_DOCS_SOURCES "${GLFW_DOCS_SOURCES} ${arg}")
endforeach()
configure_file(Doxyfile.in Doxyfile @ONLY)
add_custom_target(docs ALL "${DOXYGEN_EXECUTABLE}"
WORKING_DIRECTORY "${GLFW_BINARY_DIR}/docs"
COMMENT "Generating HTML documentation" VERBATIM) COMMENT "Generating HTML documentation" VERBATIM)

View File

@ -660,23 +660,7 @@ WARN_LOGFILE = @GLFW_BINARY_DIR@/docs/warnings.txt
# directories like "/usr/src/myproject". Separate the files or directories # directories like "/usr/src/myproject". Separate the files or directories
# with spaces. # with spaces.
INPUT = @GLFW_INTERNAL_DOCS@ \ INPUT = @GLFW_DOCS_SOURCES@
@GLFW_SOURCE_DIR@/include/GLFW/glfw3.h \
@GLFW_SOURCE_DIR@/include/GLFW/glfw3native.h \
@GLFW_SOURCE_DIR@/docs/main.dox \
@GLFW_SOURCE_DIR@/docs/news.dox \
@GLFW_SOURCE_DIR@/docs/moving.dox \
@GLFW_SOURCE_DIR@/docs/quick.dox \
@GLFW_SOURCE_DIR@/docs/compile.dox \
@GLFW_SOURCE_DIR@/docs/build.dox \
@GLFW_SOURCE_DIR@/docs/intro.dox \
@GLFW_SOURCE_DIR@/docs/context.dox \
@GLFW_SOURCE_DIR@/docs/monitor.dox \
@GLFW_SOURCE_DIR@/docs/window.dox \
@GLFW_SOURCE_DIR@/docs/input.dox \
@GLFW_SOURCE_DIR@/docs/vulkan.dox \
@GLFW_SOURCE_DIR@/docs/rift.dox \
@GLFW_SOURCE_DIR@/docs/compat.dox
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

View File

@ -1,13 +1,13 @@
/*! /*!
@page build Building applications @page build_guide Building applications
@tableofcontents @tableofcontents
This is about compiling and linking applications that use GLFW. For information on This is about compiling and linking applications that use GLFW. For information on
how to write such applications, start with the [introductory tutorial](@ref quick). how to write such applications, start with the
For information on how to compile the GLFW library itself, see the @ref compile [introductory tutorial](@ref quick_guide). For information on how to compile
guide. the GLFW library itself, see @ref compile_guide.
This is not a tutorial on compilation or linking. It assumes basic This is not a tutorial on compilation or linking. It assumes basic
understanding of how to compile and link a C program as well as how to use the understanding of how to compile and link a C program as well as how to use the
@ -158,7 +158,17 @@ build_link_cmake_module.
With just a few changes to your `CMakeLists.txt` you can have the GLFW source With just a few changes to your `CMakeLists.txt` you can have the GLFW source
tree built along with your application. tree built along with your application.
Firstly, add the root directory of the GLFW source tree to your project. This When including GLFW as part of your build, you probably don't want to build the
GLFW tests, examples and documentation. To disable these, set the corresponding
cache variables before adding the GLFW source tree.
@code
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
@endcode
Then add the root directory of the GLFW source tree to your project. This
will add the `glfw` target and the necessary cache variables to your project. will add the `glfw` target and the necessary cache variables to your project.
@code{.cmake} @code{.cmake}
@ -231,7 +241,7 @@ target_link_libraries(myapp ${OPENGL_glu_LIBRARY})
@subsection build_link_pkgconfig With makefiles and pkg-config on Unix @subsection build_link_pkgconfig With makefiles and pkg-config on Unix
GLFW supports [pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/), GLFW supports [pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/),
and the `glfw3.pc` pkf-config file is generated when the GLFW library is built and the `glfw3.pc` pkg-config file is generated when the GLFW library is built
and is installed along with it. A pkg-config file describes all necessary and is installed along with it. A pkg-config file describes all necessary
compile-time and link-time flags and dependencies needed to use a library. When compile-time and link-time flags and dependencies needed to use a library. When
they are updated or if they differ between systems, you will get the correct they are updated or if they differ between systems, you will get the correct

View File

@ -1,6 +1,6 @@
/*! /*!
@page compat Standards conformance @page compat_guide Standards conformance
@tableofcontents @tableofcontents
@ -63,10 +63,6 @@ GLFW uses the
to provide file drop events. If the application originating the drag does not to provide file drop events. If the application originating the drag does not
support this protocol, drag and drop will not work. support this protocol, drag and drop will not work.
GLFW uses the XInput 2 extension to provide sub-pixel cursor motion events. If
the running X server does not support this version of this extension, cursor
motion will be snapped to the pixel grid.
GLFW uses the XRandR 1.3 extension to provide multi-monitor support. If the GLFW uses the XRandR 1.3 extension to provide multi-monitor support. If the
running X server does not support this version of this extension, multi-monitor running X server does not support this version of this extension, multi-monitor
support will not function and only a single, desktop-spanning monitor will be support will not function and only a single, desktop-spanning monitor will be

View File

@ -1,11 +1,11 @@
/*! /*!
@page compile Compiling GLFW @page compile_guide Compiling GLFW
@tableofcontents @tableofcontents
This is about compiling the GLFW library itself. For information on how to This is about compiling the GLFW library itself. For information on how to
build applications that use GLFW, see the @ref build guide. build applications that use GLFW, see @ref build_guide.
@section compile_cmake Using CMake @section compile_cmake Using CMake
@ -87,10 +87,10 @@ Once you have Xcode installed, move on to @ref compile_generate.
@subsubsection compile_deps_x11 Dependencies for Linux and X11 @subsubsection compile_deps_x11 Dependencies for Linux and X11
To compile GLFW for X11, you need to have the X11 and OpenGL header packages To compile GLFW for X11, you need to have the X11 packages installed, as well as
installed, as well as the basic development tools like GCC and make. For the basic development tools like GCC and make. For example, on Ubuntu and other
example, on Ubuntu and other distributions based on Debian GNU/Linux, you need distributions based on Debian GNU/Linux, you need to install the `xorg-dev`
to install the `xorg-dev` package, which pulls in all X.org header packages. package, which pulls in all X.org header packages.
Once you have installed the necessary packages, move on to @ref Once you have installed the necessary packages, move on to @ref
compile_generate. compile_generate.
@ -156,7 +156,7 @@ necessary to compile GLFW. Go ahead and compile the actual GLFW library with
these files, as you would with any other project. these files, as you would with any other project.
Once the GLFW library is compiled, you are ready to build your applications, Once the GLFW library is compiled, you are ready to build your applications,
linking it to the GLFW library. See the @ref build guide for more information. linking it to the GLFW library. See @ref build_guide for more information.
@subsection compile_options CMake options @subsection compile_options CMake options
@ -166,7 +166,7 @@ available on all supported platforms. Some of these are de facto standards
among projects using CMake and so have no `GLFW_` prefix. among projects using CMake and so have no `GLFW_` prefix.
If you are using the GUI version of CMake, these are listed and can be changed If you are using the GUI version of CMake, these are listed and can be changed
from there. If you are using the command-line versionof CMake you can use the from there. If you are using the command-line version of CMake you can use the
`ccmake` ncurses GUI to set options. Some package systems like Ubuntu and other `ccmake` ncurses GUI to set options. Some package systems like Ubuntu and other
distributions based on Debian GNU/Linux have this tool in a separate distributions based on Debian GNU/Linux have this tool in a separate
`cmake-curses-gui` package. `cmake-curses-gui` package.
@ -225,19 +225,13 @@ need to be exported by the EXE to be detected by the driver, so the override
will not work if GLFW is built as a DLL. will not work if GLFW is built as a DLL.
@subsubsection compile_options_egl EGL specific CMake options
`GLFW_USE_EGL` determines whether to use EGL instead of the platform-specific
context creation API. Note that EGL is not yet provided on all supported
platforms.
@section compile_manual Compiling GLFW manually @section compile_manual Compiling GLFW manually
If you wish to compile GLFW without its CMake build environment then you will If you wish to compile GLFW without its CMake build environment then you will
have to do at least some of the platform detection yourself. GLFW needs have to do at least some of the platform detection yourself. GLFW needs
a number of configuration macros to be defined in order to know what it's being a configuration macro to be defined in order to know what window system it's
compiled for and has many optional, platform-specific ones for various features. being compiled for and also has optional, platform-specific ones for various
features.
When building with CMake, the `glfw_config.h` configuration header is generated When building with CMake, the `glfw_config.h` configuration header is generated
based on the current platform and CMake options. The GLFW CMake environment based on the current platform and CMake options. The GLFW CMake environment
@ -245,10 +239,6 @@ defines `_GLFW_USE_CONFIG_H`, which causes this header to be included by
`internal.h`. Without this macro, GLFW will expect the necessary configuration `internal.h`. Without this macro, GLFW will expect the necessary configuration
macros to be defined on the command-line. macros to be defined on the command-line.
Three macros _must_ be defined when compiling GLFW: one selecting the window
creation API and one selecting the context creation API. Exactly one of each
kind must be defined for GLFW to compile and link.
The window creation API is used to create windows, handle input, monitors, gamma The window creation API is used to create windows, handle input, monitors, gamma
ramps and clipboard. The options are: ramps and clipboard. The options are:
@ -258,24 +248,17 @@ ramps and clipboard. The options are:
- `_GLFW_WAYLAND` to use the Wayland API (experimental and incomplete) - `_GLFW_WAYLAND` to use the Wayland API (experimental and incomplete)
- `_GLFW_MIR` to use the Mir API (experimental and incomplete) - `_GLFW_MIR` to use the Mir API (experimental and incomplete)
The context creation API is used to enumerate pixel formats / framebuffer
configurations and to create contexts. The options are:
- `_GLFW_NSGL` to use the Cocoa OpenGL framework
- `_GLFW_WGL` to use the Win32 WGL API
- `_GLFW_GLX` to use the X11 GLX API
- `_GLFW_EGL` to use the EGL API
Wayland and Mir both require the EGL backend.
If you are building GLFW as a shared library / dynamic library / DLL then you If you are building GLFW as a shared library / dynamic library / DLL then you
must also define `_GLFW_BUILD_DLL`. Otherwise, you must not define it. must also define `_GLFW_BUILD_DLL`. Otherwise, you must not define it.
For the EGL context creation API, the following options are available:
- `_GLFW_USE_EGLPLATFORM_H` to use `EGL/eglplatform.h` for native handle
definitions (fallback)
If you are using the X11 window creation API, support for the following X11 If you are using the X11 window creation API, support for the following X11
extensions can be enabled: extensions can be enabled:
- `_GLFW_HAS_XINPUT` to use XInput2 for high-resolution cursor motion
(recommended)
- `_GLFW_HAS_XF86VM` to use Xxf86vm as a fallback when RandR gamma is broken - `_GLFW_HAS_XF86VM` to use Xxf86vm as a fallback when RandR gamma is broken
(recommended) (recommended)
@ -289,12 +272,6 @@ available:
- `_GLFW_USE_RETINA` to have windows use the full resolution of Retina displays - `_GLFW_USE_RETINA` to have windows use the full resolution of Retina displays
(recommended) (recommended)
If you are using the EGL context creation API, the following options are
available:
- `_GLFW_USE_EGLPLATFORM_H` to use `EGL/eglplatform.h` for native handle
definitions (fallback)
@note None of the @ref build_macros may be defined during the compilation of @note None of the @ref build_macros may be defined during the compilation of
GLFW. If you define any of these in your build files, make sure they are not GLFW. If you define any of these in your build files, make sure they are not
applied to the GLFW sources. applied to the GLFW sources.

View File

@ -1,16 +1,19 @@
/*! /*!
@page context Context guide @page context_guide Context guide
@tableofcontents @tableofcontents
This guide introduces the OpenGL and OpenGL ES context related functions of This guide introduces the OpenGL and OpenGL ES context related functions of
GLFW. There are also guides for the other areas of the GLFW API. GLFW. For details on a specific function, see the
[reference documentation](@ref context). There are also guides for the other
areas of the GLFW API.
- @ref intro - @ref intro_guide
- @ref window - @ref window_guide
- @ref monitor - @ref vulkan_guide
- @ref input - @ref monitor_guide
- @ref input_guide
@section context_object Context objects @section context_object Context objects
@ -29,7 +32,7 @@ the `glfwinfo` test program.
@note Vulkan does not have a context and the Vulkan instance is created via the @note Vulkan does not have a context and the Vulkan instance is created via the
Vulkan API itself. If you will be using Vulkan to render to a window, disable Vulkan API itself. If you will be using Vulkan to render to a window, disable
context creation by setting the [GLFW_CLIENT_API](@ref window_hints_ctx) hint to context creation by setting the [GLFW_CLIENT_API](@ref window_hints_ctx) hint to
`GLFW_NO_API`. For more information, see the @ref vulkan. `GLFW_NO_API`. For more information, see the @ref vulkan_guide.
@subsection context_hints Context creation hints @subsection context_hints Context creation hints
@ -174,9 +177,10 @@ python main.py --generator c --no-loader --out-path output
@endcode @endcode
The `--no-loader` option is added because GLFW already provides a function for The `--no-loader` option is added because GLFW already provides a function for
loading OpenGL and OpenGL ES function pointers and glad can call this instead of loading OpenGL and OpenGL ES function pointers, one that automatically uses the
having to implement its own. There are several other command-line options as selected context creation API, and glad can call this instead of having to
well. See the glad documentation for details. implement its own. There are several other command-line options as well. See
the glad documentation for details.
Add the generated `output/src/glad.c`, `output/include/glad/glad.h` and Add the generated `output/src/glad.c`, `output/include/glad/glad.h` and
`output/include/KHR/khrplatform.h` files to your build. Then you need to `output/include/KHR/khrplatform.h` files to your build. Then you need to

View File

@ -1,16 +1,17 @@
/*! /*!
@page input Input guide @page input_guide Input guide
@tableofcontents @tableofcontents
This guide introduces the input related functions of GLFW. There are also This guide introduces the input related functions of GLFW. For details on
guides for the other areas of GLFW. a specific function, see the [reference documentation](@ref input). There are
also guides for the other areas of GLFW.
- @ref intro - @ref intro_guide
- @ref window - @ref window_guide
- @ref context - @ref context_guide
- @ref monitor - @ref monitor_guide
GLFW provides many kinds of input. While some can only be polled, like time, or GLFW provides many kinds of input. While some can only be polled, like time, or
only received via callbacks, like scrolling, there are those that provide both only received via callbacks, like scrolling, there are those that provide both
@ -32,8 +33,10 @@ information.
GLFW needs to communicate regularly with the window system both in order to GLFW needs to communicate regularly with the window system both in order to
receive events and to show that the application hasn't locked up. Event receive events and to show that the application hasn't locked up. Event
processing must be done regularly while you have visible windows and is normally processing must be done regularly while you have any windows and is normally
done each frame after [buffer swapping](@ref buffer_swap). done each frame after [buffer swapping](@ref buffer_swap). Even when you have
no windows, event polling needs to be done in order to receive monitor
connection events.
There are two functions for processing pending events. @ref glfwPollEvents, There are two functions for processing pending events. @ref glfwPollEvents,
processes only those events that have already been received and then returns processes only those events that have already been received and then returns
@ -57,6 +60,17 @@ processes all received events. This saves a great deal of CPU cycles and is
useful for, for example, editing tools. There must be at least one GLFW window useful for, for example, editing tools. There must be at least one GLFW window
for this function to sleep. for this function to sleep.
If you want to wait for events but have UI elements that need periodic updates,
call @ref glfwWaitEventsTimeout.
@code
glfwWaitEventsTimeout(0.7);
@endcode
It puts the thread to sleep until at least one event has been received, or until
the specified number of seconds have elapsed. It then processes any received
events.
If the main thread is sleeping in @ref glfwWaitEvents, you can wake it from If the main thread is sleeping in @ref glfwWaitEvents, you can wake it from
another thread by posting an empty event to the event queue with @ref another thread by posting an empty event to the event queue with @ref
glfwPostEmptyEvent. glfwPostEmptyEvent.
@ -224,8 +238,9 @@ position callback.
glfwSetCursorPosCallback(window, cursor_pos_callback); glfwSetCursorPosCallback(window, cursor_pos_callback);
@endcode @endcode
The callback functions receives the cursor position. On platforms that provide The callback functions receives the cursor position, measured in screen
it, the full sub-pixel cursor position is passed on. coordinates but relative to the top-left corner of the window client area. On
platforms that provide it, the full sub-pixel cursor position is passed on.
@code @code
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos) static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
@ -532,6 +547,33 @@ and make may have the same name. Only the [joystick token](@ref joysticks) is
guaranteed to be unique, and only until that joystick is disconnected. guaranteed to be unique, and only until that joystick is disconnected.
@subsection joystick_event Joystick configuration changes
If you wish to be notified when a joystick is connected or disconnected, set
a joystick callback.
@code
glfwSetJoystickCallback(joystick_callback);
@endcode
The callback function receives the ID of the joystick that has been connected
and disconnected and the event that occurred.
@code
void joystick_callback(int joy, int event)
{
if (event == GLFW_CONNECTED)
{
// The joystick was connected
}
else if (event == GLFW_DISCONNECTED)
{
// The joystick was disconnected
}
}
@endcode
@section time Time input @section time Time input
GLFW provides high-resolution time input, in seconds, with @ref glfwGetTime. GLFW provides high-resolution time input, in seconds, with @ref glfwGetTime.
@ -552,6 +594,21 @@ glfwSetTime(4.0);
This sets the timer to the specified time, in seconds. This sets the timer to the specified time, in seconds.
You can also access the raw timer value, measured in 1&nbsp;/&nbsp;frequency
seconds, with @ref glfwGetTimerValue.
@code
uint64_t value = glfwGetTimerValue();
@endcode
The frequency of the raw timer varies depending on what time sources are
available on the machine. You can query its frequency, in Hz, with @ref
glfwGetTimerFrequency.
@code
uint64_t freqency = glfwGetTimerFrequency();
@endcode
@section clipboard Clipboard input and output @section clipboard Clipboard input and output

View File

@ -1,6 +1,6 @@
/*! /*!
@page internals Internal structure @page internals_guide Internal structure
@tableofcontents @tableofcontents

View File

@ -1,18 +1,21 @@
/*! /*!
@page intro Introduction to the API @page intro_guide Introduction to the API
@tableofcontents @tableofcontents
This guide introduces the basic concepts of GLFW and describes initialization, This guide introduces the basic concepts of GLFW and describes initialization reference
error handling and API guarantees and limitations. For a broad but shallow error handling and API guarantees and limitations. For a broad but shallow
tutorial, see @ref quick instead. There are also guides for the other areas of tutorial, see @ref quick_guide instead. For details on a specific function, see the
GLFW. [reference documentation](@ref init).
- @ref window There are also guides for the other areas of GLFW.
- @ref context
- @ref monitor - @ref window_guide
- @ref input - @ref context_guide
- @ref vulkan_guide
- @ref monitor_guide
- @ref input_guide
@section intro_init Initialization and termination @section intro_init Initialization and termination
@ -194,6 +197,7 @@ function:
- @ref glfwDestroyCursor - @ref glfwDestroyCursor
- @ref glfwPollEvents - @ref glfwPollEvents
- @ref glfwWaitEvents - @ref glfwWaitEvents
- @ref glfwWaitEventsTimeout
- @ref glfwTerminate - @ref glfwTerminate
These functions may be made reentrant in future minor or patch releases, but These functions may be made reentrant in future minor or patch releases, but
@ -239,8 +243,15 @@ may be called from any thread:
- @ref glfwExtensionSupported - @ref glfwExtensionSupported
- @ref glfwGetProcAddress - @ref glfwGetProcAddress
The timer may be accessed from any thread, but this is not synchronized by GLFW. The raw timer may be queried from any thread. The following raw timer related
The following timer related functions may be called from any thread: functions may be called from any thread:
- @ref glfwGetTimerFrequency
- @ref glfwGetTimerValue
The regular timer may be queried from any thread, but this is not synchronized
by GLFW with calls to @ref glfwSetTime. The following timer related functions
may be called from any thread:
- @ref glfwGetTime - @ref glfwGetTime
@ -250,13 +261,22 @@ version related functions may be called from any thread:
- @ref glfwGetVersion - @ref glfwGetVersion
- @ref glfwGetVersionString - @ref glfwGetVersionString
Vulkan objects may be created and information queried from any thread. The
following Vulkan related functions may be called from any thread:
- @ref glfwVulkanSupported
- @ref glfwGetRequiredInstanceExtensions
- @ref glfwGetInstanceProcAddress
- @ref glfwGetPhysicalDevicePresentationSupport
- @ref glfwCreateWindowSurface
GLFW uses no synchronization objects internally except for thread-local storage GLFW uses no synchronization objects internally except for thread-local storage
to keep track of the current context for each thread. Synchronization is left to keep track of the current context for each thread. Synchronization is left
to the application. to the application.
Functions that may currently be called from any thread will always remain so, Functions that may currently be called from any thread will always remain so,
but functions that are currently limited to the main may be updated to allow but functions that are currently limited to the main thread may be updated to
calls from any thread in future releases. allow calls from any thread in future releases.
@subsection compatibility Version compatibility @subsection compatibility Version compatibility

View File

@ -11,36 +11,36 @@ for creating windows, contexts and surfaces, reading input, handling events, etc
See @ref news_32 for release highlights or the See @ref news_32 for release highlights or the
[version history](http://www.glfw.org/changelog.html) for details. [version history](http://www.glfw.org/changelog.html) for details.
@ref quick is a guide for those new to GLFW. It takes you through how to write @ref quick_guide is a guide for users new to GLFW. It takes you through how to
a small but complete program. For people coming from GLFW 2, the @ref moving write a small but complete program.
guide explains what has changed and how to update existing code to use the new
API.
There are guides for each of the various areas of the API. There are guides for each section of the API:
- @ref intro initialization, error handling and high-level design - @ref intro_guide initialization, error handling and high-level design
- @ref window creating and working with windows and framebuffers - @ref window_guide creating and working with windows and framebuffers
- @ref context working with OpenGL and OpenGL ES contexts - @ref context_guide working with OpenGL and OpenGL ES contexts
- @ref monitor enumerating and working with monitors and video modes - @ref vulkan_guide - working with Vulkan objects and extensions
- @ref input receiving events, polling and processing input - @ref monitor_guide enumerating and working with monitors and video modes
- @ref input_guide receiving events, polling and processing input
Once you have written a program, see the @ref compile and @ref build guides. Once you have written a program, see @ref compile_guide and @ref build_guide.
The [reference documentation](modules.html) provides more detailed information The [reference documentation](modules.html) provides more detailed information
about specific functions. about specific functions.
@ref moving_guide explains what has changed and how to update existing code to
use the new API.
There is a section on @ref guarantees_limitations for pointer lifetimes, There is a section on @ref guarantees_limitations for pointer lifetimes,
reentrancy, thread safety, event order and backward and forward compatibility. reentrancy, thread safety, event order and backward and forward compatibility.
The @ref vulkan guide fills in the gaps for how to use Vulkan with GLFW. @ref rift_guide fills in the gaps for how to use LibOVR with GLFW.
The @ref rift fills in the gaps for how to use LibOVR with GLFW.
The [FAQ](http://www.glfw.org/faq.html) answers many common questions about the The [FAQ](http://www.glfw.org/faq.html) answers many common questions about the
design, implementation and use of GLFW. design, implementation and use of GLFW.
Finally, the @ref compat guide explains what APIs, standards and protocols GLFW Finally, @ref compat_guide explains what APIs, standards and protocols GLFW uses
uses and what happens when they are not present on a given machine. and what happens when they are not present on a given machine.
This documentation was generated with Doxygen. The sources for it are available This documentation was generated with Doxygen. The sources for it are available
in both the [source distribution](http://www.glfw.org/download.html) and in both the [source distribution](http://www.glfw.org/download.html) and

View File

@ -1,16 +1,17 @@
/*! /*!
@page monitor Monitor guide @page monitor_guide Monitor guide
@tableofcontents @tableofcontents
This guide introduces the monitor related functions of GLFW. There are also This guide introduces the monitor related functions of GLFW. For details on
guides for the other areas of GLFW. a specific function, see the [reference documentation](@ref monitor). There are
also guides for the other areas of GLFW.
- @ref intro - @ref intro_guide
- @ref window - @ref window_guide
- @ref context - @ref context_guide
- @ref input - @ref input_guide
@section monitor_object Monitor objects @section monitor_object Monitor objects
@ -94,8 +95,9 @@ a gamma ramp.
@subsection monitor_modes Video modes @subsection monitor_modes Video modes
GLFW generally does a good job selecting a suitable video mode when you create GLFW generally does a good job selecting a suitable video mode when you create
a full screen window, but it is sometimes useful to know exactly which video a full screen window, change its video mode or or make a windowed one full
modes are supported. screen, but it is sometimes useful to know exactly which video modes are
supported.
Video modes are represented as @ref GLFWvidmode structures. You can get an Video modes are represented as @ref GLFWvidmode structures. You can get an
array of the video modes supported by a monitor with @ref glfwGetVideoModes. array of the video modes supported by a monitor with @ref glfwGetVideoModes.

View File

@ -1,6 +1,6 @@
/*! /*!
@page moving Moving from GLFW 2 to 3 @page moving_guide Moving from GLFW 2 to 3
@tableofcontents @tableofcontents
@ -130,7 +130,7 @@ GLFW 3 provides support for multiple monitors. To request a full screen mode wi
instead of passing `GLFW_FULLSCREEN` you specify which monitor you wish the instead of passing `GLFW_FULLSCREEN` you specify which monitor you wish the
window to use. The @ref glfwGetPrimaryMonitor function returns the monitor that window to use. The @ref glfwGetPrimaryMonitor function returns the monitor that
GLFW 2 would have selected, but there are many other GLFW 2 would have selected, but there are many other
[monitor functions](@ref monitor). Monitor handles are pointers to the [monitor functions](@ref monitor_guide). Monitor handles are pointers to the
[opaque](https://en.wikipedia.org/wiki/Opaque_data_type) type @ref GLFWmonitor. [opaque](https://en.wikipedia.org/wiki/Opaque_data_type) type @ref GLFWmonitor.
@par Old basic full screen @par Old basic full screen

View File

@ -26,6 +26,47 @@ Vulkan header inclusion can be selected with
[GLFW_INCLUDE_VULKAN](@ref build_macros). [GLFW_INCLUDE_VULKAN](@ref build_macros).
@subsection news_32_setwindowmonitor Window mode switching
GLFW now supports switching between windowed and full screen modes and updating
the monitor and desired resolution and refresh rate of full screen windows with
@ref glfwSetWindowMonitor.
@subsection news_32_maximize Window maxmimization support
GLFW now supports window maximization with @ref glfwMaximizeWindow and the
[GLFW_MAXIMIZED](@ref window_attribs_wnd) window hint and attribute.
@subsection news_32_icon Window icon support
GLFW now supports setting the icon of windows with @ref glfwSetWindowIcon.
@subsection news_32_focus Window input focus control
GLFW now supports giving windows input focus with @ref glfwFocusWindow.
@subsection news_32_timer Raw timer access
GLFW now supports raw timer values with @ref glfwGetTimerValue and @ref
glfwGetTimerFrequency.
@subsection news_32_waittimeout Wait for events with timeout
GLFW now supports waiting for events for a set amount of time with @ref
glfwWaitEventsTimeout.
@subsection news_32_contextapi Run-time context creation API selection
GLFW now supports selecting the context creation API at run-time with
[GLFW_CONTEXT_CREATION_API](@ref window_hints_ctx).
@section news_31 New features in 3.1 @section news_31 New features in 3.1
These are the release highlights. For a full list of changes see the These are the release highlights. For a full list of changes see the
@ -96,7 +137,7 @@ and the cursor position directly instead of returning cached data.
@subsection news_31_libovr Better interoperability with Oculus Rift @subsection news_31_libovr Better interoperability with Oculus Rift
GLFW now provides native access functions for the OS level handles corresponding GLFW now provides native access functions for the OS level handles corresponding
to monitor objects, as well as a [brief guide](@ref rift). It is also regularly to monitor objects, as well as the @ref rift_guide. It is also regularly
tested for compatibility with the latest version of LibOVR (0.4.4 on release). tested for compatibility with the latest version of LibOVR (0.4.4 on release).

View File

@ -1,6 +1,6 @@
/*! /*!
@page quick Getting started @page quick_guide Getting started
@tableofcontents @tableofcontents
@ -10,7 +10,7 @@ and exit when the user closes the window or presses _Escape_. This guide will
introduce a few of the most commonly used functions, but there are many more. introduce a few of the most commonly used functions, but there are many more.
This guide assumes no experience with earlier versions of GLFW. If you This guide assumes no experience with earlier versions of GLFW. If you
have used GLFW 2 in the past, read the @ref moving guide, as some functions have used GLFW 2 in the past, read @ref moving_guide, as some functions
behave differently in GLFW 3. behave differently in GLFW 3.
@ -346,11 +346,11 @@ This tutorial used only a few of the many functions GLFW provides. There are
guides for each of the areas covered by GLFW. Each guide will introduce all the guides for each of the areas covered by GLFW. Each guide will introduce all the
functions for that category. functions for that category.
- @ref intro - @ref intro_guide
- @ref window - @ref window_guide
- @ref context - @ref context_guide
- @ref monitor - @ref monitor_guide
- @ref input - @ref input_guide
You can access reference documentation for any GLFW function by clicking it and You can access reference documentation for any GLFW function by clicking it and
the reference for each function links to related functions and guide sections. the reference for each function links to related functions and guide sections.
@ -359,6 +359,6 @@ The tutorial ends here. Once you have written a program that uses GLFW, you
will need to compile and link it. How to do that depends on the development will need to compile and link it. How to do that depends on the development
environment you are using and is best explained by the documentation for that environment you are using and is best explained by the documentation for that
environment. To learn about the details that are specific to GLFW, see environment. To learn about the details that are specific to GLFW, see
@ref build. @ref build_guide.
*/ */

View File

@ -1,6 +1,6 @@
/*! /*!
@page rift Oculus Rift guide @page rift_guide Using GLFW with LibOVR
@tableofcontents @tableofcontents

View File

@ -1,185 +1,212 @@
/*! /*!
@page vulkan Vulkan guide @page vulkan_guide Vulkan guide
@tableofcontents @tableofcontents
This guide is intended to fill the gaps between the Vulkan documentation and the This guide is intended to fill the gaps between the [Vulkan
rest of the GLFW documentation and is not a replacement for either. documentation](https://www.khronos.org/vulkan/) and the rest of the GLFW
documentation and is not a replacement for either. It assumes some familiarity
To develop for Vulkan you should install an SDK for your platform, for example with Vulkan concepts like loaders, devices, queues and surfaces and leaves it to
the [LunarG Vulkan SDK](http://lunarg.com/vulkan-sdk/). Apart from the headers the Vulkan documentation to explain the details of Vulkan functions.
and libraries, it also provides the validation layers necessary for development.
To develop for Vulkan you should install an SDK for your platform, for example
GLFW itself does not need a Vulkan SDK to enable support for Vulkan. However, the [LunarG Vulkan SDK](https://vulkan.lunarg.com/). Apart from the headers and
any Vulkan-specific test and example programs are built only if the CMake files libraries, it also provides the validation layers necessary for development.
find the LunarG SDK.
The GLFW library does not need the Vulkan SDK to enable support for Vulkan.
However, any Vulkan-specific test and example programs are built only if the
@section vulkan_include Including the Vulkan and GLFW header files CMake files find a Vulkan SDK.
To include the Vulkan header, define `GLFW_INCLUDE_VULKAN` before including the For details on a specific function, see the
GLFW header. [reference documentation](@ref vulkan). There are also guides for the other
areas of the GLFW API.
@code
#define GLFW_INCLUDE_VULKAN - @ref intro_guide
#include <GLFW/glfw3.h> - @ref window_guide
@endcode - @ref context_guide
- @ref monitor_guide
If you want to include the Vulkan header from a custom location or use your own - @ref input_guide
custom Vulkan header then you need to include them before the GLFW header.
@code @section vulkan_include Including the Vulkan and GLFW header files
#include <custom/path/vulkan.h>
#include <GLFW/glfw3.h> To include the Vulkan header, define [GLFW_INCLUDE_VULKAN](@ref build_macros)
@endcode before including the GLFW header.
Unless a Vulkan header is included, either by the GLFW header or above it, any @code
GLFW functions that use Vulkan types will not be declared. #define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
The `VK_USE_PLATFORM_*_KHR` macros do not need to be defined for the Vulkan part @endcode
of GLFW to work.
If you want to include the Vulkan header from a custom location or use your own
custom Vulkan header then you need to include them before the GLFW header.
@section vulkan_support Querying for Vulkan support
@code
If you are loading the Vulkan loader dynamically instead of linking directly #include <path/to/vulkan.h>
against it, you can check for the availability of a loader with @ref #include <GLFW/glfw3.h>
glfwVulkanSupported. @endcode
@code Unless a Vulkan header is included, either by the GLFW header or above it, any
if (glfwVulkanSupported()) GLFW functions that take or return Vulkan types will not be declared.
{
// Vulkan is available, at least for compute The `VK_USE_PLATFORM_*_KHR` macros do not need to be defined for the Vulkan part
} of GLFW to work. Define them only if you are using these extensions directly.
@endcode
This function returns `GLFW_TRUE` if the Vulkan loader was found. This check is @section vulkan_support Querying for Vulkan support
performed by @ref glfwInit.
If you are linking directly against the Vulkan loader then you can skip this
If no loader was found, calling any other Vulkan related GLFW function will section. The canonical desktop loader library exports all Vulkan core and
generate a @ref GLFW_API_UNAVAILABLE error. Khronos extension functions, allowing them to be called directly.
If you are loading the Vulkan loader dynamically instead of linking directly
@subsection vulkan_proc Querying Vulkan function pointers against it, you can check for the availability of a loader with @ref
glfwVulkanSupported.
To load any Vulkan core or extension function from the found loader, call @ref
glfwGetInstanceProcAddress. @code
if (glfwVulkanSupported())
@code {
PFN_vkCreateDevice pfnCreateDevice = (PFN_vkCreateDevice) // Vulkan is available, at least for compute
glfwGetInstanceProcAddress(instance, "vkCreateDevice"); }
@endcode @endcode
This is equivalent to calling `vkGetInstanceProcAddr`. If that fails, the This function returns `GLFW_TRUE` if the Vulkan loader was found. This check is
function falls back to a platform-specific query of the Vulkan loader (i.e. performed by @ref glfwInit.
`dlsym` or `GetProcAddress`). If that also fails, the function returns `NULL`.
For more information about `vkGetInstanceProcAddr`, see the Vulkan If no loader was found, calling any other Vulkan related GLFW function will
documentation. generate a @ref GLFW_API_UNAVAILABLE error.
Vulkan also provides `vkGetDeviceProcAddr` for loading device-specific versions
of Vulkan function. This function can be retrieved from an instance with @ref @subsection vulkan_proc Querying Vulkan function pointers
glfwGetInstanceProcAddress.
To load any Vulkan core or extension function from the found loader, call @ref
@code glfwGetInstanceProcAddress. To load functions needed for instance creation,
PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr) pass `NULL` as the instance.
glfwGetInstanceProcAddress(instance, "vkGetDeviceProcAddr");
@endcode @code
PFN_vkCreateInstance pfnCreateInstance = (PFN_vkCreateInstance)
Device-specific functions may execute a little bit faster, due to not having to glfwGetInstanceProcAddress(NULL, "vkCreateInstance");
dispatch internally based on the device passed to them. For more information @endcode
about `vkGetDeviceProcAddr`, see the Vulkan documentation.
Once you have created an instance, you can load from it all other Vulkan core
functions and functions from any instance extensions you enabled.
@section vulkan_ext Querying required Vulkan extensions
@code
To do anything useful with Vulkan you need to create an instance. If you want PFN_vkCreateDevice pfnCreateDevice = (PFN_vkCreateDevice)
to use Vulkan to render to a window, you must enable the instance extensions glfwGetInstanceProcAddress(instance, "vkCreateDevice");
GLFW requires to create Vulkan surfaces. @endcode
To query the instance extensions required, call @ref This function in turn calls `vkGetInstanceProcAddr`. If that fails, the
glfwGetRequiredInstanceExtensions. function falls back to a platform-specific query of the Vulkan loader (i.e.
`dlsym` or `GetProcAddress`). If that also fails, the function returns `NULL`.
@code For more information about `vkGetInstanceProcAddr`, see the Vulkan
int count; documentation.
const char** extensions = glfwGetRequiredInstanceExtensions(&count);
@endcode Vulkan also provides `vkGetDeviceProcAddr` for loading device-specific versions
of Vulkan function. This function can be retrieved from an instance with @ref
These extensions must all be enabled when creating instances that are going to glfwGetInstanceProcAddress.
be passed to @ref glfwGetPhysicalDevicePresentationSupport and @ref
glfwCreateWindowSurface. The set of extensions will vary depending on platform @code
and may also vary depending on graphics drivers and other factors. PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)
glfwGetInstanceProcAddress(instance, "vkGetDeviceProcAddr");
If it fails it will return `NULL` and Vulkan window surface creation will not be @endcode
possible. You may still use Vulkan for off-screen rendering and compute work.
Device-specific functions may execute a little bit faster, due to not having to
The returned array will always contain `VK_KHR_surface`, so if you don't dispatch internally based on the device passed to them. For more information
require any additional extensions you can pass this list directly to the about `vkGetDeviceProcAddr`, see the Vulkan documentation.
`VkInstanceCreateInfo` struct.
@code @section vulkan_ext Querying required Vulkan extensions
VkInstanceCreateInfo ici;
To do anything useful with Vulkan you need to create an instance. If you want
memset(&ici, 0, sizeof(ici)); to use Vulkan to render to a window, you must enable the instance extensions
ici.enabledExtensionCount = count; GLFW requires to create Vulkan surfaces.
ici.ppEnabledExtensionNames = extensions;
... To query the instance extensions required, call @ref
@endcode glfwGetRequiredInstanceExtensions.
Additional extensions may be required by future versions of GLFW. You should @code
check whether any extensions you wish to enable are already in the returned uint32_t count;
array, as it is an error to specify an extension more than once in the const char** extensions = glfwGetRequiredInstanceExtensions(&count);
`VkInstanceCreateInfo` struct. @endcode
These extensions must all be enabled when creating instances that are going to
@section vulkan_present Querying for Vulkan presentation support be passed to @ref glfwGetPhysicalDevicePresentationSupport and @ref
glfwCreateWindowSurface. The set of extensions will vary depending on platform
Not every Vulkan queue family of every device can present images to surfaces. and may also vary depending on graphics drivers and other factors.
To check whether a specific queue family of a physical device supports image
presentation without first having to create a window and surface, call @ref If it fails it will return `NULL` and GLFW will not be able to create Vulkan
glfwGetPhysicalDevicePresentationSupport. window surfaces. You can still use Vulkan for off-screen rendering and compute
work.
@code
if (glfwGetPhysicalDevicePresentationSupport(instance, physical_device, queue_family_index)) The returned array will always contain `VK_KHR_surface`, so if you don't
{ require any additional extensions you can pass this list directly to the
// Queue family supports image presentation `VkInstanceCreateInfo` struct.
}
@endcode @code
VkInstanceCreateInfo ici;
The `VK_KHR_surface` extension also provides the
`vkGetPhysicalDeviceSurfaceSupportKHR` function, which performs the same test on memset(&ici, 0, sizeof(ici));
an existing Vulkan surface. ici.enabledExtensionCount = count;
ici.ppEnabledExtensionNames = extensions;
...
@section vulkan_window Creating the window @endcode
Unless you will be using OpenGL or OpenGL ES in addition to Vulkan, there is no Additional extensions may be required by future versions of GLFW. You should
need to create a context for that window. You can disable context creation by check whether any extensions you wish to enable are already in the returned
setting the [GLFW_CLIENT_API](@ref window_hints_ctx) hint to `GLFW_NO_API`. array, as it is an error to specify an extension more than once in the
`VkInstanceCreateInfo` struct.
@code
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(640, 480, "Window Title", NULL, NULL); @section vulkan_present Querying for Vulkan presentation support
@endcode
Not every queue family of every Vulkan device can present images to surfaces.
See @ref context_less for more information. To check whether a specific queue family of a physical device supports image
presentation without first having to create a window and surface, call @ref
glfwGetPhysicalDevicePresentationSupport.
@section vulkan_surface Creating a Vulkan window surface
@code
You can create a Vulkan surface (as defined by the `VK_KHR_surface` extension) if (glfwGetPhysicalDevicePresentationSupport(instance, physical_device, queue_family_index))
for a GLFW window with @ref glfwCreateWindowSurface. {
// Queue family supports image presentation
@code }
VkSurfaceKHR surface; @endcode
VkResult err = glfwCreateWindowSurface(instance, window, NULL, &surface);
if (err) The `VK_KHR_surface` extension additionally provides the
{ `vkGetPhysicalDeviceSurfaceSupportKHR` function, which performs the same test on
// Window surface creation failed an existing Vulkan surface.
}
@endcode
@section vulkan_window Creating the window
It is your responsibility to destroy the surface. GLFW does not destroy it for
you. Call `vkDestroySurfaceKHR` function from the same extension to destroy it. Unless you will be using OpenGL or OpenGL ES with the same window as Vulkan,
there is no need to create a context. You can disable context creation with the
*/ [GLFW_CLIENT_API](@ref window_hints_ctx) hint.
@code
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(640, 480, "Window Title", NULL, NULL);
@endcode
See @ref context_less for more information.
@section vulkan_surface Creating a Vulkan window surface
You can create a Vulkan surface (as defined by the `VK_KHR_surface` extension)
for a GLFW window with @ref glfwCreateWindowSurface.
@code
VkSurfaceKHR surface;
VkResult err = glfwCreateWindowSurface(instance, window, NULL, &surface);
if (err)
{
// Window surface creation failed
}
@endcode
It is your responsibility to destroy the surface. GLFW does not destroy it for
you. Call `vkDestroySurfaceKHR` function from the same extension to destroy it.
*/

View File

@ -1,16 +1,17 @@
/*! /*!
@page window Window guide @page window_guide Window guide
@tableofcontents @tableofcontents
This guide introduces the window related functions of GLFW. There are also This guide introduces the window related functions of GLFW. For details on
guides for the other areas of GLFW. a specific function, see the [reference documentation](@ref window). There are
also guides for the other areas of GLFW.
- @ref intro - @ref intro_guide
- @ref context - @ref context_guide
- @ref monitor - @ref monitor_guide
- @ref input - @ref input_guide
@section window_object Window objects @section window_object Window objects
@ -55,6 +56,10 @@ GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", glfwGetPrimaryMonito
Full screen windows cover the entire display area of a monitor, have no border Full screen windows cover the entire display area of a monitor, have no border
or decorations. or decorations.
Windowed mode windows can be made full screen by setting a monitor with @ref
glfwSetWindowMonitor, and full screen ones can be made windowed by unsetting it
with the same function.
Each field of the @ref GLFWvidmode structure corresponds to a function parameter Each field of the @ref GLFWvidmode structure corresponds to a function parameter
or window hint and combine to form the _desired video mode_ for that window. or window hint and combine to form the _desired video mode_ for that window.
The supported video mode most closely matching the desired video mode will be The supported video mode most closely matching the desired video mode will be
@ -70,9 +75,11 @@ GLFWvidmode.greenBits | `GLFW_GREEN_BITS` hint
GLFWvidmode.blueBits | `GLFW_BLUE_BITS` hint GLFWvidmode.blueBits | `GLFW_BLUE_BITS` hint
GLFWvidmode.refreshRate | `GLFW_REFRESH_RATE` hint GLFWvidmode.refreshRate | `GLFW_REFRESH_RATE` hint
Once you have a full screen window, you can change its resolution with @ref Once you have a full screen window, you can change its resolution, refresh rate
glfwSetWindowSize. The new video mode will be selected and set the same way as and monitor with @ref glfwSetWindowMonitor. If you just need change its
the video mode chosen by @ref glfwCreateWindow. resolution you can also call @ref glfwSetWindowSize. In all cases, the new
video mode will be selected the same way as the video mode chosen by @ref
glfwCreateWindow.
By default, the original video mode of the monitor will be restored and the By default, the original video mode of the monitor will be restored and the
window iconified if it loses input focus, to allow the user to switch back to window iconified if it loses input focus, to allow the user to switch back to
@ -100,6 +107,18 @@ glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
GLFWwindow* window = glfwCreateWindow(mode->width, mode->height, "My Title", monitor, NULL); GLFWwindow* window = glfwCreateWindow(mode->width, mode->height, "My Title", monitor, NULL);
@endcode @endcode
This also works for windowed mode windows that are made full screen.
@code
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
@endcode
Note that @ref glfwGetVideoMode returns the _current_ video mode of a monitor,
so if you already have a full screen window on that monitor that you want to
make windowed full screen, you need to have saved the desktop resolution before.
@subsection window_destruction Window destruction @subsection window_destruction Window destruction
@ -140,6 +159,7 @@ The following hints are always hard constraints:
- `GLFW_STEREO` - `GLFW_STEREO`
- `GLFW_DOUBLEBUFFER` - `GLFW_DOUBLEBUFFER`
- `GLFW_CLIENT_API` - `GLFW_CLIENT_API`
- `GLFW_CONTEXT_CREATION_API`
The following additional hints are hard constraints when requesting an OpenGL The following additional hints are hard constraints when requesting an OpenGL
context, but are ignored when requesting an OpenGL ES context: context, but are ignored when requesting an OpenGL ES context:
@ -174,6 +194,9 @@ above other regular windows, also called topmost or always-on-top. This is
intended primarily for debugging purposes and cannot be used to implement proper intended primarily for debugging purposes and cannot be used to implement proper
full screen windows. This hint is ignored for full screen windows. full screen windows. This hint is ignored for full screen windows.
`GLFW_MAXIMIZED` specifies whether the windowed mode window will be maximized
when created. This hint is ignored for full screen windows.
@subsubsection window_hints_fb Framebuffer related hints @subsubsection window_hints_fb Framebuffer related hints
@ -206,8 +229,9 @@ Zero disables multisampling. `GLFW_DONT_CARE` means the application has no
preference. preference.
`GLFW_SRGB_CAPABLE` specifies whether the framebuffer should be sRGB capable. `GLFW_SRGB_CAPABLE` specifies whether the framebuffer should be sRGB capable.
If supported, the created context will provide `GL_ARB_framebuffer_sRGB` or If supported, a created OpenGL context will support the `GL_FRAMEBUFFER_SRGB`
`GL_EXT_framebuffer_sRGB`. enable, also called `GL_FRAMEBUFFER_SRGB_EXT`) for controlling sRGB rendering
and a created OpenGL ES context will always have sRGB rendering enabled.
`GLFW_DOUBLEBUFFER` specifies whether the framebuffer should be double buffered. `GLFW_DOUBLEBUFFER` specifies whether the framebuffer should be double buffered.
You nearly always want to use double buffering. This is a hard constraint. You nearly always want to use double buffering. This is a hard constraint.
@ -226,6 +250,24 @@ This hint is ignored for windowed mode windows.
Possible values are `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` and `GLFW_NO_API`. Possible values are `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` and `GLFW_NO_API`.
This is a hard constraint. This is a hard constraint.
`GLFW_CONTEXT_CREATION_API` specifies which context creation API to use to
create the context. Possible values are `GLFW_NATIVE_CONTEXT_API` and
`GLFW_EGL_CONTEXT_API`. This is a hard constraint. If no client API is
requested, this hint is ignored.
@par
__OS X:__ The EGL API is not available on this platform and requests to use it
will fail.
@par
__Wayland, Mir:__ The EGL API _is_ the native context creation API, so this hint
will have no effect.
@note An OpenGL extension loader library that assumes it knows which context
creation API is used on a given platform may fail if you change this hint. This
can be resolved by having it load via @ref glfwGetProcAddress, which always uses
the selected API.
`GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR` specify the client `GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR` specify the client
API version that the created context must be compatible with. The exact API version that the created context must be compatible with. The exact
behavior of these hints depend on the requested client API. behavior of these hints depend on the requested client API.
@ -321,6 +363,7 @@ Window hint | Default value | Supported values
`GLFW_FOCUSED` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` `GLFW_FOCUSED` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_AUTO_ICONIFY` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` `GLFW_AUTO_ICONIFY` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_FLOATING` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` `GLFW_FLOATING` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_MAXIMIZED` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_RED_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` `GLFW_RED_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_GREEN_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` `GLFW_GREEN_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_BLUE_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` `GLFW_BLUE_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
@ -338,6 +381,7 @@ Window hint | Default value | Supported values
`GLFW_SRGB_CAPABLE` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` `GLFW_SRGB_CAPABLE` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_DOUBLEBUFFER` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` `GLFW_DOUBLEBUFFER` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_CLIENT_API` | `GLFW_OPENGL_API` | `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API` `GLFW_CLIENT_API` | `GLFW_OPENGL_API` | `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`
`GLFW_CONTEXT_CREATION_API` | `GLFW_NATIVE_CONTEXT_API` | `GLFW_NATIVE_CONTEXT_API` or `GLFW_EGL_CONTEXT_API`
`GLFW_CONTEXT_VERSION_MAJOR` | 1 | Any valid major version number of the chosen client API `GLFW_CONTEXT_VERSION_MAJOR` | 1 | Any valid major version number of the chosen client API
`GLFW_CONTEXT_VERSION_MINOR` | 0 | Any valid minor version number of the chosen client API `GLFW_CONTEXT_VERSION_MINOR` | 0 | Any valid minor version number of the chosen client API
`GLFW_CONTEXT_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS`, `GLFW_NO_RESET_NOTIFICATION` or `GLFW_LOSE_CONTEXT_ON_RESET` `GLFW_CONTEXT_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS`, `GLFW_NO_RESET_NOTIFICATION` or `GLFW_LOSE_CONTEXT_ON_RESET`
@ -417,7 +461,7 @@ glfwSetWindowSize(window, 640, 480);
@endcode @endcode
For full screen windows, the specified size becomes the new resolution of the For full screen windows, the specified size becomes the new resolution of the
window's *desired video mode*. The video mode most closely matching the new window's desired video mode. The video mode most closely matching the new
desired video mode is set immediately. The window is resized to fit the desired video mode is set immediately. The window is resized to fit the
resolution of the set video mode. resolution of the set video mode.
@ -611,6 +655,26 @@ glfwSetWindowTitle(window, u8"This is always a UTF-8 string");
@endcode @endcode
@subsection window_icon Window icon
Decorated windows have icons on some platforms. You can set this icon by
specifying a list of candidate images with @ref glfwSetWindowIcon.
@code
GLFWimage images[2];
images[0] = load_icon("my_icon.png");
images[1] = load_icon("my_icon_small.png");
glfwSetWindowIcon(window, 2, images);
@endcode
To revert to the default window icon, pass in an empty image array.
@code
glfwSetWindowIcon(window, 0, NULL);
@endcode
@subsection window_monitor Window monitor @subsection window_monitor Window monitor
Full screen windows are associated with a specific monitor. You can get the Full screen windows are associated with a specific monitor. You can get the
@ -622,8 +686,31 @@ GLFWmonitor* monitor = glfwGetWindowMonitor(window);
This monitor handle is one of those returned by @ref glfwGetMonitors. This monitor handle is one of those returned by @ref glfwGetMonitors.
For windowed mode windows, this function returns `NULL`. This is the For windowed mode windows, this function returns `NULL`. This is how to tell
recommended way to tell full screen windows from windowed mode windows. full screen windows from windowed mode windows.
You can move windows between monitors or between full screen and windowed mode
with @ref glfwSetWindowMonitor. When making a window full screen on the same or
on a different monitor, specify the desired monitor, resolution and refresh
rate. The position arguments are ignored.
@code
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
@endcode
When making the window windowed, specify the desired position and size. The
refresh rate argument is ignored.
@code
glfwSetWindowMonitor(window, NULL, xpos, ypos, width, height, 0);
@endcode
This restores any previous window settings such as whether it is decorated,
floating, resizable, has size or aspect ratio limits, etc.. To restore a window
that was originally windowed to its original size and position, save these
before making it full screen and then pass them in as above.
@subsection window_iconify Window iconification @subsection window_iconify Window iconification
@ -709,6 +796,13 @@ int visible = glfwGetWindowAttrib(window, GLFW_VISIBLE);
@subsection window_focus Window input focus @subsection window_focus Window input focus
Windows can be given input focus and brought to the front with @ref
glfwFocusWindow.
@code
glfwFocusWindow(window);
@endcode
If you wish to be notified when a window gains or loses input focus, whether by If you wish to be notified when a window gains or loses input focus, whether by
the user, system or your own code, set a focus callback. the user, system or your own code, set a focus callback.
@ -789,6 +883,9 @@ same name.
`GLFW_ICONIFIED` indicates whether the specified window is iconified, whether by `GLFW_ICONIFIED` indicates whether the specified window is iconified, whether by
the user or with @ref glfwIconifyWindow. the user or with @ref glfwIconifyWindow.
`GLFW_MAXIMIZED` indicates whether the specified window is maximized, whether by
the user or with @ref glfwMaximizeWindow.
`GLFW_VISIBLE` indicates whether the specified window is visible. Window `GLFW_VISIBLE` indicates whether the specified window is visible. Window
visibility can be controlled with @ref glfwShowWindow and @ref glfwHideWindow visibility can be controlled with @ref glfwShowWindow and @ref glfwHideWindow
and initial visibility is controlled by the [window hint](@ref window_hints_wnd) and initial visibility is controlled by the [window hint](@ref window_hints_wnd)
@ -812,6 +909,10 @@ topmost or always-on-top. This is controlled by the
`GLFW_CLIENT_API` indicates the client API provided by the window's context; `GLFW_CLIENT_API` indicates the client API provided by the window's context;
either `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`. either `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`.
`GLFW_CONTEXT_CREATION_API` indicates the context creation API used to create
the window's context; either `GLFW_NATIVE_CONTEXT_API` or
`GLFW_EGL_CONTEXT_API`.
`GLFW_CONTEXT_VERSION_MAJOR`, `GLFW_CONTEXT_VERSION_MINOR` and `GLFW_CONTEXT_VERSION_MAJOR`, `GLFW_CONTEXT_VERSION_MINOR` and
`GLFW_CONTEXT_REVISION` indicate the client API version of the window's context. `GLFW_CONTEXT_REVISION` indicate the client API version of the window's context.
@ -835,9 +936,9 @@ window's context supports robustness, or `GLFW_NO_ROBUSTNESS` otherwise.
@subsubsection window_attribs_fb Framebuffer related attributes @subsubsection window_attribs_fb Framebuffer related attributes
The attributes of the default framebuffer (i.e. the framebuffer attached to the GLFW does not expose attributes of the default framebuffer (i.e. the framebuffer
window) are not provided by this function but can be queried with both OpenGL attached to the window) as these can be queried directly with either OpenGL,
and OpenGL ES. OpenGL ES or Vulkan.
If you are using version 3.0 or later of OpenGL or OpenGL ES, the If you are using version 3.0 or later of OpenGL or OpenGL ES, the
`glGetFramebufferAttachmentParameteriv` function can be used to retrieve the `glGetFramebufferAttachmentParameteriv` function can be used to retrieve the
@ -859,8 +960,8 @@ Stencil bits | `GL_STENCIL_BITS` | `GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE`
MSAA samples | `GL_SAMPLES` | _Not provided by this function_ MSAA samples | `GL_SAMPLES` | _Not provided by this function_
When calling `glGetFramebufferAttachmentParameteriv`, the red, green, blue and When calling `glGetFramebufferAttachmentParameteriv`, the red, green, blue and
alpha sizes can be queried from the `GL_BACK_LEFT`, while the depth and stencil alpha sizes are queried from the `GL_BACK_LEFT`, while the depth and stencil
sizes can be queried from the `GL_DEPTH` and `GL_STENCIL` attachments, sizes are queried from the `GL_DEPTH` and `GL_STENCIL` attachments,
respectively. respectively.

View File

@ -89,6 +89,7 @@ typedef enum { DRAW_BALL, DRAW_BALL_SHADOW } DRAW_BALL_ENUM;
typedef struct {float x; float y; float z;} vertex_t; typedef struct {float x; float y; float z;} vertex_t;
/* Global vars */ /* Global vars */
int windowed_xpos, windowed_ypos, windowed_width, windowed_height;
int width, height; int width, height;
GLfloat deg_rot_y = 0.f; GLfloat deg_rot_y = 0.f;
GLfloat deg_rot_y_inc = 2.f; GLfloat deg_rot_y_inc = 2.f;
@ -236,8 +237,32 @@ void reshape( GLFWwindow* window, int w, int h )
void key_callback( GLFWwindow* window, int key, int scancode, int action, int mods ) void key_callback( GLFWwindow* window, int key, int scancode, int action, int mods )
{ {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) if (action != GLFW_PRESS)
return;
if (key == GLFW_KEY_ESCAPE && mods == 0)
glfwSetWindowShouldClose(window, GLFW_TRUE); glfwSetWindowShouldClose(window, GLFW_TRUE);
if ((key == GLFW_KEY_ENTER && mods == GLFW_MOD_ALT) ||
(key == GLFW_KEY_F11 && mods == GLFW_MOD_ALT))
{
if (glfwGetWindowMonitor(window))
{
glfwSetWindowMonitor(window, NULL,
windowed_xpos, windowed_ypos,
windowed_width, windowed_height, 0);
}
else
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
if (monitor)
{
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwGetWindowPos(window, &windowed_xpos, &windowed_ypos);
glfwGetWindowSize(window, &windowed_width, &windowed_height);
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
}
}
}
} }
static void set_ball_pos ( GLfloat x, GLfloat y ) static void set_ball_pos ( GLfloat x, GLfloat y )
@ -602,8 +627,6 @@ int main( void )
if( !glfwInit() ) if( !glfwInit() )
exit( EXIT_FAILURE ); exit( EXIT_FAILURE );
glfwWindowHint(GLFW_DEPTH_BITS, 16);
window = glfwCreateWindow( 400, 400, "Boing (classic Amiga demo)", NULL, NULL ); window = glfwCreateWindow( 400, 400, "Boing (classic Amiga demo)", NULL, NULL );
if (!window) if (!window)
{ {

View File

@ -46,37 +46,37 @@ extern "C" {
* *
* For more information about how to use this file, see @ref build_include. * For more information about how to use this file, see @ref build_include.
*/ */
/*! @defgroup context Context handling /*! @defgroup context Context reference
* *
* This is the reference documentation for context related functions. For more * This is the reference documentation for OpenGL and OpenGL ES context related
* information, see the @ref context. * functions. For more task-oriented information, see the @ref context_guide.
*/ */
/*! @defgroup vulkan Vulkan support /*! @defgroup vulkan Vulkan reference
* *
* This is the reference documentation for Vulkan related functions. For more * This is the reference documentation for Vulkan related functions and types.
* information, see the @ref vulkan. * For more task-oriented information, see the @ref vulkan_guide.
*/ */
/*! @defgroup init Initialization, version and errors /*! @defgroup init Initialization, version and error reference
* *
* This is the reference documentation for initialization and termination of * This is the reference documentation for initialization and termination of
* the library, version management and error handling. For more information, * the library, version management and error handling. For more task-oriented
* see the @ref intro. * information, see the @ref intro_guide.
*/ */
/*! @defgroup input Input handling /*! @defgroup input Input reference
* *
* This is the reference documentation for input related functions and types. * This is the reference documentation for input related functions and types.
* For more information, see the @ref input. * For more task-oriented information, see the @ref input_guide.
*/ */
/*! @defgroup monitor Monitor handling /*! @defgroup monitor Monitor reference
* *
* This is the reference documentation for monitor related functions and types. * This is the reference documentation for monitor related functions and types.
* For more information, see the @ref monitor. * For more task-oriented information, see the @ref monitor_guide.
*/ */
/*! @defgroup window Window handling /*! @defgroup window Window reference
* *
* This is the reference documentation for window related functions and types, * This is the reference documentation for window related functions and types,
* including creation, deletion and event polling. For more information, see * including creation, deletion and event polling. For more task-oriented
* the @ref window. * information, see the @ref window_guide.
*/ */
@ -117,14 +117,14 @@ extern "C" {
/* Most Windows GLU headers need wchar_t. /* Most Windows GLU headers need wchar_t.
* The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h.
* Include it unconditionally to avoid surprising side-effects.
*/ */
#if !defined(GLFW_INCLUDE_NONE) #include <stddef.h>
#include <stddef.h> #include <stdint.h>
#endif
/* Include the chosen client API headers. /* Include the chosen client API headers.
*/ */
#if defined(__APPLE_CC__) #if defined(__APPLE__)
#if defined(GLFW_INCLUDE_GLCOREARB) #if defined(GLFW_INCLUDE_GLCOREARB)
#include <OpenGL/gl3.h> #include <OpenGL/gl3.h>
#if defined(GLFW_INCLUDE_GLEXT) #if defined(GLFW_INCLUDE_GLEXT)
@ -626,6 +626,7 @@ extern "C" {
#define GLFW_DECORATED 0x00020005 #define GLFW_DECORATED 0x00020005
#define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_AUTO_ICONIFY 0x00020006
#define GLFW_FLOATING 0x00020007 #define GLFW_FLOATING 0x00020007
#define GLFW_MAXIMIZED 0x00020008
#define GLFW_RED_BITS 0x00021001 #define GLFW_RED_BITS 0x00021001
#define GLFW_GREEN_BITS 0x00021002 #define GLFW_GREEN_BITS 0x00021002
@ -655,6 +656,7 @@ extern "C" {
#define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_OPENGL_PROFILE 0x00022008
#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009
#define GLFW_CONTEXT_NO_ERROR 0x0002200A #define GLFW_CONTEXT_NO_ERROR 0x0002200A
#define GLFW_CONTEXT_CREATION_API 0x0002200B
#define GLFW_NO_API 0 #define GLFW_NO_API 0
#define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_API 0x00030001
@ -680,6 +682,9 @@ extern "C" {
#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001 #define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001
#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002 #define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002
#define GLFW_NATIVE_CONTEXT_API 0x00036001
#define GLFW_EGL_CONTEXT_API 0x00036002
/*! @defgroup shapes Standard cursor shapes /*! @defgroup shapes Standard cursor shapes
* *
* See [standard cursor creation](@ref cursor_standard) for how these are used. * See [standard cursor creation](@ref cursor_standard) for how these are used.
@ -957,8 +962,10 @@ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int);
* This is the function signature for cursor position callback functions. * This is the function signature for cursor position callback functions.
* *
* @param[in] window The window that received the event. * @param[in] window The window that received the event.
* @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. * @param[in] xpos The new cursor x-coordinate, relative to the left edge of
* @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. * the client area.
* @param[in] ypos The new cursor y-coordinate, relative to the top edge of the
* client area.
* *
* @sa @ref cursor_pos * @sa @ref cursor_pos
* @sa glfwSetCursorPosCallback * @sa glfwSetCursorPosCallback
@ -1095,6 +1102,23 @@ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**);
*/ */
typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);
/*! @brief The function signature for joystick configuration callbacks.
*
* This is the function signature for joystick configuration callback
* functions.
*
* @param[in] joy The joystick that was connected or disconnected.
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
*
* @sa @ref joystick_event
* @sa glfwSetJoystickCallback
*
* @since Added in version 3.2.
*
* @ingroup input
*/
typedef void (* GLFWjoystickfun)(int,int);
/*! @brief Video mode type. /*! @brief Video mode type.
* *
* This describes a single video mode. * This describes a single video mode.
@ -1704,17 +1728,17 @@ GLFWAPI void glfwWindowHint(int hint, int value);
* glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize.
* *
* To create a full screen window, you need to specify the monitor the window * To create a full screen window, you need to specify the monitor the window
* will cover. If no monitor is specified, windowed mode will be used. Unless * will cover. If no monitor is specified, the window will be windowed mode.
* you have a way for the user to choose a specific monitor, it is recommended * Unless you have a way for the user to choose a specific monitor, it is
* that you pick the primary monitor. For more information on how to query * recommended that you pick the primary monitor. For more information on how
* connected monitors, see @ref monitor_monitors. * to query connected monitors, see @ref monitor_monitors.
* *
* For full screen windows, the specified size becomes the resolution of the * For full screen windows, the specified size becomes the resolution of the
* window's _desired video mode_. As long as a full screen window has input * window's _desired video mode_. As long as a full screen window is not
* focus, the supported video mode most closely matching the desired video mode * iconified, the supported video mode most closely matching the desired video
* is set for the specified monitor. For more information about full screen * mode is set for the specified monitor. For more information about full
* windows, including the creation of so called _windowed full screen_ or * screen windows, including the creation of so called _windowed full screen_
* _borderless full screen_ windows, see @ref window_windowed_full_screen. * or _borderless full screen_ windows, see @ref window_windowed_full_screen.
* *
* By default, newly created windows use the placement recommended by the * By default, newly created windows use the placement recommended by the
* window system. To create the window at a specific position, make it * window system. To create the window at a specific position, make it
@ -1722,8 +1746,8 @@ GLFWAPI void glfwWindowHint(int hint, int value);
* hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * hint, set its [position](@ref window_pos) and then [show](@ref window_hide)
* it. * it.
* *
* If a full screen window has input focus, the screensaver is prohibited from * As long as at least one full screen window is not iconified, the screensaver
* starting. * is prohibited from starting.
* *
* Window systems put limits on window sizes. Very large or very small window * Window systems put limits on window sizes. Very large or very small window
* dimensions may be overridden by the window system on creation. Check the * dimensions may be overridden by the window system on creation. Check the
@ -1737,7 +1761,7 @@ GLFWAPI void glfwWindowHint(int hint, int value);
* @param[in] height The desired height, in screen coordinates, of the window. * @param[in] height The desired height, in screen coordinates, of the window.
* This must be greater than zero. * This must be greater than zero.
* @param[in] title The initial, UTF-8 encoded window title. * @param[in] title The initial, UTF-8 encoded window title.
* @param[in] monitor The monitor to use for full screen mode, or `NULL` to use * @param[in] monitor The monitor to use for full screen mode, or `NULL` for
* windowed mode. * windowed mode.
* @param[in] share The window whose context to share resources with, or `NULL` * @param[in] share The window whose context to share resources with, or `NULL`
* to not share resources. * to not share resources.
@ -1899,6 +1923,45 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value);
*/ */
GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
/*! @brief Sets the icon for the specified window.
*
* This function sets the icon of the specified window. If passed an array of
* candidate images, those of or closest to the sizes desired by the system are
* selected. If no images are specified, the window reverts to its default
* icon.
*
* The desired image sizes varies depending on platform and system settings.
* The selected images will be rescaled as needed. Good sizes include 16x16,
* 32x32 and 48x48.
*
* @param[in] window The window whose icon to set.
* @param[in] count The number of images in the specified array, or zero to
* revert to the default window icon.
* @param[in] images The images to create the icon from. This is ignored if
* count is zero.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @pointer_lifetime The specified image data is copied before this function
* returns.
*
* @remark @osx The GLFW window has no icon, as it is not a document
* window, but the dock icon will be the same as the application bundle's icon.
* For more information on bundles, see the
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
* in the Mac Developer Library.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_icon
*
* @since Added in version 3.2.
*
* @ingroup window
*/
GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images);
/*! @brief Retrieves the position of the client area of the specified window. /*! @brief Retrieves the position of the client area of the specified window.
* *
* This function retrieves the position, in screen coordinates, of the * This function retrieves the position, in screen coordinates, of the
@ -1991,11 +2054,15 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
/*! @brief Sets the size limits of the specified window. /*! @brief Sets the size limits of the specified window.
* *
* This function sets the size limits of the client area of the specified * This function sets the size limits of the client area of the specified
* window. If the window is full screen or not resizable, this function does * window. If the window is full screen, the size limits only take effect
* nothing. * once it is made windowed. If the window is not resizable, this function
* does nothing.
* *
* The size limits are applied immediately and may cause the window to be * The size limits are applied immediately to a windowed mode window and may
* resized. * cause it to be resized.
*
* The maximum dimensions must be greater than or equal to the minimum
* dimensions and all must be greater than or equal to zero.
* *
* @param[in] window The window to set limits for. * @param[in] window The window to set limits for.
* @param[in] minwidth The minimum width, in screen coordinates, of the client * @param[in] minwidth The minimum width, in screen coordinates, of the client
@ -2007,8 +2074,8 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
* @param[in] maxheight The maximum height, in screen coordinates, of the * @param[in] maxheight The maximum height, in screen coordinates, of the
* client area, or `GLFW_DONT_CARE`. * client area, or `GLFW_DONT_CARE`.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR. * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
* *
* @remark If you set size limits and an aspect ratio that conflict, the * @remark If you set size limits and an aspect ratio that conflict, the
* results are undefined. * results are undefined.
@ -2027,7 +2094,8 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minhe
/*! @brief Sets the aspect ratio of the specified window. /*! @brief Sets the aspect ratio of the specified window.
* *
* This function sets the required aspect ratio of the client area of the * This function sets the required aspect ratio of the client area of the
* specified window. If the window is full screen or not resizable, this * specified window. If the window is full screen, the aspect ratio only takes
* effect once it is made windowed. If the window is not resizable, this
* function does nothing. * function does nothing.
* *
* The aspect ratio is specified as a numerator and a denominator and both * The aspect ratio is specified as a numerator and a denominator and both
@ -2037,8 +2105,8 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minhe
* If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect
* ratio limit is disabled. * ratio limit is disabled.
* *
* The aspect ratio is applied immediately and may cause the window to be * The aspect ratio is applied immediately to a windowed mode window and may
* resized. * cause it to be resized.
* *
* @param[in] window The window to set limits for. * @param[in] window The window to set limits for.
* @param[in] numer The numerator of the desired aspect ratio, or * @param[in] numer The numerator of the desired aspect ratio, or
@ -2068,17 +2136,22 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
* This function sets the size, in screen coordinates, of the client area of * This function sets the size, in screen coordinates, of the client area of
* the specified window. * the specified window.
* *
* For full screen windows, this function selects and switches to the resolution * For full screen windows, this function updates the resolution of its desired
* closest to the specified size, without affecting the window's context. As * video mode and switches to the video mode closest to it, without affecting
* the context is unaffected, the bit depths of the framebuffer remain * the window's context. As the context is unaffected, the bit depths of the
* unchanged. * framebuffer remain unchanged.
*
* If you wish to update the refresh rate of the desired video mode in addition
* to its resolution, see @ref glfwSetWindowMonitor.
* *
* The window manager may put limits on what sizes are allowed. GLFW cannot * The window manager may put limits on what sizes are allowed. GLFW cannot
* and should not override these limits. * and should not override these limits.
* *
* @param[in] window The window to resize. * @param[in] window The window to resize.
* @param[in] width The desired width of the specified window. * @param[in] width The desired width, in screen coordinates, of the window
* @param[in] height The desired height of the specified window. * client area.
* @param[in] height The desired height, in screen coordinates, of the window
* client area.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
@ -2087,6 +2160,7 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
* *
* @sa @ref window_size * @sa @ref window_size
* @sa glfwGetWindowSize * @sa glfwGetWindowSize
* @sa glfwSetWindowMonitor
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * @glfw3 Added window handle parameter.
@ -2179,6 +2253,7 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int
* *
* @sa @ref window_iconify * @sa @ref window_iconify
* @sa glfwRestoreWindow * @sa glfwRestoreWindow
* @sa glfwMaximizeWindow
* *
* @since Added in version 2.1. * @since Added in version 2.1.
* @glfw3 Added window handle parameter. * @glfw3 Added window handle parameter.
@ -2190,7 +2265,8 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
/*! @brief Restores the specified window. /*! @brief Restores the specified window.
* *
* This function restores the specified window if it was previously iconified * This function restores the specified window if it was previously iconified
* (minimized). If the window is already restored, this function does nothing. * (minimized) or maximized. If the window is already restored, this function
* does nothing.
* *
* If the specified window is a full screen window, the resolution chosen for * If the specified window is a full screen window, the resolution chosen for
* the window is restored on the selected monitor. * the window is restored on the selected monitor.
@ -2204,6 +2280,7 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
* *
* @sa @ref window_iconify * @sa @ref window_iconify
* @sa glfwIconifyWindow * @sa glfwIconifyWindow
* @sa glfwMaximizeWindow
* *
* @since Added in version 2.1. * @since Added in version 2.1.
* @glfw3 Added window handle parameter. * @glfw3 Added window handle parameter.
@ -2212,6 +2289,28 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
*/ */
GLFWAPI void glfwRestoreWindow(GLFWwindow* window); GLFWAPI void glfwRestoreWindow(GLFWwindow* window);
/*! @brief Maximizes the specified window.
*
* This function maximizes the specified window if it was previously not
* maximized. If the window is already maximized, this function does nothing.
*
* If the specified window is a full screen window, this function does nothing.
*
* @param[in] window The window to maximize.
*
* @par Thread Safety
* This function may only be called from the main thread.
*
* @sa @ref window_iconify
* @sa glfwIconifyWindow
* @sa glfwRestoreWindow
*
* @since Added in GLFW 3.2.
*
* @ingroup window
*/
GLFWAPI void glfwMaximizeWindow(GLFWwindow* window);
/*! @brief Makes the specified window visible. /*! @brief Makes the specified window visible.
* *
* This function makes the specified window visible if it was previously * This function makes the specified window visible if it was previously
@ -2256,6 +2355,34 @@ GLFWAPI void glfwShowWindow(GLFWwindow* window);
*/ */
GLFWAPI void glfwHideWindow(GLFWwindow* window); GLFWAPI void glfwHideWindow(GLFWwindow* window);
/*! @brief Brings the specified window to front and sets input focus.
*
* This function brings the specified window to front and sets input focus.
* The window should already be visible and not iconified.
*
* By default, both windowed and full screen mode windows are focused when
* initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable
* this behavior.
*
* __Do not use this function__ to steal focus from other applications unless
* you are certain that is what the user wants. Focus stealing can be
* extremely disruptive.
*
* @param[in] window The window to give input focus.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_focus
*
* @since Added in version 3.2.
*
* @ingroup window
*/
GLFWAPI void glfwFocusWindow(GLFWwindow* window);
/*! @brief Returns the monitor that the window uses for full screen mode. /*! @brief Returns the monitor that the window uses for full screen mode.
* *
* This function returns the handle of the monitor that the specified window is * This function returns the handle of the monitor that the specified window is
@ -2270,6 +2397,7 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window);
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
* @sa @ref window_monitor * @sa @ref window_monitor
* @sa glfwSetWindowMonitor
* *
* @since Added in version 3.0. * @since Added in version 3.0.
* *
@ -2277,6 +2405,54 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window);
*/ */
GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
/*! @brief Sets the mode, monitor, video mode and placement of a window.
*
* This function sets the monitor that the window uses for full screen mode or,
* if the monitor is `NULL`, makes it windowed mode.
*
* When setting a monitor, this function updates the width, height and refresh
* rate of the desired video mode and switches to the video mode closest to it.
* The window position is ignored when setting a monitor.
*
* When the monitor is `NULL`, the position, width and height are used to
* place the window client area. The refresh rate is ignored when no monitor
* is specified.
*
* If you only wish to update the resolution of a full screen window or the
* size of a windowed mode window, see @ref glfwSetWindowSize.
*
* When a window transitions from full screen to windowed mode, this function
* restores any previous window settings such as whether it is decorated,
* floating, resizable, has size or aspect ratio limits, etc..
*
* @param[in] window The window whose monitor, size or video mode to set.
* @param[in] monitor The desired monitor, or `NULL` to set windowed mode.
* @param[in] xpos The desired x-coordinate of the upper-left corner of the
* client area.
* @param[in] ypos The desired y-coordinate of the upper-left corner of the
* client area.
* @param[in] width The desired with, in screen coordinates, of the client area
* or video mode.
* @param[in] height The desired height, in screen coordinates, of the client
* area or video mode.
* @param[in] refreshRate The desired refresh rate, in Hz, of the video mode.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_monitor
* @sa @ref window_full_screen
* @sa glfwGetWindowMonitor
* @sa glfwSetWindowSize
*
* @since Added in version 3.2.
*
* @ingroup window
*/
GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
/*! @brief Returns an attribute of the specified window. /*! @brief Returns an attribute of the specified window.
* *
* This function returns the value of an attribute of the specified window or * This function returns the value of an attribute of the specified window or
@ -2566,6 +2742,7 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window
* *
* @sa @ref events * @sa @ref events
* @sa glfwWaitEvents * @sa glfwWaitEvents
* @sa glfwWaitEventsTimeout
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* *
@ -2610,6 +2787,7 @@ GLFWAPI void glfwPollEvents(void);
* *
* @sa @ref events * @sa @ref events
* @sa glfwPollEvents * @sa glfwPollEvents
* @sa glfwWaitEventsTimeout
* *
* @since Added in version 2.5. * @since Added in version 2.5.
* *
@ -2617,6 +2795,52 @@ GLFWAPI void glfwPollEvents(void);
*/ */
GLFWAPI void glfwWaitEvents(void); GLFWAPI void glfwWaitEvents(void);
/*! @brief Waits with timeout until events are queued and processes them.
*
* This function puts the calling thread to sleep until at least one event is
* available in the event queue, or until the specified timeout is reached. If
* one or more events are available, it behaves exactly like @ref
* glfwPollEvents, i.e. the events in the queue are processed and the function
* then returns immediately. Processing events will cause the window and input
* callbacks associated with those events to be called.
*
* The timeout value must be a positive finite number.
*
* Since not all events are associated with callbacks, this function may return
* without a callback having been called even if you are monitoring all
* callbacks.
*
* On some platforms, a window move, resize or menu operation will cause event
* processing to block. This is due to how event processing is designed on
* those platforms. You can use the
* [window refresh callback](@ref window_refresh) to redraw the contents of
* your window when necessary during such operations.
*
* On some platforms, certain callbacks may be called outside of a call to one
* of the event processing functions.
*
* If no windows exist, this function returns immediately. For synchronization
* of threads in applications that do not create windows, use your threading
* library of choice.
*
* Event processing is not required for joystick input to work.
*
* @param[in] timeout The maximum amount of time, in seconds, to wait.
*
* @reentrancy This function must not be called from a callback.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref events
* @sa glfwPollEvents
* @sa glfwWaitEvents
*
* @since Added in version 3.2.
*
* @ingroup window
*/
GLFWAPI void glfwWaitEventsTimeout(double timeout);
/*! @brief Posts an empty event to the event queue. /*! @brief Posts an empty event to the event queue.
* *
* This function posts an empty event from the current thread to the event * This function posts an empty event from the current thread to the event
@ -2714,13 +2938,42 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value);
/*! @brief Returns the localized name of the specified printable key. /*! @brief Returns the localized name of the specified printable key.
* *
* This function returns the localized name of the specified printable key. * This function returns the localized name of the specified printable key.
* This is intended for displaying key bindings to the user.
* *
* If the key is `GLFW_KEY_UNKNOWN`, the scancode is used, otherwise the * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise
* scancode is ignored. * the scancode is ignored. If a non-printable key or (if the key is
* `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is
* specified, this function returns `NULL`.
*
* This behavior allows you to pass in the arguments passed to the
* [key callback](@ref input_key) without modification.
*
* The printable keys are:
* - `GLFW_KEY_APOSTROPHE`
* - `GLFW_KEY_COMMA`
* - `GLFW_KEY_MINUS`
* - `GLFW_KEY_PERIOD`
* - `GLFW_KEY_SLASH`
* - `GLFW_KEY_SEMICOLON`
* - `GLFW_KEY_EQUAL`
* - `GLFW_KEY_LEFT_BRACKET`
* - `GLFW_KEY_RIGHT_BRACKET`
* - `GLFW_KEY_BACKSLASH`
* - `GLFW_KEY_WORLD_1`
* - `GLFW_KEY_WORLD_2`
* - `GLFW_KEY_0` to `GLFW_KEY_9`
* - `GLFW_KEY_A` to `GLFW_KEY_Z`
* - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9`
* - `GLFW_KEY_KP_DECIMAL`
* - `GLFW_KEY_KP_DIVIDE`
* - `GLFW_KEY_KP_MULTIPLY`
* - `GLFW_KEY_KP_SUBTRACT`
* - `GLFW_KEY_KP_ADD`
* - `GLFW_KEY_KP_EQUAL`
* *
* @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`.
* @param[in] scancode The scancode of the key to query. * @param[in] scancode The scancode of the key to query.
* @return The localized name of the key. * @return The localized name of the key, or `NULL`.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
@ -3368,6 +3621,29 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count);
*/ */
GLFWAPI const char* glfwGetJoystickName(int joy); GLFWAPI const char* glfwGetJoystickName(int joy);
/*! @brief Sets the joystick configuration callback.
*
* This function sets the joystick configuration callback, or removes the
* currently set callback. This is called when a joystick is connected to or
* disconnected from the system.
*
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
* callback.
* @return The previously set callback, or `NULL` if no callback was set or the
* library had not been [initialized](@ref intro_init).
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref joystick_event
*
* @since Added in version 3.2.
*
* @ingroup input
*/
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun);
/*! @brief Sets the clipboard to the specified string. /*! @brief Sets the clipboard to the specified string.
* *
* This function sets the system clipboard to the specified, UTF-8 encoded * This function sets the system clipboard to the specified, UTF-8 encoded
@ -3438,8 +3714,8 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
* *
* @thread_safety This function may be called from any thread. Access is not * @thread_safety This function may be called from any thread. Reading of the
* synchronized. * internal timer offset is not atomic.
* *
* @sa @ref time * @sa @ref time
* *
@ -3464,7 +3740,8 @@ GLFWAPI double glfwGetTime(void);
* floor((2<sup>64</sup> - 1) / 10<sup>9</sup>) and is due to implementations * floor((2<sup>64</sup> - 1) / 10<sup>9</sup>) and is due to implementations
* storing nanoseconds in 64 bits. The limit may be increased in the future. * storing nanoseconds in 64 bits. The limit may be increased in the future.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function may be called from any thread. Writing of the
* internal timer offset is not atomic.
* *
* @sa @ref time * @sa @ref time
* *
@ -3474,6 +3751,48 @@ GLFWAPI double glfwGetTime(void);
*/ */
GLFWAPI void glfwSetTime(double time); GLFWAPI void glfwSetTime(double time);
/*! @brief Returns the current value of the raw timer.
*
* This function returns the current value of the raw timer, measured in
* 1&nbsp;/&nbsp;frequency seconds. To get the frequency, call @ref
* glfwGetTimerFrequency.
*
* @return The value of the timer, or zero if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread.
*
* @sa @ref time
* @sa glfwGetTimerFrequency
*
* @since Added in version 3.2.
*
* @ingroup input
*/
GLFWAPI uint64_t glfwGetTimerValue(void);
/*! @brief Returns the frequency, in Hz, of the raw timer.
*
* This function returns the frequency, in Hz, of the raw timer.
*
* @return The frequency of the timer, in Hz, or zero if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread.
*
* @sa @ref time
* @sa glfwGetTimerValue
*
* @since Added in version 3.2.
*
* @ingroup input
*/
GLFWAPI uint64_t glfwGetTimerFrequency(void);
/*! @brief Makes the context of the specified window current for the calling /*! @brief Makes the context of the specified window current for the calling
* thread. * thread.
* *
@ -3531,14 +3850,18 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void);
/*! @brief Swaps the front and back buffers of the specified window. /*! @brief Swaps the front and back buffers of the specified window.
* *
* This function swaps the front and back buffers of the specified window. If * This function swaps the front and back buffers of the specified window when
* the swap interval is greater than zero, the GPU driver waits the specified * rendering with OpenGL or OpenGL ES. If the swap interval is greater than
* number of screen updates before swapping the buffers. * zero, the GPU driver waits the specified number of screen updates before
* swapping the buffers.
* *
* The specified window must have an OpenGL or OpenGL ES context. Specifying * The specified window must have an OpenGL or OpenGL ES context. Specifying
* a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT
* error. * error.
* *
* This function does not apply to Vulkan. If you are rendering with Vulkan,
* see `vkQueuePresentKHR` instead.
*
* @param[in] window The window whose buffers to swap. * @param[in] window The window whose buffers to swap.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
@ -3561,11 +3884,11 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* window);
/*! @brief Sets the swap interval for the current context. /*! @brief Sets the swap interval for the current context.
* *
* This function sets the swap interval for the current context, i.e. the * This function sets the swap interval for the current OpenGL or OpenGL ES
* number of screen updates to wait from the time @ref glfwSwapBuffers was * context, i.e. the number of screen updates to wait from the time @ref
* called before swapping the buffers and returning. This is sometimes called * glfwSwapBuffers was called before swapping the buffers and returning. This
* _vertical synchronization_, _vertical retrace synchronization_ or just * is sometimes called _vertical synchronization_, _vertical retrace
* _vsync_. * synchronization_ or just _vsync_.
* *
* Contexts that support either of the `WGL_EXT_swap_control_tear` and * Contexts that support either of the `WGL_EXT_swap_control_tear` and
* `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals,
@ -3577,6 +3900,9 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* window);
* A context must be current on the calling thread. Calling this function * A context must be current on the calling thread. Calling this function
* without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
* *
* This function does not apply to Vulkan. If you are rendering with Vulkan,
* see the present mode of your swapchain instead.
*
* @param[in] interval The minimum number of screen updates to wait for * @param[in] interval The minimum number of screen updates to wait for
* until the buffers are swapped by @ref glfwSwapBuffers. * until the buffers are swapped by @ref glfwSwapBuffers.
* *
@ -3606,9 +3932,9 @@ GLFWAPI void glfwSwapInterval(int interval);
/*! @brief Returns whether the specified extension is available. /*! @brief Returns whether the specified extension is available.
* *
* This function returns whether the specified * This function returns whether the specified
* [client API extension](@ref context_glext) is supported by the current * [API extension](@ref context_glext) is supported by the current OpenGL or
* OpenGL or OpenGL ES context. It searches both for OpenGL and OpenGL ES * OpenGL ES context. It searches both for client API extension and context
* extension and platform-specific context creation API extensions. * creation API extensions.
* *
* A context must be current on the calling thread. Calling this function * A context must be current on the calling thread. Calling this function
* without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
@ -3618,6 +3944,10 @@ GLFWAPI void glfwSwapInterval(int interval);
* frequently. The extension strings will not change during the lifetime of * frequently. The extension strings will not change during the lifetime of
* a context, so there is no danger in doing this. * a context, so there is no danger in doing this.
* *
* This function does not apply to Vulkan. If you are using Vulkan, see @ref
* glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties`
* and `vkEnumerateDeviceExtensionProperties` instead.
*
* @param[in] extension The ASCII encoded name of the extension. * @param[in] extension The ASCII encoded name of the extension.
* @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE`
* otherwise. * otherwise.
@ -3640,13 +3970,17 @@ GLFWAPI int glfwExtensionSupported(const char* extension);
/*! @brief Returns the address of the specified function for the current /*! @brief Returns the address of the specified function for the current
* context. * context.
* *
* This function returns the address of the specified * This function returns the address of the specified OpenGL or OpenGL ES
* [core or extension function](@ref context_glext), if it is supported * [core or extension function](@ref context_glext), if it is supported
* by the current context. * by the current context.
* *
* A context must be current on the calling thread. Calling this function * A context must be current on the calling thread. Calling this function
* without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
* *
* This function does not apply to Vulkan. If you are rendering with Vulkan,
* see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and
* `vkGetDeviceProcAddr` instead.
*
* @param[in] procname The ASCII encoded name of the function. * @param[in] procname The ASCII encoded name of the function.
* @return The address of the function, or `NULL` if an * @return The address of the function, or `NULL` if an
* [error](@ref error_handling) occurred. * [error](@ref error_handling) occurred.
@ -3743,7 +4077,7 @@ GLFWAPI int glfwVulkanSupported(void);
* *
* @ingroup vulkan * @ingroup vulkan
*/ */
GLFWAPI const char** glfwGetRequiredInstanceExtensions(int* count); GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count);
#if defined(VK_VERSION_1_0) #if defined(VK_VERSION_1_0)
@ -3857,7 +4191,7 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys
* @remarks If an error occurs before the creation call is made, GLFW returns * @remarks If an error occurs before the creation call is made, GLFW returns
* the Vulkan error code most appropriate for the error. Appropriate use of * the Vulkan error code most appropriate for the error. Appropriate use of
* @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
* elminiate almost all occurences of these errors. * eliminate almost all occurrences of these errors.
* *
* @thread_safety This function may be called from any thread. For * @thread_safety This function may be called from any thread. For
* synchronization details of Vulkan objects, see the Vulkan specification. * synchronization details of Vulkan objects, see the Vulkan specification.

View File

@ -7,42 +7,44 @@ set(common_SOURCES context.c init.c input.c monitor.c vulkan.c window.c)
if (_GLFW_COCOA) if (_GLFW_COCOA)
set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h
posix_tls.h) posix_tls.h nsgl_context.h)
set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_tls.c) cocoa_monitor.m cocoa_window.m cocoa_time.c posix_tls.c
nsgl_context.m)
elseif (_GLFW_WIN32) elseif (_GLFW_WIN32)
set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h) set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h
wgl_context.h egl_context.h)
set(glfw_SOURCES ${common_SOURCES} win32_init.c win32_joystick.c set(glfw_SOURCES ${common_SOURCES} win32_init.c win32_joystick.c
win32_monitor.c win32_time.c win32_tls.c win32_window.c) win32_monitor.c win32_time.c win32_tls.c win32_window.c
wgl_context.c egl_context.c)
elseif (_GLFW_X11) elseif (_GLFW_X11)
set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h
linux_joystick.h posix_time.h posix_tls.h) linux_joystick.h posix_time.h posix_tls.h glx_context.h
egl_context.h)
set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c
xkb_unicode.c linux_joystick.c posix_time.c posix_tls.c) xkb_unicode.c linux_joystick.c posix_time.c posix_tls.c
glx_context.c egl_context.c)
elseif (_GLFW_WAYLAND) elseif (_GLFW_WAYLAND)
set(glfw_HEADERS ${common_HEADERS} wl_platform.h linux_joystick.h set(glfw_HEADERS ${common_HEADERS} wl_platform.h linux_joystick.h
posix_time.h posix_tls.h xkb_unicode.h) posix_time.h posix_tls.h xkb_unicode.h egl_context.h)
set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c) linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
egl_context.c)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml
BASENAME relative-pointer-unstable-v1)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml
BASENAME pointer-constraints-unstable-v1)
elseif (_GLFW_MIR) elseif (_GLFW_MIR)
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
posix_time.h posix_tls.h xkb_unicode.h) posix_time.h posix_tls.h xkb_unicode.h egl_context.h)
set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c) linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
endif() egl_context.c)
if (_GLFW_EGL)
list(APPEND glfw_HEADERS ${common_HEADERS} egl_context.h)
list(APPEND glfw_SOURCES ${common_SOURCES} egl_context.c)
elseif (_GLFW_NSGL)
list(APPEND glfw_HEADERS ${common_HEADERS} nsgl_context.h)
list(APPEND glfw_SOURCES ${common_SOURCES} nsgl_context.m)
elseif (_GLFW_WGL)
list(APPEND glfw_HEADERS ${common_HEADERS} wgl_context.h)
list(APPEND glfw_SOURCES ${common_SOURCES} wgl_context.c)
elseif (_GLFW_X11)
list(APPEND glfw_HEADERS ${common_HEADERS} glx_context.h)
list(APPEND glfw_SOURCES ${common_SOURCES} glx_context.c)
endif() endif()
if (APPLE) if (APPLE)

View File

@ -265,9 +265,6 @@ void _glfwPlatformTerminate(void)
_glfw.ns.delegate = nil; _glfw.ns.delegate = nil;
} }
[_glfw.ns.autoreleasePool release];
_glfw.ns.autoreleasePool = nil;
[_glfw.ns.cursor release]; [_glfw.ns.cursor release];
_glfw.ns.cursor = nil; _glfw.ns.cursor = nil;
@ -276,14 +273,14 @@ void _glfwPlatformTerminate(void)
_glfwTerminateNSGL(); _glfwTerminateNSGL();
_glfwTerminateJoysticksNS(); _glfwTerminateJoysticksNS();
_glfwTerminateThreadLocalStoragePOSIX(); _glfwTerminateThreadLocalStoragePOSIX();
[_glfw.ns.autoreleasePool release];
_glfw.ns.autoreleasePool = nil;
} }
const char* _glfwPlatformGetVersionString(void) const char* _glfwPlatformGetVersionString(void)
{ {
return _GLFW_VERSION_NUMBER " Cocoa" return _GLFW_VERSION_NUMBER " Cocoa NSGL"
#if defined(_GLFW_NSGL)
" NSGL"
#endif
#if defined(_GLFW_USE_CHDIR) #if defined(_GLFW_USE_CHDIR)
" chdir" " chdir"
#endif #endif

View File

@ -56,7 +56,7 @@ typedef struct _GLFWjoydeviceNS
// //
typedef struct _GLFWjoystickNS typedef struct _GLFWjoystickNS
{ {
_GLFWjoydeviceNS devices[GLFW_JOYSTICK_LAST + 1]; _GLFWjoydeviceNS js[GLFW_JOYSTICK_LAST + 1];
IOHIDManagerRef managerRef; IOHIDManagerRef managerRef;
} _GLFWjoystickNS; } _GLFWjoystickNS;

View File

@ -38,9 +38,8 @@
#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h> #include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>
//------------------------------------------------------------------------
// Joystick element information // Joystick element information
//------------------------------------------------------------------------ //
typedef struct _GLFWjoyelementNS typedef struct _GLFWjoyelementNS
{ {
IOHIDElementRef elementRef; IOHIDElementRef elementRef;
@ -58,7 +57,7 @@ static void getElementsCFArrayHandler(const void* value, void* parameter);
// Adds an element to the specified joystick // Adds an element to the specified joystick
// //
static void addJoystickElement(_GLFWjoydeviceNS* joystick, static void addJoystickElement(_GLFWjoydeviceNS* js,
IOHIDElementRef elementRef) IOHIDElementRef elementRef)
{ {
IOHIDElementType elementType; IOHIDElementType elementType;
@ -91,10 +90,10 @@ static void addJoystickElement(_GLFWjoydeviceNS* joystick,
case kHIDUsage_GD_Slider: case kHIDUsage_GD_Slider:
case kHIDUsage_GD_Dial: case kHIDUsage_GD_Dial:
case kHIDUsage_GD_Wheel: case kHIDUsage_GD_Wheel:
elementsArray = joystick->axisElements; elementsArray = js->axisElements;
break; break;
case kHIDUsage_GD_Hatswitch: case kHIDUsage_GD_Hatswitch:
elementsArray = joystick->hatElements; elementsArray = js->hatElements;
break; break;
} }
@ -102,7 +101,7 @@ static void addJoystickElement(_GLFWjoydeviceNS* joystick,
} }
case kHIDPage_Button: case kHIDPage_Button:
elementsArray = joystick->buttonElements; elementsArray = js->buttonElements;
break; break;
default: default:
break; break;
@ -134,15 +133,15 @@ static void getElementsCFArrayHandler(const void* value, void* parameter)
// Returns the value of the specified element of the specified joystick // Returns the value of the specified element of the specified joystick
// //
static long getElementValue(_GLFWjoydeviceNS* joystick, _GLFWjoyelementNS* element) static long getElementValue(_GLFWjoydeviceNS* js, _GLFWjoyelementNS* element)
{ {
IOReturn result = kIOReturnSuccess; IOReturn result = kIOReturnSuccess;
IOHIDValueRef valueRef; IOHIDValueRef valueRef;
long value = 0; long value = 0;
if (joystick && element && joystick->deviceRef) if (js && element && js->deviceRef)
{ {
result = IOHIDDeviceGetValue(joystick->deviceRef, result = IOHIDDeviceGetValue(js->deviceRef,
element->elementRef, element->elementRef,
&valueRef); &valueRef);
@ -164,87 +163,101 @@ static long getElementValue(_GLFWjoydeviceNS* joystick, _GLFWjoyelementNS* eleme
// Removes the specified joystick // Removes the specified joystick
// //
static void removeJoystick(_GLFWjoydeviceNS* joystick) static void removeJoystick(_GLFWjoydeviceNS* js)
{ {
int i; int i;
if (!joystick->present) if (!js->present)
return; return;
for (i = 0; i < CFArrayGetCount(joystick->axisElements); i++) for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
free((void*) CFArrayGetValueAtIndex(joystick->axisElements, i)); free((void*) CFArrayGetValueAtIndex(js->axisElements, i));
CFArrayRemoveAllValues(joystick->axisElements); CFArrayRemoveAllValues(js->axisElements);
CFRelease(joystick->axisElements); CFRelease(js->axisElements);
for (i = 0; i < CFArrayGetCount(joystick->buttonElements); i++) for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
free((void*) CFArrayGetValueAtIndex(joystick->buttonElements, i)); free((void*) CFArrayGetValueAtIndex(js->buttonElements, i));
CFArrayRemoveAllValues(joystick->buttonElements); CFArrayRemoveAllValues(js->buttonElements);
CFRelease(joystick->buttonElements); CFRelease(js->buttonElements);
for (i = 0; i < CFArrayGetCount(joystick->hatElements); i++) for (i = 0; i < CFArrayGetCount(js->hatElements); i++)
free((void*) CFArrayGetValueAtIndex(joystick->hatElements, i)); free((void*) CFArrayGetValueAtIndex(js->hatElements, i));
CFArrayRemoveAllValues(joystick->hatElements); CFArrayRemoveAllValues(js->hatElements);
CFRelease(joystick->hatElements); CFRelease(js->hatElements);
free(joystick->axes); free(js->axes);
free(joystick->buttons); free(js->buttons);
memset(joystick, 0, sizeof(_GLFWjoydeviceNS)); memset(js, 0, sizeof(_GLFWjoydeviceNS));
_glfwInputJoystickChange(js - _glfw.ns_js.js, GLFW_DISCONNECTED);
} }
// Polls for joystick events and updates GLFW state // Polls for joystick axis events and updates GLFW state
// //
static GLFWbool pollJoystickEvents(_GLFWjoydeviceNS* joystick) static GLFWbool pollJoystickAxisEvents(_GLFWjoydeviceNS* js)
{
CFIndex i;
if (!js->present)
return GLFW_FALSE;
for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
{
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(js->axisElements, i);
long value = getElementValue(js, axis);
long readScale = axis->maxReport - axis->minReport;
if (readScale == 0)
js->axes[i] = value;
else
js->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;
}
return GLFW_TRUE;
}
// Polls for joystick button events and updates GLFW state
//
static GLFWbool pollJoystickButtonEvents(_GLFWjoydeviceNS* js)
{ {
CFIndex i; CFIndex i;
int buttonIndex = 0; int buttonIndex = 0;
if (!joystick->present) if (!js->present)
return GLFW_FALSE; return GLFW_FALSE;
for (i = 0; i < CFArrayGetCount(joystick->buttonElements); i++) for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
{ {
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*) _GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(joystick->buttonElements, i); CFArrayGetValueAtIndex(js->buttonElements, i);
if (getElementValue(joystick, button)) if (getElementValue(js, button))
joystick->buttons[buttonIndex++] = GLFW_PRESS; js->buttons[buttonIndex++] = GLFW_PRESS;
else else
joystick->buttons[buttonIndex++] = GLFW_RELEASE; js->buttons[buttonIndex++] = GLFW_RELEASE;
} }
for (i = 0; i < CFArrayGetCount(joystick->axisElements); i++) for (i = 0; i < CFArrayGetCount(js->hatElements); i++)
{
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(joystick->axisElements, i);
long value = getElementValue(joystick, axis);
long readScale = axis->maxReport - axis->minReport;
if (readScale == 0)
joystick->axes[i] = value;
else
joystick->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;
}
for (i = 0; i < CFArrayGetCount(joystick->hatElements); i++)
{ {
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*) _GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(joystick->hatElements, i); CFArrayGetValueAtIndex(js->hatElements, i);
// Bit fields of button presses for each direction, including nil // Bit fields of button presses for each direction, including nil
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 }; const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
long j, value = getElementValue(joystick, hat); long j, value = getElementValue(js, hat);
if (value < 0 || value > 8) if (value < 0 || value > 8)
value = 8; value = 8;
for (j = 0; j < 4; j++) for (j = 0; j < 4; j++)
{ {
if (directions[value] & (1 << j)) if (directions[value] & (1 << j))
joystick->buttons[buttonIndex++] = GLFW_PRESS; js->buttons[buttonIndex++] = GLFW_PRESS;
else else
joystick->buttons[buttonIndex++] = GLFW_RELEASE; js->buttons[buttonIndex++] = GLFW_RELEASE;
} }
} }
@ -258,49 +271,43 @@ static void matchCallback(void* context,
void* sender, void* sender,
IOHIDDeviceRef deviceRef) IOHIDDeviceRef deviceRef)
{ {
_GLFWjoydeviceNS* joystick; _GLFWjoydeviceNS* js;
int joy; int joy;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++) for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{ {
joystick = _glfw.ns_js.devices + joy; if (_glfw.ns_js.js[joy].present && _glfw.ns_js.js[joy].deviceRef == deviceRef)
if (!joystick->present)
continue;
if (joystick->deviceRef == deviceRef)
return; return;
} }
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++) for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{ {
joystick = _glfw.ns_js.devices + joy; if (!_glfw.ns_js.js[joy].present)
if (!joystick->present)
break; break;
} }
if (joy > GLFW_JOYSTICK_LAST) if (joy > GLFW_JOYSTICK_LAST)
return; return;
joystick->present = GLFW_TRUE; js = _glfw.ns_js.js + joy;
joystick->deviceRef = deviceRef; js->present = GLFW_TRUE;
js->deviceRef = deviceRef;
CFStringRef name = IOHIDDeviceGetProperty(deviceRef, CFStringRef name = IOHIDDeviceGetProperty(deviceRef,
CFSTR(kIOHIDProductKey)); CFSTR(kIOHIDProductKey));
if (name) if (name)
{ {
CFStringGetCString(name, CFStringGetCString(name,
joystick->name, js->name,
sizeof(joystick->name), sizeof(js->name),
kCFStringEncodingUTF8); kCFStringEncodingUTF8);
} }
else else
strncpy(joystick->name, "Unknown", sizeof(joystick->name)); strncpy(js->name, "Unknown", sizeof(js->name));
joystick->axisElements = CFArrayCreateMutable(NULL, 0, NULL); js->axisElements = CFArrayCreateMutable(NULL, 0, NULL);
joystick->buttonElements = CFArrayCreateMutable(NULL, 0, NULL); js->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);
joystick->hatElements = CFArrayCreateMutable(NULL, 0, NULL); js->hatElements = CFArrayCreateMutable(NULL, 0, NULL);
CFArrayRef arrayRef = IOHIDDeviceCopyMatchingElements(deviceRef, CFArrayRef arrayRef = IOHIDDeviceCopyMatchingElements(deviceRef,
NULL, NULL,
@ -309,14 +316,15 @@ static void matchCallback(void* context,
CFArrayApplyFunction(arrayRef, CFArrayApplyFunction(arrayRef,
range, range,
getElementsCFArrayHandler, getElementsCFArrayHandler,
(void*) joystick); (void*) js);
CFRelease(arrayRef); CFRelease(arrayRef);
joystick->axes = calloc(CFArrayGetCount(joystick->axisElements), js->axes = calloc(CFArrayGetCount(js->axisElements), sizeof(float));
sizeof(float)); js->buttons = calloc(CFArrayGetCount(js->buttonElements) +
joystick->buttons = calloc(CFArrayGetCount(joystick->buttonElements) + CFArrayGetCount(js->hatElements) * 4, 1);
CFArrayGetCount(joystick->hatElements) * 4, 1);
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
} }
// Callback for user-initiated joystick removal // Callback for user-initiated joystick removal
@ -330,10 +338,9 @@ static void removeCallback(void* context,
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++) for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{ {
_GLFWjoydeviceNS* joystick = _glfw.ns_js.devices + joy; if (_glfw.ns_js.js[joy].deviceRef == deviceRef)
if (joystick->deviceRef == deviceRef)
{ {
removeJoystick(joystick); removeJoystick(_glfw.ns_js.js + joy);
break; break;
} }
} }
@ -451,10 +458,10 @@ void _glfwTerminateJoysticksNS(void)
{ {
int joy; int joy;
for (joy = 0; joy <= GLFW_JOYSTICK_LAST; joy++) for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{ {
_GLFWjoydeviceNS* joystick = _glfw.ns_js.devices + joy; _GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
removeJoystick(joystick); removeJoystick(js);
} }
CFRelease(_glfw.ns_js.managerRef); CFRelease(_glfw.ns_js.managerRef);
@ -468,37 +475,37 @@ void _glfwTerminateJoysticksNS(void)
int _glfwPlatformJoystickPresent(int joy) int _glfwPlatformJoystickPresent(int joy)
{ {
_GLFWjoydeviceNS* joystick = _glfw.ns_js.devices + joy; _GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
return pollJoystickEvents(joystick); return js->present;
} }
const float* _glfwPlatformGetJoystickAxes(int joy, int* count) const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
{ {
_GLFWjoydeviceNS* joystick = _glfw.ns_js.devices + joy; _GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
if (!pollJoystickEvents(joystick)) if (!pollJoystickAxisEvents(js))
return NULL; return NULL;
*count = (int) CFArrayGetCount(joystick->axisElements); *count = (int) CFArrayGetCount(js->axisElements);
return joystick->axes; return js->axes;
} }
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count) const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
{ {
_GLFWjoydeviceNS* joystick = _glfw.ns_js.devices + joy; _GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
if (!pollJoystickEvents(joystick)) if (!pollJoystickButtonEvents(js))
return NULL; return NULL;
*count = (int) CFArrayGetCount(joystick->buttonElements) + *count = (int) CFArrayGetCount(js->buttonElements) +
(int) CFArrayGetCount(joystick->hatElements) * 4; (int) CFArrayGetCount(js->hatElements) * 4;
return joystick->buttons; return js->buttons;
} }
const char* _glfwPlatformGetJoystickName(int joy) const char* _glfwPlatformGetJoystickName(int joy)
{ {
_GLFWjoydeviceNS* joystick = _glfw.ns_js.devices + joy; _GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
if (!pollJoystickEvents(joystick)) if (!js->present)
return NULL; return NULL;
return joystick->name; return js->name;
} }

View File

@ -41,12 +41,7 @@ typedef void* id;
#include "posix_tls.h" #include "posix_tls.h"
#include "cocoa_joystick.h" #include "cocoa_joystick.h"
#include "nsgl_context.h"
#if defined(_GLFW_NSGL)
#include "nsgl_context.h"
#else
#error "The Cocoa backend depends on NSGL platform support"
#endif
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle) #define _glfw_dlclose(handle) dlclose(handle)
@ -58,6 +53,9 @@ typedef void* id;
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns
#define _GLFW_EGL_CONTEXT_STATE
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
// Cocoa-specific per-window data // Cocoa-specific per-window data
// //
@ -66,7 +64,6 @@ typedef struct _GLFWwindowNS
id object; id object;
id delegate; id delegate;
id view; id view;
unsigned int modifierFlags;
// The total sum of the distances the cursor has been warped // The total sum of the distances the cursor has been warped
// since the last cursor motion event was processed // since the last cursor motion event was processed
@ -119,8 +116,7 @@ typedef struct _GLFWcursorNS
// //
typedef struct _GLFWtimeNS typedef struct _GLFWtimeNS
{ {
double base; uint64_t frequency;
double resolution;
} _GLFWtimeNS; } _GLFWtimeNS;

View File

@ -29,14 +29,6 @@
#include <mach/mach_time.h> #include <mach/mach_time.h>
// Return raw time
//
static uint64_t getRawTime(void)
{
return mach_absolute_time();
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -48,8 +40,7 @@ void _glfwInitTimerNS(void)
mach_timebase_info_data_t info; mach_timebase_info_data_t info;
mach_timebase_info(&info); mach_timebase_info(&info);
_glfw.ns_time.resolution = (double) info.numer / (info.denom * 1.0e9); _glfw.ns_time.frequency = (info.denom * 1e9) / info.numer;
_glfw.ns_time.base = getRawTime();
} }
@ -57,15 +48,13 @@ void _glfwInitTimerNS(void)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
double _glfwPlatformGetTime(void) uint64_t _glfwPlatformGetTimerValue(void)
{ {
return (double) (getRawTime() - _glfw.ns_time.base) * return mach_absolute_time();
_glfw.ns_time.resolution;
} }
void _glfwPlatformSetTime(double time) uint64_t _glfwPlatformGetTimerFrequency(void)
{ {
_glfw.ns_time.base = getRawTime() - return _glfw.ns_time.frequency;
(uint64_t) (time / _glfw.ns_time.resolution);
} }

View File

@ -26,6 +26,7 @@
#include "internal.h" #include "internal.h"
#include <float.h>
#include <string.h> #include <string.h>
// Needed for _NSGetProgname // Needed for _NSGetProgname
@ -55,6 +56,26 @@ static NSCursor* getStandardCursor(int shape)
return nil; return nil;
} }
// Returns the style mask corresponding to the window settings
//
static NSUInteger getStyleMask(_GLFWwindow* window)
{
NSUInteger styleMask = 0;
if (window->monitor || !window->decorated)
styleMask |= NSBorderlessWindowMask;
else
{
styleMask |= NSTitledWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask;
if (window->resizable)
styleMask |= NSResizableWindowMask;
}
return styleMask;
}
// Center the cursor in the view of the window // Center the cursor in the view of the window
// //
static void centerCursor(_GLFWwindow *window) static void centerCursor(_GLFWwindow *window)
@ -72,9 +93,9 @@ static float transformY(float y)
return CGDisplayBounds(CGMainDisplayID()).size.height - y; return CGDisplayBounds(CGMainDisplayID()).size.height - y;
} }
// Enter full screen mode // Make the specified window and its video mode active on its monitor
// //
static GLFWbool enterFullscreenMode(_GLFWwindow* window) static GLFWbool acquireMonitor(_GLFWwindow* window)
{ {
const GLFWbool status = _glfwSetVideoModeNS(window->monitor, &window->videoMode); const GLFWbool status = _glfwSetVideoModeNS(window->monitor, &window->videoMode);
const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID); const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);
@ -84,13 +105,19 @@ static GLFWbool enterFullscreenMode(_GLFWwindow* window)
bounds.size.height); bounds.size.height);
[window->ns.object setFrame:frame display:YES]; [window->ns.object setFrame:frame display:YES];
_glfwInputMonitorWindowChange(window->monitor, window);
return status; return status;
} }
// Leave full screen mode // Remove the window and restore the original video mode
// //
static void leaveFullscreenMode(_GLFWwindow* window) static void releaseMonitor(_GLFWwindow* window)
{ {
if (window->monitor->window != window)
return;
_glfwInputMonitorWindowChange(window->monitor, NULL);
_glfwRestoreVideoModeNS(window->monitor); _glfwRestoreVideoModeNS(window->monitor);
} }
@ -122,6 +149,33 @@ static int translateKey(unsigned int key)
return _glfw.ns.publicKeys[key]; return _glfw.ns.publicKeys[key];
} }
// Translate a GLFW keycode to a Cocoa modifier flag
//
static NSUInteger translateKeyToModifierFlag(int key)
{
switch (key)
{
case GLFW_KEY_LEFT_SHIFT:
case GLFW_KEY_RIGHT_SHIFT:
return NSShiftKeyMask;
case GLFW_KEY_LEFT_CONTROL:
case GLFW_KEY_RIGHT_CONTROL:
return NSControlKeyMask;
case GLFW_KEY_LEFT_ALT:
case GLFW_KEY_RIGHT_ALT:
return NSAlternateKeyMask;
case GLFW_KEY_LEFT_SUPER:
case GLFW_KEY_RIGHT_SUPER:
return NSCommandKeyMask;
}
return 0;
}
// Defines a constant for empty ranges in NSTextInputClient
//
static const NSRange kEmptyRange = { NSNotFound, 0 };
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Delegate for window related notifications // Delegate for window related notifications
@ -155,7 +209,7 @@ static int translateKey(unsigned int key)
- (void)windowDidResize:(NSNotification *)notification - (void)windowDidResize:(NSNotification *)notification
{ {
if (window->context.api != GLFW_NO_API) if (window->context.client != GLFW_NO_API)
[window->context.nsgl.object update]; [window->context.nsgl.object update];
if (_glfw.cursorWindow == window && if (_glfw.cursorWindow == window &&
@ -173,7 +227,7 @@ static int translateKey(unsigned int key)
- (void)windowDidMove:(NSNotification *)notification - (void)windowDidMove:(NSNotification *)notification
{ {
if (window->context.api != GLFW_NO_API) if (window->context.client != GLFW_NO_API)
[window->context.nsgl.object update]; [window->context.nsgl.object update];
if (_glfw.cursorWindow == window && if (_glfw.cursorWindow == window &&
@ -190,7 +244,7 @@ static int translateKey(unsigned int key)
- (void)windowDidMiniaturize:(NSNotification *)notification - (void)windowDidMiniaturize:(NSNotification *)notification
{ {
if (window->monitor) if (window->monitor)
leaveFullscreenMode(window); releaseMonitor(window);
_glfwInputWindowIconify(window, GLFW_TRUE); _glfwInputWindowIconify(window, GLFW_TRUE);
} }
@ -198,7 +252,7 @@ static int translateKey(unsigned int key)
- (void)windowDidDeminiaturize:(NSNotification *)notification - (void)windowDidDeminiaturize:(NSNotification *)notification
{ {
if (window->monitor) if (window->monitor)
enterFullscreenMode(window); acquireMonitor(window);
_glfwInputWindowIconify(window, GLFW_FALSE); _glfwInputWindowIconify(window, GLFW_FALSE);
} }
@ -272,10 +326,11 @@ static int translateKey(unsigned int key)
// Content view class for the GLFW window // Content view class for the GLFW window
//------------------------------------------------------------------------ //------------------------------------------------------------------------
@interface GLFWContentView : NSView @interface GLFWContentView : NSView <NSTextInputClient>
{ {
_GLFWwindow* window; _GLFWwindow* window;
NSTrackingArea* trackingArea; NSTrackingArea* trackingArea;
NSMutableAttributedString* markedText;
} }
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow; - (id)initWithGlfwWindow:(_GLFWwindow *)initWindow;
@ -305,6 +360,7 @@ static int translateKey(unsigned int key)
{ {
window = initWindow; window = initWindow;
trackingArea = nil; trackingArea = nil;
markedText = [[NSMutableAttributedString alloc] init];
[self updateTrackingAreas]; [self updateTrackingAreas];
[self registerForDraggedTypes:[NSArray arrayWithObjects: [self registerForDraggedTypes:[NSArray arrayWithObjects:
@ -314,9 +370,10 @@ static int translateKey(unsigned int key)
return self; return self;
} }
-(void)dealloc - (void)dealloc
{ {
[trackingArea release]; [trackingArea release];
[markedText release];
[super dealloc]; [super dealloc];
} }
@ -481,18 +538,7 @@ static int translateKey(unsigned int key)
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods); _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
NSString* characters = [event characters]; [self interpretKeyEvents:[NSArray arrayWithObject:event]];
NSUInteger i, length = [characters length];
const int plain = !(mods & GLFW_MOD_SUPER);
for (i = 0; i < length; i++)
{
const unichar codepoint = [characters characterAtIndex:i];
if ((codepoint & 0xff00) == 0xf700)
continue;
_glfwInputChar(window, codepoint, mods, plain);
}
} }
- (void)flagsChanged:(NSEvent *)event - (void)flagsChanged:(NSEvent *)event
@ -502,21 +548,18 @@ static int translateKey(unsigned int key)
[event modifierFlags] & NSDeviceIndependentModifierFlagsMask; [event modifierFlags] & NSDeviceIndependentModifierFlagsMask;
const int key = translateKey([event keyCode]); const int key = translateKey([event keyCode]);
const int mods = translateFlags(modifierFlags); const int mods = translateFlags(modifierFlags);
const NSUInteger keyFlag = translateKeyToModifierFlag(key);
if (modifierFlags == window->ns.modifierFlags) if (keyFlag & modifierFlags)
{ {
if (window->keys[key] == GLFW_PRESS) if (window->keys[key] == GLFW_PRESS)
action = GLFW_RELEASE; action = GLFW_RELEASE;
else else
action = GLFW_PRESS; action = GLFW_PRESS;
} }
else if (modifierFlags > window->ns.modifierFlags)
action = GLFW_PRESS;
else else
action = GLFW_RELEASE; action = GLFW_RELEASE;
window->ns.modifierFlags = modifierFlags;
_glfwInputKey(window, key, [event keyCode], action, mods); _glfwInputKey(window, key, [event keyCode], action, mods);
} }
@ -597,6 +640,92 @@ static int translateKey(unsigned int key)
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} }
- (BOOL)hasMarkedText
{
return [markedText length] > 0;
}
- (NSRange)markedRange
{
if ([markedText length] > 0)
return NSMakeRange(0, [markedText length] - 1);
else
return kEmptyRange;
}
- (NSRange)selectedRange
{
return kEmptyRange;
}
- (void)setMarkedText:(id)string
selectedRange:(NSRange)selectedRange
replacementRange:(NSRange)replacementRange
{
if ([string isKindOfClass:[NSAttributedString class]])
[markedText initWithAttributedString:string];
else
[markedText initWithString:string];
}
- (void)unmarkText
{
[[markedText mutableString] setString:@""];
}
- (NSArray*)validAttributesForMarkedText
{
return [NSArray array];
}
- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range
actualRange:(NSRangePointer)actualRange
{
return nil;
}
- (NSUInteger)characterIndexForPoint:(NSPoint)point
{
return 0;
}
- (NSRect)firstRectForCharacterRange:(NSRange)range
actualRange:(NSRangePointer)actualRange
{
int xpos, ypos;
_glfwPlatformGetWindowPos(window, &xpos, &ypos);
const NSRect contentRect = [window->ns.view frame];
return NSMakeRect(xpos, transformY(ypos + contentRect.size.height), 0.0, 0.0);
}
- (void)insertText:(id)string replacementRange:(NSRange)replacementRange
{
NSString* characters;
NSEvent* event = [NSApp currentEvent];
const int mods = translateFlags([event modifierFlags]);
const int plain = !(mods & GLFW_MOD_SUPER);
if ([string isKindOfClass:[NSAttributedString class]])
characters = [string string];
else
characters = (NSString*) string;
NSUInteger i, length = [characters length];
for (i = 0; i < length; i++)
{
const unichar codepoint = [characters characterAtIndex:i];
if ((codepoint & 0xff00) == 0xf700)
continue;
_glfwInputChar(window, codepoint, mods, plain);
}
}
- (void)doCommandBySelector:(SEL)selector
{
}
@end @end
@ -802,22 +931,9 @@ static GLFWbool createWindow(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
unsigned int styleMask = 0;
if (wndconfig->monitor || !wndconfig->decorated)
styleMask = NSBorderlessWindowMask;
else
{
styleMask = NSTitledWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask;
if (wndconfig->resizable)
styleMask |= NSResizableWindowMask;
}
NSRect contentRect; NSRect contentRect;
if (wndconfig->monitor) if (window->monitor)
{ {
GLFWvidmode mode; GLFWvidmode mode;
int xpos, ypos; int xpos, ypos;
@ -832,7 +948,7 @@ static GLFWbool createWindow(_GLFWwindow* window,
window->ns.object = [[GLFWWindow alloc] window->ns.object = [[GLFWWindow alloc]
initWithContentRect:contentRect initWithContentRect:contentRect
styleMask:styleMask styleMask:getStyleMask(window)
backing:NSBackingStoreBuffered backing:NSBackingStoreBuffered
defer:NO]; defer:NO];
@ -842,19 +958,20 @@ static GLFWbool createWindow(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
if (wndconfig->resizable) if (window->monitor)
[window->ns.object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
if (wndconfig->monitor)
{
[window->ns.object setLevel:NSMainMenuWindowLevel + 1]; [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
}
else else
{ {
[window->ns.object center]; [window->ns.object center];
if (wndconfig->resizable)
[window->ns.object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
if (wndconfig->floating) if (wndconfig->floating)
[window->ns.object setLevel:NSFloatingWindowLevel]; [window->ns.object setLevel:NSFloatingWindowLevel];
if (wndconfig->maximized)
[window->ns.object zoom:nil];
} }
window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window]; window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
@ -863,12 +980,7 @@ static GLFWbool createWindow(_GLFWwindow* window,
[window->ns.view setWantsBestResolutionOpenGLSurface:YES]; [window->ns.view setWantsBestResolutionOpenGLSurface:YES];
#endif /*_GLFW_USE_RETINA*/ #endif /*_GLFW_USE_RETINA*/
if (wndconfig->transparent) [window->ns.object makeFirstResponder:window->ns.view];
{
[window->ns.object setOpaque:NO];
[window->ns.object setBackgroundColor:[NSColor clearColor]];
}
[window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]]; [window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
[window->ns.object setDelegate:window->ns.delegate]; [window->ns.object setDelegate:window->ns.delegate];
[window->ns.object setAcceptsMouseMovedEvents:YES]; [window->ns.object setAcceptsMouseMovedEvents:YES];
@ -894,16 +1006,25 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!createWindow(window, wndconfig)) if (!createWindow(window, wndconfig))
return GLFW_FALSE; return GLFW_FALSE;
if (ctxconfig->api != GLFW_NO_API) if (ctxconfig->client != GLFW_NO_API)
{ {
if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig)) if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
{
if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else
{
_glfwInputError(GLFW_API_UNAVAILABLE, "Cocoa: EGL not available");
return GLFW_FALSE; return GLFW_FALSE;
}
} }
if (wndconfig->monitor) if (window->monitor)
{ {
_glfwPlatformShowWindow(window); _glfwPlatformShowWindow(window);
if (!enterFullscreenMode(window)) _glfwPlatformFocusWindow(window);
if (!acquireMonitor(window))
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -915,10 +1036,10 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
[window->ns.object orderOut:nil]; [window->ns.object orderOut:nil];
if (window->monitor) if (window->monitor)
leaveFullscreenMode(window); releaseMonitor(window);
if (window->context.api != GLFW_NO_API) if (window->context.client != GLFW_NO_API)
_glfwDestroyContextNSGL(window); window->context.destroyContext(window);
[window->ns.object setDelegate:nil]; [window->ns.object setDelegate:nil];
[window->ns.delegate release]; [window->ns.delegate release];
@ -929,6 +1050,9 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
[window->ns.object close]; [window->ns.object close];
window->ns.object = nil; window->ns.object = nil;
[_glfw.ns.autoreleasePool drain];
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
} }
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char *title) void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char *title)
@ -936,6 +1060,12 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char *title)
[window->ns.object setTitle:[NSString stringWithUTF8String:title]]; [window->ns.object setTitle:[NSString stringWithUTF8String:title]];
} }
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
int count, const GLFWimage* images)
{
// Regular windows do not have icons
}
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
{ {
// Code from Matt Reagan on the Cocoa-dev mailing list. // Code from Matt Reagan on the Cocoa-dev mailing list.
@ -987,7 +1117,10 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{ {
if (window->monitor) if (window->monitor)
enterFullscreenMode(window); {
if (window->monitor->window == window)
acquireMonitor(window);
}
else else
[window->ns.object setContentSize:NSMakeSize(width, height)]; [window->ns.object setContentSize:NSMakeSize(width, height)];
} }
@ -1002,7 +1135,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
[window->ns.object setContentMinSize:NSMakeSize(minwidth, minheight)]; [window->ns.object setContentMinSize:NSMakeSize(minwidth, minheight)];
if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE) if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
[window->ns.object setContentMaxSize:NSMakeSize(0, 0)]; [window->ns.object setContentMaxSize:NSMakeSize(DBL_MAX, DBL_MAX)];
else else
[window->ns.object setContentMaxSize:NSMakeSize(maxwidth, maxheight)]; [window->ns.object setContentMaxSize:NSMakeSize(maxwidth, maxheight)];
} }
@ -1052,10 +1185,29 @@ void _glfwPlatformIconifyWindow(_GLFWwindow* window)
void _glfwPlatformRestoreWindow(_GLFWwindow* window) void _glfwPlatformRestoreWindow(_GLFWwindow* window)
{ {
[window->ns.object deminiaturize:nil]; if ([window->ns.object isMiniaturized])
[window->ns.object deminiaturize:nil];
else if ([window->ns.object isZoomed])
[window->ns.object zoom:nil];
}
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{
if (![window->ns.object isZoomed])
[window->ns.object zoom:nil];
} }
void _glfwPlatformShowWindow(_GLFWwindow* window) void _glfwPlatformShowWindow(_GLFWwindow* window)
{
[window->ns.object orderFront:nil];
}
void _glfwPlatformHideWindow(_GLFWwindow* window)
{
[window->ns.object orderOut:nil];
}
void _glfwPlatformFocusWindow(_GLFWwindow* window)
{ {
// Make us the active application // Make us the active application
// HACK: This has been moved here from initializeAppKit to prevent // HACK: This has been moved here from initializeAppKit to prevent
@ -1066,14 +1218,101 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
[window->ns.object makeKeyAndOrderFront:nil]; [window->ns.object makeKeyAndOrderFront:nil];
} }
void _glfwPlatformUnhideWindow(_GLFWwindow* window) void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{ {
[window->ns.object orderFront:nil]; if (window->monitor == monitor)
} {
if (monitor)
{
if (monitor->window == window)
acquireMonitor(window);
}
else
{
const NSRect contentRect =
NSMakeRect(xpos, transformY(ypos + height), width, height);
const NSRect frameRect =
[window->ns.object frameRectForContentRect:contentRect
styleMask:getStyleMask(window)];
void _glfwPlatformHideWindow(_GLFWwindow* window) [window->ns.object setFrame:frameRect display:YES];
{ }
[window->ns.object orderOut:nil];
return;
}
if (window->monitor)
releaseMonitor(window);
_glfwInputWindowMonitorChange(window, monitor);
const NSUInteger styleMask = getStyleMask(window);
[window->ns.object setStyleMask:styleMask];
[window->ns.object makeFirstResponder:window->ns.view];
NSRect contentRect;
if (monitor)
{
GLFWvidmode mode;
_glfwPlatformGetVideoMode(window->monitor, &mode);
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
contentRect = NSMakeRect(xpos, transformY(ypos + mode.height),
mode.width, mode.height);
}
else
{
contentRect = NSMakeRect(xpos, transformY(ypos + height),
width, height);
}
NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect
styleMask:styleMask];
[window->ns.object setFrame:frameRect display:YES];
if (monitor)
{
[window->ns.object setLevel:NSMainMenuWindowLevel + 1];
[window->ns.object setHasShadow:NO];
acquireMonitor(window);
}
else
{
if (window->numer != GLFW_DONT_CARE &&
window->denom != GLFW_DONT_CARE)
{
[window->ns.object setContentAspectRatio:NSMakeSize(window->numer,
window->denom)];
}
if (window->minwidth != GLFW_DONT_CARE &&
window->minheight != GLFW_DONT_CARE)
{
[window->ns.object setContentMinSize:NSMakeSize(window->minwidth,
window->minheight)];
}
if (window->maxwidth != GLFW_DONT_CARE &&
window->maxheight != GLFW_DONT_CARE)
{
[window->ns.object setContentMaxSize:NSMakeSize(window->maxwidth,
window->maxheight)];
}
if (window->floating)
[window->ns.object setLevel:NSFloatingWindowLevel];
else
[window->ns.object setLevel:NSNormalWindowLevel];
[window->ns.object setHasShadow:YES];
}
} }
int _glfwPlatformWindowFocused(_GLFWwindow* window) int _glfwPlatformWindowFocused(_GLFWwindow* window)
@ -1091,6 +1330,11 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window)
return [window->ns.object isVisible]; return [window->ns.object isVisible];
} }
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
{
return [window->ns.object isZoomed];
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
for (;;) for (;;)
@ -1123,6 +1367,19 @@ void _glfwPlatformWaitEvents(void)
_glfwPlatformPollEvents(); _glfwPlatformPollEvents();
} }
void _glfwPlatformWaitEventsTimeout(double timeout)
{
NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:date
inMode:NSDefaultRunLoopMode
dequeue:YES];
if (event)
[NSApp sendEvent:event];
_glfwPlatformPollEvents();
}
void _glfwPlatformPostEmptyEvent(void) void _glfwPlatformPostEmptyEvent(void)
{ {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@ -1351,7 +1608,7 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
return _glfw.ns.clipboardString; return _glfw.ns.clipboardString;
} }
char** _glfwPlatformGetRequiredInstanceExtensions(int* count) char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
{ {
*count = 0; *count = 0;
return NULL; return NULL;
@ -1359,7 +1616,7 @@ char** _glfwPlatformGetRequiredInstanceExtensions(int* count)
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
unsigned int queuefamily) uint32_t queuefamily)
{ {
return GLFW_FALSE; return GLFW_FALSE;
} }

View File

@ -57,7 +57,7 @@ static GLFWbool parseVersionString(int* api, int* major, int* minor, int* rev)
if (!version) if (!version)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Failed to retrieve context version string"); "Client API version string retrieval is broken");
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -76,7 +76,7 @@ static GLFWbool parseVersionString(int* api, int* major, int* minor, int* rev)
if (!sscanf(version, "%d.%d.%d", major, minor, rev)) if (!sscanf(version, "%d.%d.%d", major, minor, rev))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"No version found in context version string"); "No version found in client API version string");
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -90,15 +90,26 @@ static GLFWbool parseVersionString(int* api, int* major, int* minor, int* rev)
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
{ {
if (ctxconfig->api != GLFW_NO_API && if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
ctxconfig->api != GLFW_OPENGL_API && ctxconfig->source != GLFW_EGL_CONTEXT_API)
ctxconfig->api != GLFW_OPENGL_ES_API)
{ {
_glfwInputError(GLFW_INVALID_ENUM, "Invalid client API"); _glfwInputError(GLFW_INVALID_ENUM,
"Invalid context creation API %i",
ctxconfig->source);
return GLFW_FALSE; return GLFW_FALSE;
} }
if (ctxconfig->api == GLFW_OPENGL_API) if (ctxconfig->client != GLFW_NO_API &&
ctxconfig->client != GLFW_OPENGL_API &&
ctxconfig->client != GLFW_OPENGL_ES_API)
{
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid client API %i",
ctxconfig->client);
return GLFW_FALSE;
}
if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if ((ctxconfig->major < 1 || ctxconfig->minor < 0) || if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||
(ctxconfig->major == 1 && ctxconfig->minor > 5) || (ctxconfig->major == 1 && ctxconfig->minor > 5) ||
@ -123,7 +134,8 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE) ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
{ {
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,
"Invalid OpenGL profile"); "Invalid OpenGL profile %i",
ctxconfig->profile);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -147,7 +159,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
return GLFW_FALSE; return GLFW_FALSE;
} }
} }
else if (ctxconfig->api == GLFW_OPENGL_ES_API) else if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
if (ctxconfig->major < 1 || ctxconfig->minor < 0 || if (ctxconfig->major < 1 || ctxconfig->minor < 0 ||
(ctxconfig->major == 1 && ctxconfig->minor > 1) || (ctxconfig->major == 1 && ctxconfig->minor > 1) ||
@ -171,7 +183,8 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET) ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
{ {
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,
"Invalid context robustness mode"); "Invalid context robustness mode %i",
ctxconfig->robustness);
return GLFW_FALSE; return GLFW_FALSE;
} }
} }
@ -182,7 +195,8 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH) ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
{ {
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,
"Invalid context release behavior"); "Invalid context release behavior %i",
ctxconfig->release);
return GLFW_FALSE; return GLFW_FALSE;
} }
} }
@ -367,8 +381,13 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
glfwGetProcAddress("glGetIntegerv"); glfwGetProcAddress("glGetIntegerv");
window->context.GetString = (PFNGLGETSTRINGPROC) window->context.GetString = (PFNGLGETSTRINGPROC)
glfwGetProcAddress("glGetString"); glfwGetProcAddress("glGetString");
if (!window->context.GetIntegerv || !window->context.GetString)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
return GLFW_FALSE;
}
if (!parseVersionString(&window->context.api, if (!parseVersionString(&window->context.client,
&window->context.major, &window->context.major,
&window->context.minor, &window->context.minor,
&window->context.revision)) &window->context.revision))
@ -376,6 +395,26 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
return GLFW_FALSE; return GLFW_FALSE;
} }
window->context.source = ctxconfig->source;
if (window->context.major < ctxconfig->major ||
(window->context.major == ctxconfig->major &&
window->context.minor < ctxconfig->minor))
{
// The desired OpenGL version is greater than the actual version
// This only happens if the machine lacks {GLX|WGL}_ARB_create_context
// /and/ the user has requested an OpenGL version greater than 1.0
// For API consistency, we emulate the behavior of the
// {GLX|WGL}_ARB_create_context extension and fail here
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"Requested client API version %i.%i, got version %i.%i",
ctxconfig->major, ctxconfig->minor,
window->context.major, window->context.minor);
return GLFW_FALSE;
}
if (window->context.major >= 3) if (window->context.major >= 3)
{ {
// OpenGL 3.0+ uses a different function for extension string retrieval // OpenGL 3.0+ uses a different function for extension string retrieval
@ -392,7 +431,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
} }
} }
if (window->context.api == GLFW_OPENGL_API) if (window->context.client == GLFW_OPENGL_API)
{ {
// Read back context flags (OpenGL 3.0 and above) // Read back context flags (OpenGL 3.0 and above)
if (window->context.major >= 3) if (window->context.major >= 3)
@ -490,29 +529,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
{ {
PFNGLCLEARPROC glClear = (PFNGLCLEARPROC) glfwGetProcAddress("glClear"); PFNGLCLEARPROC glClear = (PFNGLCLEARPROC) glfwGetProcAddress("glClear");
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
_glfwPlatformSwapBuffers(window); window->context.swapBuffers(window);
}
return GLFW_TRUE;
}
GLFWbool _glfwIsValidContext(const _GLFWctxconfig* ctxconfig)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (window->context.major < ctxconfig->major ||
(window->context.major == ctxconfig->major &&
window->context.minor < ctxconfig->minor))
{
// The desired OpenGL version is greater than the actual version
// This only happens if the machine lacks {GLX|WGL}_ARB_create_context
// /and/ the user has requested an OpenGL version greater than 1.0
// For API consistency, we emulate the behavior of the
// {GLX|WGL}_ARB_create_context extension and fail here
_glfwInputError(GLFW_VERSION_UNAVAILABLE, NULL);
return GLFW_FALSE;
} }
return GLFW_TRUE; return GLFW_TRUE;
@ -552,16 +569,24 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFWwindow* previous = _glfwPlatformGetCurrentContext();
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (window && window->context.api == GLFW_NO_API) if (window && window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return; return;
} }
_glfwPlatformMakeContextCurrent(window); if (previous)
{
if (!window || window->context.source != previous->context.source)
previous->context.makeContextCurrent(NULL);
}
if (window)
window->context.makeContextCurrent(window);
} }
GLFWAPI GLFWwindow* glfwGetCurrentContext(void) GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
@ -573,37 +598,40 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle) GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return; return;
} }
_glfwPlatformSwapBuffers(window); window->context.swapBuffers(window);
} }
GLFWAPI void glfwSwapInterval(int interval) GLFWAPI void glfwSwapInterval(int interval)
{ {
_GLFWwindow* window;
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (!_glfwPlatformGetCurrentContext()) window = _glfwPlatformGetCurrentContext();
if (!window)
{ {
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
return; return;
} }
_glfwPlatformSwapInterval(interval); window->context.swapInterval(interval);
} }
GLFWAPI int glfwExtensionSupported(const char* extension) GLFWAPI int glfwExtensionSupported(const char* extension)
{ {
_GLFWwindow* window; _GLFWwindow* window;
assert(extension); assert(extension != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
@ -616,7 +644,7 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
if (*extension == '\0') if (*extension == '\0')
{ {
_glfwInputError(GLFW_INVALID_VALUE, NULL); _glfwInputError(GLFW_INVALID_VALUE, "Extension name is empty string");
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -636,7 +664,7 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
if (!en) if (!en)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Failed to retrieve extension string %i", i); "Extension string retrieval is broken");
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -653,7 +681,7 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
if (!extensions) if (!extensions)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Failed to retrieve extension string"); "Extension string retrieval is broken");
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -662,21 +690,23 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
} }
// Check if extension is in the platform-specific string // Check if extension is in the platform-specific string
return _glfwPlatformExtensionSupported(extension); return window->context.extensionSupported(extension);
} }
GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname) GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
{ {
assert(procname); _GLFWwindow* window;
assert(procname != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (!_glfwPlatformGetCurrentContext()) window = _glfwPlatformGetCurrentContext();
if (!window)
{ {
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
return NULL; return NULL;
} }
return _glfwPlatformGetProcAddress(procname); return window->context.getProcAddress(procname);
} }

View File

@ -68,9 +68,9 @@ static const char* getErrorString(EGLint error)
return "A NativeWindowType argument does not refer to a valid native window"; return "A NativeWindowType argument does not refer to a valid native window";
case EGL_CONTEXT_LOST: case EGL_CONTEXT_LOST:
return "The application must destroy all contexts and reinitialise"; return "The application must destroy all contexts and reinitialise";
default:
return "ERROR: UNKNOWN EGL ERROR";
} }
return "UNKNOWN EGL ERROR";
} }
// Returns the specified attribute of the specified EGLConfig // Returns the specified attribute of the specified EGLConfig
@ -125,7 +125,7 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
continue; continue;
#endif // _GLFW_X11 #endif // _GLFW_X11
if (ctxconfig->api == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
if (ctxconfig->major == 1) if (ctxconfig->major == 1)
{ {
@ -138,7 +138,7 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
continue; continue;
} }
} }
else if (ctxconfig->api == GLFW_OPENGL_API) else if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT)) if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
continue; continue;
@ -155,18 +155,122 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
u->samples = getConfigAttrib(n, EGL_SAMPLES); u->samples = getConfigAttrib(n, EGL_SAMPLES);
u->doublebuffer = GLFW_TRUE; u->doublebuffer = GLFW_TRUE;
u->egl = n; u->handle = (uintptr_t) n;
usableCount++; usableCount++;
} }
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
if (closest) if (closest)
*result = closest->egl; *result = (EGLConfig) closest->handle;
free(nativeConfigs); free(nativeConfigs);
free(usableConfigs); free(usableConfigs);
return closest ? GLFW_TRUE : GLFW_FALSE; return closest != NULL;
}
static void makeContextCurrent(_GLFWwindow* window)
{
if (window)
{
if (!eglMakeCurrent(_glfw.egl.display,
window->context.egl.surface,
window->context.egl.surface,
window->context.egl.handle))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to make context current: %s",
getErrorString(eglGetError()));
return;
}
}
else
{
if (!eglMakeCurrent(_glfw.egl.display,
EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to clear current context: %s",
getErrorString(eglGetError()));
return;
}
}
_glfwPlatformSetCurrentContext(window);
}
static void swapBuffers(_GLFWwindow* window)
{
if (window != _glfwPlatformGetCurrentContext())
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: The context must be current on the calling thread when swapping buffers");
return;
}
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
}
static void swapInterval(int interval)
{
eglSwapInterval(_glfw.egl.display, interval);
}
static int extensionSupported(const char* extension)
{
const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
return GLFW_FALSE;
}
static GLFWglproc getProcAddress(const char* procname)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (window->context.egl.client)
{
GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client,
procname);
if (proc)
return proc;
}
return eglGetProcAddress(procname);
}
static void destroyContext(_GLFWwindow* window)
{
#if defined(_GLFW_X11)
// NOTE: Do not unload libGL.so.1 while the X11 display is still open,
// as it will make XCloseDisplay segfault
if (window->context.client != GLFW_OPENGL_API)
#endif // _GLFW_X11
{
if (window->context.egl.client)
{
_glfw_dlclose(window->context.egl.client);
window->context.egl.client = NULL;
}
}
if (window->context.egl.surface)
{
eglDestroySurface(_glfw.egl.display, window->context.egl.surface);
window->context.egl.surface = EGL_NO_SURFACE;
}
if (window->context.egl.handle)
{
eglDestroyContext(_glfw.egl.display, window->context.egl.handle);
window->context.egl.handle = EGL_NO_CONTEXT;
}
} }
@ -200,10 +304,7 @@ GLFWbool _glfwInitEGL(void)
} }
if (!_glfw.egl.handle) if (!_glfw.egl.handle)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to load EGL");
return GLFW_FALSE; return GLFW_FALSE;
}
_glfw.egl.GetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC) _glfw.egl.GetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC)
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib"); _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
@ -244,6 +345,8 @@ GLFWbool _glfwInitEGL(void)
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to get EGL display: %s", "EGL: Failed to get EGL display: %s",
getErrorString(eglGetError())); getErrorString(eglGetError()));
_glfwTerminateEGL();
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -252,13 +355,17 @@ GLFWbool _glfwInitEGL(void)
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to initialize EGL: %s", "EGL: Failed to initialize EGL: %s",
getErrorString(eglGetError())); getErrorString(eglGetError()));
_glfwTerminateEGL();
return GLFW_FALSE; return GLFW_FALSE;
} }
_glfw.egl.KHR_create_context = _glfw.egl.KHR_create_context =
_glfwPlatformExtensionSupported("EGL_KHR_create_context"); extensionSupported("EGL_KHR_create_context");
_glfw.egl.KHR_create_context_no_error = _glfw.egl.KHR_create_context_no_error =
_glfwPlatformExtensionSupported("EGL_KHR_create_context_no_error"); extensionSupported("EGL_KHR_create_context_no_error");
_glfw.egl.KHR_gl_colorspace =
extensionSupported("EGL_KHR_gl_colorspace");
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -267,9 +374,14 @@ GLFWbool _glfwInitEGL(void)
// //
void _glfwTerminateEGL(void) void _glfwTerminateEGL(void)
{ {
if (_glfw.egl.handle) if (_glfw.egl.display)
{ {
eglTerminate(_glfw.egl.display); eglTerminate(_glfw.egl.display);
_glfw.egl.display = EGL_NO_DISPLAY;
}
if (_glfw.egl.handle)
{
_glfw_dlclose(_glfw.egl.handle); _glfw_dlclose(_glfw.egl.handle);
_glfw.egl.handle = NULL; _glfw.egl.handle = NULL;
} }
@ -288,10 +400,16 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
{ {
int attribs[40]; EGLint attribs[40];
EGLConfig config; EGLConfig config;
EGLContext share = NULL; EGLContext share = NULL;
if (!_glfw.egl.display)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
return GLFW_FALSE;
}
if (ctxconfig->share) if (ctxconfig->share)
share = ctxconfig->share->context.egl.handle; share = ctxconfig->share->context.egl.handle;
@ -302,7 +420,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
if (ctxconfig->api == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
if (!eglBindAPI(EGL_OPENGL_ES_API)) if (!eglBindAPI(EGL_OPENGL_ES_API))
{ {
@ -327,7 +445,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{ {
int index = 0, mask = 0, flags = 0; int index = 0, mask = 0, flags = 0;
if (ctxconfig->api == GLFW_OPENGL_API) if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if (ctxconfig->forward) if (ctxconfig->forward)
flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
@ -381,7 +499,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{ {
int index = 0; int index = 0;
if (ctxconfig->api == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major); setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
setEGLattrib(EGL_NONE, EGL_NONE); setEGLattrib(EGL_NONE, EGL_NONE);
@ -401,11 +519,26 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
// Set up attributes for surface creation
{
int index = 0;
if (fbconfig->sRGB)
{
if (_glfw.egl.KHR_gl_colorspace)
{
setEGLattrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
}
}
setEGLattrib(EGL_NONE, EGL_NONE);
}
window->context.egl.surface = window->context.egl.surface =
eglCreateWindowSurface(_glfw.egl.display, eglCreateWindowSurface(_glfw.egl.display,
config, config,
_GLFW_EGL_NATIVE_WINDOW, _GLFW_EGL_NATIVE_WINDOW,
NULL); attribs);
if (window->context.egl.surface == EGL_NO_SURFACE) if (window->context.egl.surface == EGL_NO_SURFACE)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
@ -455,7 +588,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
NULL NULL
}; };
if (ctxconfig->api == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
if (ctxconfig->major == 1) if (ctxconfig->major == 1)
sonames = es1sonames; sonames = es1sonames;
@ -480,41 +613,18 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
} }
} }
window->context.makeContextCurrent = makeContextCurrent;
window->context.swapBuffers = swapBuffers;
window->context.swapInterval = swapInterval;
window->context.extensionSupported = extensionSupported;
window->context.getProcAddress = getProcAddress;
window->context.destroyContext = destroyContext;
return GLFW_TRUE; return GLFW_TRUE;
} }
#undef setEGLattrib #undef setEGLattrib
// Destroy the OpenGL context
//
void _glfwDestroyContextEGL(_GLFWwindow* window)
{
#if defined(_GLFW_X11)
// NOTE: Do not unload libGL.so.1 while the X11 display is still open,
// as it will make XCloseDisplay segfault
if (window->context.api != GLFW_OPENGL_API)
#endif // _GLFW_X11
{
if (window->context.egl.client)
{
_glfw_dlclose(window->context.egl.client);
window->context.egl.client = NULL;
}
}
if (window->context.egl.surface)
{
eglDestroySurface(_glfw.egl.display, window->context.egl.surface);
window->context.egl.surface = EGL_NO_SURFACE;
}
if (window->context.egl.handle)
{
eglDestroyContext(_glfw.egl.display, window->context.egl.handle);
window->context.egl.handle = EGL_NO_CONTEXT;
}
}
// Returns the Visual and depth of the chosen EGLConfig // Returns the Visual and depth of the chosen EGLConfig
// //
#if defined(_GLFW_X11) #if defined(_GLFW_X11)
@ -558,75 +668,6 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
#endif // _GLFW_X11 #endif // _GLFW_X11
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
{
if (window)
{
eglMakeCurrent(_glfw.egl.display,
window->context.egl.surface,
window->context.egl.surface,
window->context.egl.handle);
}
else
{
eglMakeCurrent(_glfw.egl.display,
EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT);
}
_glfwPlatformSetCurrentContext(window);
}
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
{
if (window != _glfwPlatformGetCurrentContext())
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: The context must be current on the calling thread when swapping buffers");
return;
}
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
}
void _glfwPlatformSwapInterval(int interval)
{
eglSwapInterval(_glfw.egl.display, interval);
}
int _glfwPlatformExtensionSupported(const char* extension)
{
const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
return GLFW_FALSE;
}
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (window->context.egl.client)
{
GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client,
procname);
if (proc)
return proc;
}
return eglGetProcAddress(procname);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -642,7 +683,7 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT);
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return EGL_NO_CONTEXT; return EGL_NO_CONTEXT;
@ -656,7 +697,7 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE);
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return EGL_NO_SURFACE; return EGL_NO_SURFACE;

View File

@ -104,6 +104,8 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30fd #define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30fd
#define EGL_CONTEXT_FLAGS_KHR 0x30fc #define EGL_CONTEXT_FLAGS_KHR 0x30fc
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3 #define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3
#define EGL_GL_COLORSPACE_KHR 0x309d
#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
typedef int EGLint; typedef int EGLint;
typedef unsigned int EGLBoolean; typedef unsigned int EGLBoolean;
@ -147,9 +149,8 @@ typedef GLFWglproc (EGLAPIENTRY * PFNEGLGETPROCADDRESSPROC)(const char*);
#define eglQueryString _glfw.egl.QueryString #define eglQueryString _glfw.egl.QueryString
#define eglGetProcAddress _glfw.egl.GetProcAddress #define eglGetProcAddress _glfw.egl.GetProcAddress
#define _GLFW_PLATFORM_FBCONFIG EGLConfig egl #define _GLFW_EGL_CONTEXT_STATE _GLFWcontextEGL egl
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextEGL egl #define _GLFW_EGL_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl
// EGL-specific per-context data // EGL-specific per-context data
@ -174,6 +175,7 @@ typedef struct _GLFWlibraryEGL
GLFWbool KHR_create_context; GLFWbool KHR_create_context;
GLFWbool KHR_create_context_no_error; GLFWbool KHR_create_context_no_error;
GLFWbool KHR_gl_colorspace;
void* handle; void* handle;
@ -202,7 +204,6 @@ void _glfwTerminateEGL(void);
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
void _glfwDestroyContextEGL(_GLFWwindow* window);
#if defined(_GLFW_X11) #if defined(_GLFW_X11)
GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig, GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig, const _GLFWfbconfig* fbconfig,

View File

@ -45,23 +45,12 @@
// Define this to 1 if building GLFW for Mir // Define this to 1 if building GLFW for Mir
#cmakedefine _GLFW_MIR #cmakedefine _GLFW_MIR
// Define this to 1 if building GLFW for EGL
#cmakedefine _GLFW_EGL
// Define this to 1 if building GLFW for GLX
#cmakedefine _GLFW_GLX
// Define this to 1 if building GLFW for WGL
#cmakedefine _GLFW_WGL
// Define this to 1 if building GLFW for NSGL
#cmakedefine _GLFW_NSGL
// Define this to 1 if building as a shared library / dynamic library / DLL // Define this to 1 if building as a shared library / dynamic library / DLL
#cmakedefine _GLFW_BUILD_DLL #cmakedefine _GLFW_BUILD_DLL
// Define this to 1 to force use of high-performance GPU on hybrid systems // Define this to 1 to force use of high-performance GPU on hybrid systems
#cmakedefine _GLFW_USE_HYBRID_HPG #cmakedefine _GLFW_USE_HYBRID_HPG
// Define this to 1 if the XInput X11 extension is available
#cmakedefine _GLFW_HAS_XINPUT
// Define this to 1 if the Xxf86vm X11 extension is available // Define this to 1 if the Xxf86vm X11 extension is available
#cmakedefine _GLFW_HAS_XF86VM #cmakedefine _GLFW_HAS_XF86VM

View File

@ -115,18 +115,18 @@ static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result
if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB) if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)
u->sRGB = getFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB); u->sRGB = getFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
u->glx = n; u->handle = (uintptr_t) n;
usableCount++; usableCount++;
} }
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
if (closest) if (closest)
*result = closest->glx; *result = (GLXFBConfig) closest->handle;
XFree(nativeConfigs); XFree(nativeConfigs);
free(usableConfigs); free(usableConfigs);
return closest ? GLFW_TRUE : GLFW_FALSE; return closest != NULL;
} }
// Create the OpenGL context using legacy API // Create the OpenGL context using legacy API
@ -142,6 +142,96 @@ static GLXContext createLegacyContext(_GLFWwindow* window,
True); True);
} }
static void makeContextCurrent(_GLFWwindow* window)
{
if (window)
{
if (!glXMakeCurrent(_glfw.x11.display,
window->context.glx.window,
window->context.glx.handle))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"GLX: Failed to make context current");
return;
}
}
else
{
if (!glXMakeCurrent(_glfw.x11.display, None, NULL))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"GLX: Failed to clear current context");
return;
}
}
_glfwPlatformSetCurrentContext(window);
}
static void swapBuffers(_GLFWwindow* window)
{
glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
}
static void swapInterval(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (_glfw.glx.EXT_swap_control)
{
_glfw.glx.SwapIntervalEXT(_glfw.x11.display,
window->context.glx.window,
interval);
}
else if (_glfw.glx.MESA_swap_control)
_glfw.glx.SwapIntervalMESA(interval);
else if (_glfw.glx.SGI_swap_control)
{
if (interval > 0)
_glfw.glx.SwapIntervalSGI(interval);
}
}
static int extensionSupported(const char* extension)
{
const char* extensions =
glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
return GLFW_FALSE;
}
static GLFWglproc getProcAddress(const char* procname)
{
if (_glfw.glx.GetProcAddress)
return _glfw.glx.GetProcAddress((const GLubyte*) procname);
else if (_glfw.glx.GetProcAddressARB)
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
else
return dlsym(_glfw.glx.handle, procname);
}
// Destroy the OpenGL context
//
static void destroyContext(_GLFWwindow* window)
{
if (window->context.glx.window)
{
glXDestroyWindow(_glfw.x11.display, window->context.glx.window);
window->context.glx.window = None;
}
if (window->context.glx.handle)
{
glXDestroyContext(_glfw.x11.display, window->context.glx.handle);
window->context.glx.handle = NULL;
}
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
@ -163,7 +253,6 @@ GLFWbool _glfwInitGLX(void)
NULL NULL
}; };
for (i = 0; sonames[i]; i++) for (i = 0; sonames[i]; i++)
{ {
_glfw.glx.handle = dlopen(sonames[i], RTLD_LAZY | RTLD_GLOBAL); _glfw.glx.handle = dlopen(sonames[i], RTLD_LAZY | RTLD_GLOBAL);
@ -230,61 +319,61 @@ GLFWbool _glfwInitGLX(void)
return GLFW_FALSE; return GLFW_FALSE;
} }
if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) if (extensionSupported("GLX_EXT_swap_control"))
{ {
_glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) _glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)
_glfwPlatformGetProcAddress("glXSwapIntervalEXT"); getProcAddress("glXSwapIntervalEXT");
if (_glfw.glx.SwapIntervalEXT) if (_glfw.glx.SwapIntervalEXT)
_glfw.glx.EXT_swap_control = GLFW_TRUE; _glfw.glx.EXT_swap_control = GLFW_TRUE;
} }
if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) if (extensionSupported("GLX_SGI_swap_control"))
{ {
_glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) _glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
_glfwPlatformGetProcAddress("glXSwapIntervalSGI"); getProcAddress("glXSwapIntervalSGI");
if (_glfw.glx.SwapIntervalSGI) if (_glfw.glx.SwapIntervalSGI)
_glfw.glx.SGI_swap_control = GLFW_TRUE; _glfw.glx.SGI_swap_control = GLFW_TRUE;
} }
if (_glfwPlatformExtensionSupported("GLX_MESA_swap_control")) if (extensionSupported("GLX_MESA_swap_control"))
{ {
_glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) _glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)
_glfwPlatformGetProcAddress("glXSwapIntervalMESA"); getProcAddress("glXSwapIntervalMESA");
if (_glfw.glx.SwapIntervalMESA) if (_glfw.glx.SwapIntervalMESA)
_glfw.glx.MESA_swap_control = GLFW_TRUE; _glfw.glx.MESA_swap_control = GLFW_TRUE;
} }
if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) if (extensionSupported("GLX_ARB_multisample"))
_glfw.glx.ARB_multisample = GLFW_TRUE; _glfw.glx.ARB_multisample = GLFW_TRUE;
if (_glfwPlatformExtensionSupported("GLX_ARB_framebuffer_sRGB")) if (extensionSupported("GLX_ARB_framebuffer_sRGB"))
_glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE; _glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
if (_glfwPlatformExtensionSupported("GLX_EXT_framebuffer_sRGB")) if (extensionSupported("GLX_EXT_framebuffer_sRGB"))
_glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE; _glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) if (extensionSupported("GLX_ARB_create_context"))
{ {
_glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) _glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
_glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); getProcAddress("glXCreateContextAttribsARB");
if (_glfw.glx.CreateContextAttribsARB) if (_glfw.glx.CreateContextAttribsARB)
_glfw.glx.ARB_create_context = GLFW_TRUE; _glfw.glx.ARB_create_context = GLFW_TRUE;
} }
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) if (extensionSupported("GLX_ARB_create_context_robustness"))
_glfw.glx.ARB_create_context_robustness = GLFW_TRUE; _glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) if (extensionSupported("GLX_ARB_create_context_profile"))
_glfw.glx.ARB_create_context_profile = GLFW_TRUE; _glfw.glx.ARB_create_context_profile = GLFW_TRUE;
if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) if (extensionSupported("GLX_EXT_create_context_es2_profile"))
_glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE; _glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
if (_glfwPlatformExtensionSupported("GLX_ARB_context_flush_control")) if (extensionSupported("GLX_ARB_context_flush_control"))
_glfw.glx.ARB_context_flush_control = GLFW_TRUE; _glfw.glx.ARB_context_flush_control = GLFW_TRUE;
return GLFW_TRUE; return GLFW_TRUE;
@ -331,7 +420,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
if (ctxconfig->api == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
if (!_glfw.glx.ARB_create_context || if (!_glfw.glx.ARB_create_context ||
!_glfw.glx.ARB_create_context_profile || !_glfw.glx.ARB_create_context_profile ||
@ -370,7 +459,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
{ {
int index = 0, mask = 0, flags = 0; int index = 0, mask = 0, flags = 0;
if (ctxconfig->api == GLFW_OPENGL_API) if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if (ctxconfig->forward) if (ctxconfig->forward)
flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
@ -455,7 +544,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
if (!window->context.glx.handle) if (!window->context.glx.handle)
{ {
if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB && if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
ctxconfig->api == GLFW_OPENGL_API && ctxconfig->client == GLFW_OPENGL_API &&
ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE && ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
ctxconfig->forward == GLFW_FALSE) ctxconfig->forward == GLFW_FALSE)
{ {
@ -483,28 +572,18 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
window->context.makeContextCurrent = makeContextCurrent;
window->context.swapBuffers = swapBuffers;
window->context.swapInterval = swapInterval;
window->context.extensionSupported = extensionSupported;
window->context.getProcAddress = getProcAddress;
window->context.destroyContext = destroyContext;
return GLFW_TRUE; return GLFW_TRUE;
} }
#undef setGLXattrib #undef setGLXattrib
// Destroy the OpenGL context
//
void _glfwDestroyContextGLX(_GLFWwindow* window)
{
if (window->context.glx.window)
{
glXDestroyWindow(_glfw.x11.display, window->context.glx.window);
window->context.glx.window = None;
}
if (window->context.glx.handle)
{
glXDestroyContext(_glfw.x11.display, window->context.glx.handle);
window->context.glx.handle = NULL;
}
}
// Returns the Visual and depth of the chosen GLXFBConfig // Returns the Visual and depth of the chosen GLXFBConfig
// //
GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig, GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
@ -537,72 +616,6 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
} }
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
{
if (window)
{
glXMakeCurrent(_glfw.x11.display,
window->context.glx.window,
window->context.glx.handle);
}
else
glXMakeCurrent(_glfw.x11.display, None, NULL);
_glfwPlatformSetCurrentContext(window);
}
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
{
glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
}
void _glfwPlatformSwapInterval(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (_glfw.glx.EXT_swap_control)
{
_glfw.glx.SwapIntervalEXT(_glfw.x11.display,
window->context.glx.window,
interval);
}
else if (_glfw.glx.MESA_swap_control)
_glfw.glx.SwapIntervalMESA(interval);
else if (_glfw.glx.SGI_swap_control)
{
if (interval > 0)
_glfw.glx.SwapIntervalSGI(interval);
}
}
int _glfwPlatformExtensionSupported(const char* extension)
{
const char* extensions =
glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
return GLFW_FALSE;
}
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
{
if (_glfw.glx.GetProcAddress)
return _glfw.glx.GetProcAddress((const GLubyte*) procname);
else if (_glfw.glx.GetProcAddressARB)
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
else
return dlsym(_glfw.glx.handle, procname);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -612,7 +625,7 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL; return NULL;
@ -626,7 +639,7 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(None); _GLFW_REQUIRE_INIT_OR_RETURN(None);
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return None; return None;

View File

@ -108,7 +108,6 @@ typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow);
#define glXCreateWindow _glfw.glx.CreateWindow #define glXCreateWindow _glfw.glx.CreateWindow
#define glXDestroyWindow _glfw.glx.DestroyWindow #define glXDestroyWindow _glfw.glx.DestroyWindow
#define _GLFW_PLATFORM_FBCONFIG GLXFBConfig glx
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx

View File

@ -74,9 +74,9 @@ static const char* getErrorString(int error)
return "The requested format is unavailable"; return "The requested format is unavailable";
case GLFW_NO_WINDOW_CONTEXT: case GLFW_NO_WINDOW_CONTEXT:
return "The specified window has no context"; return "The specified window has no context";
default:
return "ERROR: UNKNOWN GLFW ERROR";
} }
return "ERROR: UNKNOWN ERROR TOKEN PASSED TO glfwErrorString";
} }
@ -135,6 +135,8 @@ GLFWAPI int glfwInit(void)
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount); _glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
_glfwInitialized = GLFW_TRUE; _glfwInitialized = GLFW_TRUE;
_glfw.timerOffset = _glfwPlatformGetTimerValue();
// Not all window hints have zero as their default value // Not all window hints have zero as their default value
glfwDefaultWindowHints(); glfwDefaultWindowHints();

View File

@ -44,7 +44,7 @@ static void setCursorMode(_GLFWwindow* window, int newMode)
newMode != GLFW_CURSOR_HIDDEN && newMode != GLFW_CURSOR_HIDDEN &&
newMode != GLFW_CURSOR_DISABLED) newMode != GLFW_CURSOR_DISABLED)
{ {
_glfwInputError(GLFW_INVALID_ENUM, "Invalid cursor mode"); _glfwInputError(GLFW_INVALID_ENUM, "Invalid cursor mode %i", newMode);
return; return;
} }
@ -220,6 +220,12 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
window->callbacks.drop((GLFWwindow*) window, count, paths); window->callbacks.drop((GLFWwindow*) window, count, paths);
} }
void _glfwInputJoystickChange(int joy, int event)
{
if (_glfw.callbacks.joystick)
_glfw.callbacks.joystick(joy, event);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
@ -240,7 +246,7 @@ GLFWbool _glfwIsPrintable(int key)
GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode) GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(0); _GLFW_REQUIRE_INIT_OR_RETURN(0);
@ -253,7 +259,7 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
case GLFW_STICKY_MOUSE_BUTTONS: case GLFW_STICKY_MOUSE_BUTTONS:
return window->stickyMouseButtons; return window->stickyMouseButtons;
default: default:
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode"); _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
return 0; return 0;
} }
} }
@ -261,7 +267,7 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
@ -277,7 +283,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
setStickyMouseButtons(window, value ? GLFW_TRUE : GLFW_FALSE); setStickyMouseButtons(window, value ? GLFW_TRUE : GLFW_FALSE);
break; break;
default: default:
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode"); _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
break; break;
} }
} }
@ -291,13 +297,13 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode)
GLFWAPI int glfwGetKey(GLFWwindow* handle, int key) GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
if (key < 0 || key > GLFW_KEY_LAST) if (key < 0 || key > GLFW_KEY_LAST)
{ {
_glfwInputError(GLFW_INVALID_ENUM, "Invalid key"); _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
return GLFW_RELEASE; return GLFW_RELEASE;
} }
@ -314,14 +320,13 @@ GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button) GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
{ {
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button);
"Invalid mouse button");
return GLFW_RELEASE; return GLFW_RELEASE;
} }
@ -338,7 +343,7 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button)
GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos) GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
if (xpos) if (xpos)
*xpos = 0; *xpos = 0;
@ -361,7 +366,7 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos)
GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos) GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
@ -385,7 +390,7 @@ GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
{ {
_GLFWcursor* cursor; _GLFWcursor* cursor;
assert(image); assert(image != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@ -415,7 +420,7 @@ GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
shape != GLFW_HRESIZE_CURSOR && shape != GLFW_HRESIZE_CURSOR &&
shape != GLFW_VRESIZE_CURSOR) shape != GLFW_VRESIZE_CURSOR)
{ {
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor"); _glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor %i", shape);
return NULL; return NULL;
} }
@ -471,7 +476,7 @@ GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle)
{ {
_GLFWwindow* window = (_GLFWwindow*) windowHandle; _GLFWwindow* window = (_GLFWwindow*) windowHandle;
_GLFWcursor* cursor = (_GLFWcursor*) cursorHandle; _GLFWcursor* cursor = (_GLFWcursor*) cursorHandle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
@ -483,7 +488,7 @@ GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle)
GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun) GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.key, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.key, cbfun);
@ -493,7 +498,7 @@ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun)
GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun) GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.character, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.character, cbfun);
@ -503,7 +508,7 @@ GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun)
GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun) GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.charmods, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.charmods, cbfun);
@ -514,7 +519,7 @@ GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle,
GLFWmousebuttonfun cbfun) GLFWmousebuttonfun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.mouseButton, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.mouseButton, cbfun);
@ -525,7 +530,7 @@ GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle,
GLFWcursorposfun cbfun) GLFWcursorposfun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.cursorPos, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.cursorPos, cbfun);
@ -536,7 +541,7 @@ GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle,
GLFWcursorenterfun cbfun) GLFWcursorenterfun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.cursorEnter, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.cursorEnter, cbfun);
@ -547,7 +552,7 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle,
GLFWscrollfun cbfun) GLFWscrollfun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.scroll, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.scroll, cbfun);
@ -557,7 +562,7 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle,
GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun) GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.drop, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.drop, cbfun);
@ -570,7 +575,7 @@ GLFWAPI int glfwJoystickPresent(int joy)
if (joy < 0 || joy > GLFW_JOYSTICK_LAST) if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
{ {
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick"); _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
return 0; return 0;
} }
@ -579,14 +584,14 @@ GLFWAPI int glfwJoystickPresent(int joy)
GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count) GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count)
{ {
assert(count); assert(count != NULL);
*count = 0; *count = 0;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (joy < 0 || joy > GLFW_JOYSTICK_LAST) if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
{ {
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick"); _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
return NULL; return NULL;
} }
@ -595,14 +600,14 @@ GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count)
GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count) GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count)
{ {
assert(count); assert(count != NULL);
*count = 0; *count = 0;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (joy < 0 || joy > GLFW_JOYSTICK_LAST) if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
{ {
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick"); _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
return NULL; return NULL;
} }
@ -615,19 +620,26 @@ GLFWAPI const char* glfwGetJoystickName(int joy)
if (joy < 0 || joy > GLFW_JOYSTICK_LAST) if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
{ {
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick"); _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
return NULL; return NULL;
} }
return _glfwPlatformGetJoystickName(joy); return _glfwPlatformGetJoystickName(joy);
} }
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun);
return cbfun;
}
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string) GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
assert(string); assert(string != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_glfwPlatformSetClipboardString(window, string); _glfwPlatformSetClipboardString(window, string);
@ -636,7 +648,7 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle) GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return _glfwPlatformGetClipboardString(window); return _glfwPlatformGetClipboardString(window);
@ -645,7 +657,8 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
GLFWAPI double glfwGetTime(void) GLFWAPI double glfwGetTime(void)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(0.0); _GLFW_REQUIRE_INIT_OR_RETURN(0.0);
return _glfwPlatformGetTime(); return (double) (_glfwPlatformGetTimerValue() - _glfw.timerOffset) /
_glfwPlatformGetTimerFrequency();
} }
GLFWAPI void glfwSetTime(double time) GLFWAPI void glfwSetTime(double time)
@ -654,10 +667,23 @@ GLFWAPI void glfwSetTime(double time)
if (time != time || time < 0.0 || time > 18446744073.0) if (time != time || time < 0.0 || time > 18446744073.0)
{ {
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time"); _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
return; return;
} }
_glfwPlatformSetTime(time); _glfw.timerOffset = _glfwPlatformGetTimerValue() -
(uint64_t) (time * _glfwPlatformGetTimerFrequency());
}
GLFWAPI uint64_t glfwGetTimerValue(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(0);
return _glfwPlatformGetTimerValue();
}
GLFWAPI uint64_t glfwGetTimerFrequency(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(0);
return _glfwPlatformGetTimerFrequency();
} }

View File

@ -47,15 +47,6 @@
#define GLFW_INCLUDE_NONE #define GLFW_INCLUDE_NONE
#include "../include/GLFW/glfw3.h" #include "../include/GLFW/glfw3.h"
#include <stddef.h>
#if defined(_MSC_VER) && (_MSC_VER < 1600)
typedef unsigned __int64 GLFWuint64;
#else
#include <stdint.h>
typedef uint64_t GLFWuint64;
#endif
typedef int GLFWbool; typedef int GLFWbool;
typedef struct _GLFWwndconfig _GLFWwndconfig; typedef struct _GLFWwndconfig _GLFWwndconfig;
@ -67,6 +58,13 @@ typedef struct _GLFWlibrary _GLFWlibrary;
typedef struct _GLFWmonitor _GLFWmonitor; typedef struct _GLFWmonitor _GLFWmonitor;
typedef struct _GLFWcursor _GLFWcursor; typedef struct _GLFWcursor _GLFWcursor;
typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
typedef void (* _GLFWswapintervalfun)(int);
typedef int (* _GLFWextensionsupportedfun)(const char*);
typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*);
typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
#define GL_VERSION 0x1f02 #define GL_VERSION 0x1f02
#define GL_NONE 0 #define GL_NONE 0
#define GL_COLOR_BUFFER_BIT 0x00004000 #define GL_COLOR_BUFFER_BIT 0x00004000
@ -100,9 +98,9 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
typedef void* VkInstance; typedef void* VkInstance;
typedef void* VkPhysicalDevice; typedef void* VkPhysicalDevice;
typedef GLFWuint64 VkSurfaceKHR; typedef uint64_t VkSurfaceKHR;
typedef unsigned int VkFlags; typedef uint32_t VkFlags;
typedef unsigned int VkBool32; typedef uint32_t VkBool32;
typedef enum VkStructureType typedef enum VkStructureType
{ {
@ -147,12 +145,12 @@ typedef struct VkAllocationCallbacks VkAllocationCallbacks;
typedef struct VkExtensionProperties typedef struct VkExtensionProperties
{ {
char extensionName[256]; char extensionName[256];
unsigned int specVersion; uint32_t specVersion;
} VkExtensionProperties; } VkExtensionProperties;
typedef void (APIENTRY * PFN_vkVoidFunction)(void); typedef void (APIENTRY * PFN_vkVoidFunction)(void);
typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*); typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*);
typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,unsigned int*,VkExtensionProperties*); typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*);
#define vkEnumerateInstanceExtensionProperties _glfw.vk.EnumerateInstanceExtensionProperties #define vkEnumerateInstanceExtensionProperties _glfw.vk.EnumerateInstanceExtensionProperties
#define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr #define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr
@ -255,8 +253,7 @@ struct _GLFWwndconfig
GLFWbool focused; GLFWbool focused;
GLFWbool autoIconify; GLFWbool autoIconify;
GLFWbool floating; GLFWbool floating;
GLFWbool transparent; GLFWbool maximized;
_GLFWmonitor* monitor;
}; };
@ -268,7 +265,8 @@ struct _GLFWwndconfig
*/ */
struct _GLFWctxconfig struct _GLFWctxconfig
{ {
int api; int client;
int source;
int major; int major;
int minor; int minor;
GLFWbool forward; GLFWbool forward;
@ -306,10 +304,7 @@ struct _GLFWfbconfig
int samples; int samples;
GLFWbool sRGB; GLFWbool sRGB;
GLFWbool doublebuffer; GLFWbool doublebuffer;
int transparent; uintptr_t handle;
// This is defined in the context API's context.h
_GLFW_PLATFORM_FBCONFIG;
}; };
@ -317,7 +312,8 @@ struct _GLFWfbconfig
*/ */
struct _GLFWcontext struct _GLFWcontext
{ {
int api; int client;
int source;
int major, minor, revision; int major, minor, revision;
GLFWbool forward, debug, noerror; GLFWbool forward, debug, noerror;
int profile; int profile;
@ -328,8 +324,17 @@ struct _GLFWcontext
PFNGLGETINTEGERVPROC GetIntegerv; PFNGLGETINTEGERVPROC GetIntegerv;
PFNGLGETSTRINGPROC GetString; PFNGLGETSTRINGPROC GetString;
_GLFWmakecontextcurrentfun makeContextCurrent;
_GLFWswapbuffersfun swapBuffers;
_GLFWswapintervalfun swapInterval;
_GLFWextensionsupportedfun extensionSupported;
_GLFWgetprocaddressfun getProcAddress;
_GLFWdestroycontextfun destroyContext;
// This is defined in the context API's context.h // This is defined in the context API's context.h
_GLFW_PLATFORM_CONTEXT_STATE; _GLFW_PLATFORM_CONTEXT_STATE;
// This is defined in egl_context.h
_GLFW_EGL_CONTEXT_STATE;
}; };
@ -351,6 +356,10 @@ struct _GLFWwindow
_GLFWmonitor* monitor; _GLFWmonitor* monitor;
_GLFWcursor* cursor; _GLFWcursor* cursor;
int minwidth, minheight;
int maxwidth, maxheight;
int numer, denom;
// Window input state // Window input state
GLFWbool stickyKeys; GLFWbool stickyKeys;
GLFWbool stickyMouseButtons; GLFWbool stickyMouseButtons;
@ -393,6 +402,9 @@ struct _GLFWmonitor
// Physical dimensions in millimeters. // Physical dimensions in millimeters.
int widthMM, heightMM; int widthMM, heightMM;
// The window whose video mode is current on this monitor
_GLFWwindow* window;
GLFWvidmode* modes; GLFWvidmode* modes;
int modeCount; int modeCount;
GLFWvidmode currentMode; GLFWvidmode currentMode;
@ -436,11 +448,13 @@ struct _GLFWlibrary
_GLFWmonitor** monitors; _GLFWmonitor** monitors;
int monitorCount; int monitorCount;
uint64_t timerOffset;
struct { struct {
GLFWbool available; GLFWbool available;
void* handle; void* handle;
char** extensions; char** extensions;
int extensionCount; uint32_t extensionCount;
PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties; PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
PFN_vkGetInstanceProcAddr GetInstanceProcAddr; PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
GLFWbool KHR_surface; GLFWbool KHR_surface;
@ -453,6 +467,7 @@ struct _GLFWlibrary
struct { struct {
GLFWmonitorfun monitor; GLFWmonitorfun monitor;
GLFWjoystickfun joystick;
} callbacks; } callbacks;
// This is defined in the window API's platform.h // This is defined in the window API's platform.h
@ -465,6 +480,8 @@ struct _GLFWlibrary
_GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE; _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE;
// This is defined in the platform's tls.h // This is defined in the platform's tls.h
_GLFW_PLATFORM_LIBRARY_TLS_STATE; _GLFW_PLATFORM_LIBRARY_TLS_STATE;
// This is defined in egl_context.h
_GLFW_EGL_LIBRARY_CONTEXT_STATE;
}; };
@ -600,15 +617,15 @@ const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count);
*/ */
const char* _glfwPlatformGetJoystickName(int joy); const char* _glfwPlatformGetJoystickName(int joy);
/*! @copydoc glfwGetTime /*! @copydoc glfwGetTimerValue
* @ingroup platform * @ingroup platform
*/ */
double _glfwPlatformGetTime(void); uint64_t _glfwPlatformGetTimerValue(void);
/*! @copydoc glfwSetTime /*! @copydoc glfwGetTimerFrequency
* @ingroup platform * @ingroup platform
*/ */
void _glfwPlatformSetTime(double time); uint64_t _glfwPlatformGetTimerFrequency(void);
/*! @ingroup platform /*! @ingroup platform
*/ */
@ -626,6 +643,11 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window);
*/ */
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title); void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title);
/*! @copydoc glfwSetWindowIcon
* @ingroup platform
*/
void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count, const GLFWimage* images);
/*! @copydoc glfwGetWindowPos /*! @copydoc glfwGetWindowPos
* @ingroup platform * @ingroup platform
*/ */
@ -676,20 +698,31 @@ void _glfwPlatformIconifyWindow(_GLFWwindow* window);
*/ */
void _glfwPlatformRestoreWindow(_GLFWwindow* window); void _glfwPlatformRestoreWindow(_GLFWwindow* window);
/*! @copydoc glfwMaximizeWindow
* @ingroup platform
*/
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
/*! @copydoc glfwShowWindow /*! @copydoc glfwShowWindow
* @ingroup platform * @ingroup platform
*/ */
void _glfwPlatformShowWindow(_GLFWwindow* window); void _glfwPlatformShowWindow(_GLFWwindow* window);
/*! @ingroup platform
*/
void _glfwPlatformUnhideWindow(_GLFWwindow* window);
/*! @copydoc glfwHideWindow /*! @copydoc glfwHideWindow
* @ingroup platform * @ingroup platform
*/ */
void _glfwPlatformHideWindow(_GLFWwindow* window); void _glfwPlatformHideWindow(_GLFWwindow* window);
/*! @copydoc glfwFocusWindow
* @ingroup platform
*/
void _glfwPlatformFocusWindow(_GLFWwindow* window);
/*! @copydoc glfwSetWindowMonitor
* @ingroup platform
*/
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
/*! @brief Returns whether the window is focused. /*! @brief Returns whether the window is focused.
* @ingroup platform * @ingroup platform
*/ */
@ -705,6 +738,11 @@ int _glfwPlatformWindowIconified(_GLFWwindow* window);
*/ */
int _glfwPlatformWindowVisible(_GLFWwindow* window); int _glfwPlatformWindowVisible(_GLFWwindow* window);
/*! @brief Returns whether the window is maximized.
* @ingroup platform
*/
int _glfwPlatformWindowMaximized(_GLFWwindow* window);
/*! @copydoc glfwPollEvents /*! @copydoc glfwPollEvents
* @ingroup platform * @ingroup platform
*/ */
@ -715,16 +753,16 @@ void _glfwPlatformPollEvents(void);
*/ */
void _glfwPlatformWaitEvents(void); void _glfwPlatformWaitEvents(void);
/*! @copydoc glfwWaitEventsTimeout
* @ingroup platform
*/
void _glfwPlatformWaitEventsTimeout(double timeout);
/*! @copydoc glfwPostEmptyEvent /*! @copydoc glfwPostEmptyEvent
* @ingroup platform * @ingroup platform
*/ */
void _glfwPlatformPostEmptyEvent(void); void _glfwPlatformPostEmptyEvent(void);
/*! @copydoc glfwMakeContextCurrent
* @ingroup platform
*/
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window);
/*! @ingroup platform /*! @ingroup platform
*/ */
void _glfwPlatformSetCurrentContext(_GLFWwindow* context); void _glfwPlatformSetCurrentContext(_GLFWwindow* context);
@ -734,26 +772,6 @@ void _glfwPlatformSetCurrentContext(_GLFWwindow* context);
*/ */
_GLFWwindow* _glfwPlatformGetCurrentContext(void); _GLFWwindow* _glfwPlatformGetCurrentContext(void);
/*! @copydoc glfwSwapBuffers
* @ingroup platform
*/
void _glfwPlatformSwapBuffers(_GLFWwindow* window);
/*! @copydoc glfwSwapInterval
* @ingroup platform
*/
void _glfwPlatformSwapInterval(int interval);
/*! @copydoc glfwExtensionSupported
* @ingroup platform
*/
int _glfwPlatformExtensionSupported(const char* extension);
/*! @copydoc glfwGetProcAddress
* @ingroup platform
*/
GLFWglproc _glfwPlatformGetProcAddress(const char* procname);
/*! @copydoc glfwCreateCursor /*! @copydoc glfwCreateCursor
* @ingroup platform * @ingroup platform
*/ */
@ -776,11 +794,11 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
/*! @ingroup platform /*! @ingroup platform
*/ */
char** _glfwPlatformGetRequiredInstanceExtensions(int* count); char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count);
/*! @ingroup platform /*! @ingroup platform
*/ */
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, unsigned int queuefamily); int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
/*! @ingroup platform /*! @ingroup platform
*/ */
@ -842,6 +860,8 @@ void _glfwInputWindowDamage(_GLFWwindow* window);
*/ */
void _glfwInputWindowCloseRequest(_GLFWwindow* window); void _glfwInputWindowCloseRequest(_GLFWwindow* window);
void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor);
/*! @brief Notifies shared code of a physical key event. /*! @brief Notifies shared code of a physical key event.
* @param[in] window The window that received the event. * @param[in] window The window that received the event.
* @param[in] key The key that was pressed or released. * @param[in] key The key that was pressed or released.
@ -900,6 +920,10 @@ void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
*/ */
void _glfwInputMonitorChange(void); void _glfwInputMonitorChange(void);
/*! @ingroup event
*/
void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window);
/*! @brief Notifies shared code of an error. /*! @brief Notifies shared code of an error.
* @param[in] error The error code most suitable for the error. * @param[in] error The error code most suitable for the error.
* @param[in] format The `printf` style format string of the error * @param[in] format The `printf` style format string of the error
@ -920,6 +944,13 @@ void _glfwInputError(int error, const char* format, ...);
*/ */
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names); void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
/*! @brief Notifies shared code of a joystick connection/disconnection event.
* @param[in] joy The joystick that was connected or disconnected.
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
* @ingroup event
*/
void _glfwInputJoystickChange(int joy, int event);
//======================================================================== //========================================================================
// Utility functions // Utility functions
@ -980,15 +1011,6 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig);
*/ */
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig); GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
/*! @brief Checks whether the current context fulfils the specified hard
* constraints.
* @param[in] ctxconfig The desired context attributes.
* @return `GLFW_TRUE` if the context fulfils the hard constraints, or
* `GLFW_FALSE` otherwise.
* @ingroup utility
*/
GLFWbool _glfwIsValidContext(const _GLFWctxconfig* ctxconfig);
/*! @ingroup utility /*! @ingroup utility
*/ */
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size); void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size);

View File

@ -45,9 +45,9 @@
// Attempt to open the specified joystick device // Attempt to open the specified joystick device
// //
#if defined(__linux__)
static GLFWbool openJoystickDevice(const char* path) static GLFWbool openJoystickDevice(const char* path)
{ {
#if defined(__linux__)
char axisCount, buttonCount; char axisCount, buttonCount;
char name[256]; char name[256];
int joy, fd, version; int joy, fd, version;
@ -100,34 +100,18 @@ static GLFWbool openJoystickDevice(const char* path)
ioctl(fd, JSIOCGBUTTONS, &buttonCount); ioctl(fd, JSIOCGBUTTONS, &buttonCount);
js->buttonCount = (int) buttonCount; js->buttonCount = (int) buttonCount;
js->buttons = calloc(buttonCount, 1); js->buttons = calloc(buttonCount, 1);
#endif // __linux__
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
return GLFW_TRUE; return GLFW_TRUE;
} }
#endif // __linux__
// Polls for and processes events the specified joystick // Polls for and processes events the specified joystick
// //
static GLFWbool pollJoystickEvents(_GLFWjoystickLinux* js) static GLFWbool pollJoystickEvents(_GLFWjoystickLinux* js)
{ {
#if defined(__linux__) #if defined(__linux__)
ssize_t offset = 0; _glfwPollJoystickEvents();
char buffer[16384];
const ssize_t size = read(_glfw.linux_js.inotify, buffer, sizeof(buffer));
while (size > offset)
{
regmatch_t match;
const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
if (regexec(&_glfw.linux_js.regex, e->name, 1, &match, 0) == 0)
{
char path[20];
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
openJoystickDevice(path);
}
offset += sizeof(struct inotify_event) + e->len;
}
if (!js->present) if (!js->present)
return GLFW_FALSE; return GLFW_FALSE;
@ -149,6 +133,9 @@ static GLFWbool pollJoystickEvents(_GLFWjoystickLinux* js)
free(js->path); free(js->path);
memset(js, 0, sizeof(_GLFWjoystickLinux)); memset(js, 0, sizeof(_GLFWjoystickLinux));
_glfwInputJoystickChange(js - _glfw.linux_js.js,
GLFW_DISCONNECTED);
} }
break; break;
@ -168,12 +155,14 @@ static GLFWbool pollJoystickEvents(_GLFWjoystickLinux* js)
// Lexically compare joysticks, used by quicksort // Lexically compare joysticks, used by quicksort
// //
#if defined(__linux__)
static int compareJoysticks(const void* fp, const void* sp) static int compareJoysticks(const void* fp, const void* sp)
{ {
const _GLFWjoystickLinux* fj = fp; const _GLFWjoystickLinux* fj = fp;
const _GLFWjoystickLinux* sj = sp; const _GLFWjoystickLinux* sj = sp;
return strcmp(fj->path, sj->path); return strcmp(fj->path, sj->path);
} }
#endif // __linux__
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -285,6 +274,31 @@ void _glfwTerminateJoysticksLinux(void)
#endif // __linux__ #endif // __linux__
} }
void _glfwPollJoystickEvents(void)
{
#if defined(__linux__)
ssize_t offset = 0;
char buffer[16384];
const ssize_t size = read(_glfw.linux_js.inotify, buffer, sizeof(buffer));
while (size > offset)
{
regmatch_t match;
const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
if (regexec(&_glfw.linux_js.regex, e->name, 1, &match, 0) == 0)
{
char path[20];
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
openJoystickDevice(path);
}
offset += sizeof(struct inotify_event) + e->len;
}
#endif
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////

View File

@ -64,4 +64,6 @@ typedef struct _GLFWjoylistLinux
GLFWbool _glfwInitJoysticksLinux(void); GLFWbool _glfwInitJoysticksLinux(void);
void _glfwTerminateJoysticksLinux(void); void _glfwTerminateJoysticksLinux(void);
void _glfwPollJoystickEvents(void);
#endif // _glfw3_linux_joystick_h_ #endif // _glfw3_linux_joystick_h_

View File

@ -26,6 +26,7 @@
#include "internal.h" #include "internal.h"
#include <linux/input.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

View File

@ -51,12 +51,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(Vk
#include "posix_time.h" #include "posix_time.h"
#include "linux_joystick.h" #include "linux_joystick.h"
#include "xkb_unicode.h" #include "xkb_unicode.h"
#include "egl_context.h"
#if defined(_GLFW_EGL)
#include "egl_context.h"
#else
#error "The Mir backend depends on EGL platform support"
#endif
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle) #define _glfw_dlclose(handle) dlclose(handle)
@ -70,6 +65,9 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(Vk
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir
#define _GLFW_PLATFORM_CONTEXT_STATE
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
// Mir-specific Event Queue // Mir-specific Event Queue
// //

View File

@ -160,10 +160,15 @@ static void handlePointerButton(_GLFWwindow* window,
int pressed, int pressed,
const MirPointerEvent* pointer_event) const MirPointerEvent* pointer_event)
{ {
MirPointerButton button = mir_pointer_event_buttons (pointer_event);
int mods = mir_pointer_event_modifiers(pointer_event); int mods = mir_pointer_event_modifiers(pointer_event);
const int publicMods = mirModToGLFWMod(mods); const int publicMods = mirModToGLFWMod(mods);
int publicButton; MirPointerButton button = mir_pointer_button_primary;
static uint32_t oldButtonStates = 0;
uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event);
int publicButton = GLFW_MOUSE_BUTTON_LEFT;
// XOR our old button states our new states to figure out what was added or removed
button = newButtonStates ^ oldButtonStates;
switch (button) switch (button)
{ {
@ -188,6 +193,8 @@ static void handlePointerButton(_GLFWwindow* window,
break; break;
} }
oldButtonStates = newButtonStates;
_glfwInputMouseClick(window, publicButton, pressed, publicMods); _glfwInputMouseClick(window, publicButton, pressed, publicMods);
} }
@ -345,16 +352,10 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
{ {
if (ctxconfig->api != GLFW_NO_API) if (window->monitor)
{
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
if (wndconfig->monitor)
{ {
GLFWvidmode mode; GLFWvidmode mode;
_glfwPlatformGetVideoMode(wndconfig->monitor, &mode); _glfwPlatformGetVideoMode(window->monitor, &mode);
mir_surface_set_state(window->mir.surface, mir_surface_state_fullscreen); mir_surface_set_state(window->mir.surface, mir_surface_state_fullscreen);
@ -377,6 +378,12 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
window->mir.window = mir_buffer_stream_get_egl_native_window( window->mir.window = mir_buffer_stream_get_egl_native_window(
mir_surface_get_buffer_stream(window->mir.surface)); mir_surface_get_buffer_stream(window->mir.surface));
if (ctxconfig->client != GLFW_NO_API)
{
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -388,7 +395,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
window->mir.surface = NULL; window->mir.surface = NULL;
} }
_glfwDestroyContextEGL(window); if (window->context.client != GLFW_NO_API)
window->context.destroyContext(window);
} }
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
@ -403,6 +411,13 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
mir_surface_spec_release(spec); mir_surface_spec_release(spec);
} }
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
int count, const GLFWimage* images)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{ {
MirSurfaceSpec* spec; MirSurfaceSpec* spec;
@ -467,6 +482,12 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
mir_surface_set_state(window->mir.surface, mir_surface_state_restored); mir_surface_set_state(window->mir.surface, mir_surface_state_restored);
} }
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformHideWindow(_GLFWwindow* window) void _glfwPlatformHideWindow(_GLFWwindow* window)
{ {
MirSurfaceSpec* spec; MirSurfaceSpec* spec;
@ -489,7 +510,17 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
mir_surface_spec_release(spec); mir_surface_spec_release(spec);
} }
void _glfwPlatformUnhideWindow(_GLFWwindow* window) void _glfwPlatformFocusWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__); "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
@ -514,6 +545,13 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window)
return mir_surface_get_visibility(window->mir.surface) == mir_surface_visibility_exposed; return mir_surface_get_visibility(window->mir.surface) == mir_surface_visibility_exposed;
} }
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return GLFW_FALSE;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
EventNode* node = NULL; EventNode* node = NULL;
@ -537,6 +575,24 @@ void _glfwPlatformWaitEvents(void)
_glfwPlatformPollEvents(); _glfwPlatformPollEvents();
} }
void _glfwPlatformWaitEventsTimeout(double timeout)
{
pthread_mutex_lock(&_glfw.mir.event_mutex);
if (emptyEventQueue(_glfw.mir.event_queue))
{
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
time.tv_sec += (long) timeout;
time.tv_nsec += (long) ((timeout - (long) timeout) * 1e9);
pthread_cond_timedwait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex, &time);
}
pthread_mutex_unlock(&_glfw.mir.event_mutex);
_glfwPlatformPollEvents();
}
void _glfwPlatformPostEmptyEvent(void) void _glfwPlatformPostEmptyEvent(void)
{ {
} }
@ -653,11 +709,6 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf)); mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf));
if (cursor->mir.custom_cursor) if (cursor->mir.custom_cursor)
{ {
/* FIXME Bug https://bugs.launchpad.net/mir/+bug/1477285
Requires a triple buffer swap to get the cursor buffer on top! (since mir is tripled buffered)
*/
mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor);
mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor);
mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor); mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor);
} }
} }
@ -706,7 +757,7 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
return NULL; return NULL;
} }
char** _glfwPlatformGetRequiredInstanceExtensions(int* count) char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
{ {
char** extensions; char** extensions;
@ -725,7 +776,7 @@ char** _glfwPlatformGetRequiredInstanceExtensions(int* count)
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
unsigned int queuefamily) uint32_t queuefamily)
{ {
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR = PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR =
(PFN_vkGetPhysicalDeviceMirPresentationSupportKHR) (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)
@ -762,8 +813,8 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
memset(&sci, 0, sizeof(sci)); memset(&sci, 0, sizeof(sci));
sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR; sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR;
sci.display = _glfw.mir.connection; sci.connection = _glfw.mir.connection;
sci.surface = window->mir.surface; sci.mirSurface = window->mir.surface;
err = vkCreateMirSurfaceKHR(instance, &sci, allocator, surface); err = vkCreateMirSurfaceKHR(instance, &sci, allocator, surface);
if (err) if (err)

View File

@ -126,7 +126,11 @@ void _glfwInputMonitorChange(void)
for (window = _glfw.windowListHead; window; window = window->next) for (window = _glfw.windowListHead; window; window = window->next)
{ {
if (window->monitor == monitors[i]) if (window->monitor == monitors[i])
window->monitor = NULL; {
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
}
} }
if (_glfw.callbacks.monitor) if (_glfw.callbacks.monitor)
@ -158,6 +162,11 @@ void _glfwInputMonitorChange(void)
_glfwFreeMonitors(monitors, monitorCount); _glfwFreeMonitors(monitors, monitorCount);
} }
void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window)
{
monitor->window = window;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
@ -294,7 +303,7 @@ void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
GLFWAPI GLFWmonitor** glfwGetMonitors(int* count) GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
{ {
assert(count); assert(count != NULL);
*count = 0; *count = 0;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@ -316,7 +325,7 @@ GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void)
GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos) GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor); assert(monitor != NULL);
if (xpos) if (xpos)
*xpos = 0; *xpos = 0;
@ -331,7 +340,7 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM) GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor); assert(monitor != NULL);
if (widthMM) if (widthMM)
*widthMM = 0; *widthMM = 0;
@ -349,7 +358,7 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int*
GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle) GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor); assert(monitor != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return monitor->name; return monitor->name;
@ -365,9 +374,9 @@ GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count) GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor); assert(monitor != NULL);
assert(count); assert(count != NULL);
*count = 0; *count = 0;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@ -382,7 +391,7 @@ GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle) GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor); assert(monitor != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@ -400,7 +409,7 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX) if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
{ {
_glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value"); _glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
return; return;
} }
@ -431,7 +440,7 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle) GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor); assert(monitor != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@ -444,9 +453,9 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp) GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor); assert(monitor != NULL);
assert(ramp); assert(ramp != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();

View File

@ -27,7 +27,6 @@
#ifndef _glfw3_nsgl_context_h_ #ifndef _glfw3_nsgl_context_h_
#define _glfw3_nsgl_context_h_ #define _glfw3_nsgl_context_h_
#define _GLFW_PLATFORM_FBCONFIG
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl

View File

@ -27,6 +27,63 @@
#include "internal.h" #include "internal.h"
static void makeContextCurrent(_GLFWwindow* window)
{
if (window)
[window->context.nsgl.object makeCurrentContext];
else
[NSOpenGLContext clearCurrentContext];
_glfwPlatformSetCurrentContext(window);
}
static void swapBuffers(_GLFWwindow* window)
{
// ARP appears to be unnecessary, but this is future-proof
[window->context.nsgl.object flushBuffer];
}
static void swapInterval(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
GLint sync = interval;
[window->context.nsgl.object setValues:&sync
forParameter:NSOpenGLCPSwapInterval];
}
static int extensionSupported(const char* extension)
{
// There are no NSGL extensions
return GLFW_FALSE;
}
static GLFWglproc getProcAddress(const char* procname)
{
CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault,
procname,
kCFStringEncodingASCII);
GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework,
symbolName);
CFRelease(symbolName);
return symbol;
}
// Destroy the OpenGL context
//
static void destroyContext(_GLFWwindow* window)
{
[window->context.nsgl.pixelFormat release];
window->context.nsgl.pixelFormat = nil;
[window->context.nsgl.object release];
window->context.nsgl.object = nil;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -61,7 +118,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
{ {
unsigned int attributeCount = 0; unsigned int attributeCount = 0;
if (ctxconfig->api == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
"NSGL: OpenGL ES is not available on OS X"); "NSGL: OpenGL ES is not available on OS X");
@ -222,70 +279,17 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
} }
[window->context.nsgl.object setView:window->ns.view]; [window->context.nsgl.object setView:window->ns.view];
window->context.makeContextCurrent = makeContextCurrent;
window->context.swapBuffers = swapBuffers;
window->context.swapInterval = swapInterval;
window->context.extensionSupported = extensionSupported;
window->context.getProcAddress = getProcAddress;
window->context.destroyContext = destroyContext;
return GLFW_TRUE; return GLFW_TRUE;
} }
// Destroy the OpenGL context
//
void _glfwDestroyContextNSGL(_GLFWwindow* window)
{
[window->context.nsgl.pixelFormat release];
window->context.nsgl.pixelFormat = nil;
[window->context.nsgl.object release];
window->context.nsgl.object = nil;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
{
if (window)
[window->context.nsgl.object makeCurrentContext];
else
[NSOpenGLContext clearCurrentContext];
_glfwPlatformSetCurrentContext(window);
}
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
{
// ARP appears to be unnecessary, but this is future-proof
[window->context.nsgl.object flushBuffer];
}
void _glfwPlatformSwapInterval(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
GLint sync = interval;
[window->context.nsgl.object setValues:&sync
forParameter:NSOpenGLCPSwapInterval];
}
int _glfwPlatformExtensionSupported(const char* extension)
{
// There are no NSGL extensions
return GLFW_FALSE;
}
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
{
CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault,
procname,
kCFStringEncodingASCII);
GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework,
symbolName);
CFRelease(symbolName);
return symbol;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////
@ -296,7 +300,7 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(nil); _GLFW_REQUIRE_INIT_OR_RETURN(nil);
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL; return NULL;

View File

@ -30,28 +30,6 @@
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
// Return raw time
//
static uint64_t getRawTime(void)
{
#if defined(CLOCK_MONOTONIC)
if (_glfw.posix_time.monotonic)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t) ts.tv_sec * (uint64_t) 1000000000 + (uint64_t) ts.tv_nsec;
}
else
#endif
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t) tv.tv_sec * (uint64_t) 1000000 + (uint64_t) tv.tv_usec;
}
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
@ -67,15 +45,14 @@ void _glfwInitTimerPOSIX(void)
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
{ {
_glfw.posix_time.monotonic = GLFW_TRUE; _glfw.posix_time.monotonic = GLFW_TRUE;
_glfw.posix_time.resolution = 1e-9; _glfw.posix_time.frequency = 1000000000;
} }
else else
#endif #endif
{ {
_glfw.posix_time.resolution = 1e-6; _glfw.posix_time.monotonic = GLFW_FALSE;
_glfw.posix_time.frequency = 1000000;
} }
_glfw.posix_time.base = getRawTime();
} }
@ -83,15 +60,26 @@ void _glfwInitTimerPOSIX(void)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
double _glfwPlatformGetTime(void) uint64_t _glfwPlatformGetTimerValue(void)
{ {
return (double) (getRawTime() - _glfw.posix_time.base) * #if defined(CLOCK_MONOTONIC)
_glfw.posix_time.resolution; if (_glfw.posix_time.monotonic)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t) ts.tv_sec * (uint64_t) 1000000000 + (uint64_t) ts.tv_nsec;
}
else
#endif
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t) tv.tv_sec * (uint64_t) 1000000 + (uint64_t) tv.tv_usec;
}
} }
void _glfwPlatformSetTime(double time) uint64_t _glfwPlatformGetTimerFrequency(void)
{ {
_glfw.posix_time.base = getRawTime() - return _glfw.posix_time.frequency;
(uint64_t) (time / _glfw.posix_time.resolution);
} }

View File

@ -38,8 +38,7 @@
typedef struct _GLFWtimePOSIX typedef struct _GLFWtimePOSIX
{ {
GLFWbool monotonic; GLFWbool monotonic;
double resolution; uint64_t frequency;
uint64_t base;
} _GLFWtimePOSIX; } _GLFWtimePOSIX;

View File

@ -40,7 +40,7 @@ void _glfwInitVulkan(void)
{ {
VkResult err; VkResult err;
VkExtensionProperties* ep; VkExtensionProperties* ep;
unsigned int i, count; uint32_t i, count;
#if defined(_GLFW_WIN32) #if defined(_GLFW_WIN32)
const char* name = "vulkan-1.dll"; const char* name = "vulkan-1.dll";
#else #else
@ -61,7 +61,7 @@ void _glfwInitVulkan(void)
} }
_glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties) _glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
vkGetInstanceProcAddr(0, "vkEnumerateInstanceExtensionProperties"); vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties");
if (!_glfw.vk.EnumerateInstanceExtensionProperties) if (!_glfw.vk.EnumerateInstanceExtensionProperties)
{ {
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
@ -120,7 +120,7 @@ void _glfwInitVulkan(void)
void _glfwTerminateVulkan(void) void _glfwTerminateVulkan(void)
{ {
int i; uint32_t i;
for (i = 0; i < _glfw.vk.extensionCount; i++) for (i = 0; i < _glfw.vk.extensionCount; i++)
free(_glfw.vk.extensions[i]); free(_glfw.vk.extensions[i]);
@ -181,7 +181,7 @@ const char* _glfwGetVulkanResultString(VkResult result)
case VK_ERROR_VALIDATION_FAILED_EXT: case VK_ERROR_VALIDATION_FAILED_EXT:
return "A validation layer found an error"; return "A validation layer found an error";
default: default:
return "ERROR: UNKNOWN VULKAN ERROR TOKEN"; return "ERROR: UNKNOWN VULKAN ERROR";
} }
} }
@ -196,7 +196,7 @@ GLFWAPI int glfwVulkanSupported(void)
return _glfw.vk.available; return _glfw.vk.available;
} }
GLFWAPI const char** glfwGetRequiredInstanceExtensions(int* count) GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
{ {
*count = 0; *count = 0;
@ -262,9 +262,9 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
VkSurfaceKHR* surface) VkSurfaceKHR* surface)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
assert(surface); assert(surface != NULL);
*surface = VK_NULL_HANDLE; *surface = VK_NULL_HANDLE;
_GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED); _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);

View File

@ -32,55 +32,6 @@
#include <assert.h> #include <assert.h>
// Initialize WGL-specific extensions
//
static void loadExtensions(void)
{
// Functions for WGL_EXT_extension_string
// NOTE: These are needed by _glfwPlatformExtensionSupported
_glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
wglGetProcAddress("wglGetExtensionsStringEXT");
_glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
wglGetProcAddress("wglGetExtensionsStringARB");
// Functions for WGL_ARB_create_context
_glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
// Functions for WGL_EXT_swap_control
_glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
wglGetProcAddress("wglSwapIntervalEXT");
// Functions for WGL_ARB_pixel_format
_glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
wglGetProcAddress("wglGetPixelFormatAttribivARB");
// This needs to include every extension used below except for
// WGL_ARB_extensions_string and WGL_EXT_extensions_string
_glfw.wgl.ARB_multisample =
_glfwPlatformExtensionSupported("WGL_ARB_multisample");
_glfw.wgl.ARB_framebuffer_sRGB =
_glfwPlatformExtensionSupported("WGL_ARB_framebuffer_sRGB");
_glfw.wgl.EXT_framebuffer_sRGB =
_glfwPlatformExtensionSupported("WGL_EXT_framebuffer_sRGB");
_glfw.wgl.ARB_create_context =
_glfwPlatformExtensionSupported("WGL_ARB_create_context");
_glfw.wgl.ARB_create_context_profile =
_glfwPlatformExtensionSupported("WGL_ARB_create_context_profile");
_glfw.wgl.EXT_create_context_es2_profile =
_glfwPlatformExtensionSupported("WGL_EXT_create_context_es2_profile");
_glfw.wgl.ARB_create_context_robustness =
_glfwPlatformExtensionSupported("WGL_ARB_create_context_robustness");
_glfw.wgl.EXT_swap_control =
_glfwPlatformExtensionSupported("WGL_EXT_swap_control");
_glfw.wgl.ARB_pixel_format =
_glfwPlatformExtensionSupported("WGL_ARB_pixel_format");
_glfw.wgl.ARB_context_flush_control =
_glfwPlatformExtensionSupported("WGL_ARB_context_flush_control");
_glfw.wgl.extensionsLoaded = GLFW_TRUE;
}
// Returns the specified attribute of the specified pixel format // Returns the specified attribute of the specified pixel format
// //
static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib) static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib)
@ -236,10 +187,7 @@ static GLFWbool choosePixelFormat(_GLFWwindow* window,
u->doublebuffer = GLFW_TRUE; u->doublebuffer = GLFW_TRUE;
} }
// always able to create transparent windows on Windows u->handle = n;
u->transparent = desired->transparent;
u->wgl = n;
usableCount++; usableCount++;
} }
@ -262,7 +210,7 @@ static GLFWbool choosePixelFormat(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
*result = closest->wgl; *result = (int) closest->handle;
free(usableConfigs); free(usableConfigs);
return GLFW_TRUE; return GLFW_TRUE;
@ -283,6 +231,157 @@ static GLFWbool isCompositionEnabled(void)
return enabled; return enabled;
} }
static void makeContextCurrent(_GLFWwindow* window)
{
if (window)
{
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
_glfwPlatformSetCurrentContext(window);
else
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to make context current");
_glfwPlatformSetCurrentContext(NULL);
}
}
else
{
if (!wglMakeCurrent(NULL, NULL))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to clear current context");
}
_glfwPlatformSetCurrentContext(NULL);
}
}
static void swapBuffers(_GLFWwindow* window)
{
// HACK: Use DwmFlush when desktop composition is enabled
if (isCompositionEnabled() && !window->monitor)
{
int count = abs(window->context.wgl.interval);
while (count--)
_glfw_DwmFlush();
}
SwapBuffers(window->context.wgl.dc);
}
static void swapInterval(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
window->context.wgl.interval = interval;
// HACK: Disable WGL swap interval when desktop composition is enabled to
// avoid interfering with DWM vsync
if (isCompositionEnabled() && !window->monitor)
interval = 0;
if (_glfw.wgl.EXT_swap_control)
_glfw.wgl.SwapIntervalEXT(interval);
}
static int extensionSupported(const char* extension)
{
const char* extensions;
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (_glfw.wgl.GetExtensionsStringEXT)
{
extensions = _glfw.wgl.GetExtensionsStringEXT();
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
if (_glfw.wgl.GetExtensionsStringARB)
{
extensions = _glfw.wgl.GetExtensionsStringARB(window->context.wgl.dc);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
return GLFW_FALSE;
}
static GLFWglproc getProcAddress(const char* procname)
{
const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
if (proc)
return proc;
return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
}
// Destroy the OpenGL context
//
static void destroyContext(_GLFWwindow* window)
{
if (window->context.wgl.handle)
{
wglDeleteContext(window->context.wgl.handle);
window->context.wgl.handle = NULL;
}
}
// Initialize WGL-specific extensions
//
static void loadExtensions(void)
{
// Functions for WGL_EXT_extension_string
// NOTE: These are needed by extensionSupported
_glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
wglGetProcAddress("wglGetExtensionsStringEXT");
_glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
wglGetProcAddress("wglGetExtensionsStringARB");
// Functions for WGL_ARB_create_context
_glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
// Functions for WGL_EXT_swap_control
_glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
wglGetProcAddress("wglSwapIntervalEXT");
// Functions for WGL_ARB_pixel_format
_glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
wglGetProcAddress("wglGetPixelFormatAttribivARB");
// This needs to include every extension used below except for
// WGL_ARB_extensions_string and WGL_EXT_extensions_string
_glfw.wgl.ARB_multisample =
extensionSupported("WGL_ARB_multisample");
_glfw.wgl.ARB_framebuffer_sRGB =
extensionSupported("WGL_ARB_framebuffer_sRGB");
_glfw.wgl.EXT_framebuffer_sRGB =
extensionSupported("WGL_EXT_framebuffer_sRGB");
_glfw.wgl.ARB_create_context =
extensionSupported("WGL_ARB_create_context");
_glfw.wgl.ARB_create_context_profile =
extensionSupported("WGL_ARB_create_context_profile");
_glfw.wgl.EXT_create_context_es2_profile =
extensionSupported("WGL_EXT_create_context_es2_profile");
_glfw.wgl.ARB_create_context_robustness =
extensionSupported("WGL_ARB_create_context_robustness");
_glfw.wgl.EXT_swap_control =
extensionSupported("WGL_EXT_swap_control");
_glfw.wgl.ARB_pixel_format =
extensionSupported("WGL_ARB_pixel_format");
_glfw.wgl.ARB_context_flush_control =
extensionSupported("WGL_ARB_context_flush_control");
_glfw.wgl.extensionsLoaded = GLFW_TRUE;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
@ -339,7 +438,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
HGLRC share = NULL; HGLRC share = NULL;
if (ctxconfig->api == GLFW_NO_API) if (ctxconfig->client == GLFW_NO_API)
return GLFW_TRUE; return GLFW_TRUE;
if (ctxconfig->share) if (ctxconfig->share)
@ -375,7 +474,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
{ {
int index = 0, mask = 0, flags = 0; int index = 0, mask = 0, flags = 0;
if (ctxconfig->api == GLFW_OPENGL_API) if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if (ctxconfig->forward) if (ctxconfig->forward)
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
@ -477,22 +576,18 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
} }
} }
window->context.makeContextCurrent = makeContextCurrent;
window->context.swapBuffers = swapBuffers;
window->context.swapInterval = swapInterval;
window->context.extensionSupported = extensionSupported;
window->context.getProcAddress = getProcAddress;
window->context.destroyContext = destroyContext;
return GLFW_TRUE; return GLFW_TRUE;
} }
#undef setWGLattrib #undef setWGLattrib
// Destroy the OpenGL context
//
void _glfwDestroyContextWGL(_GLFWwindow* window)
{
if (window->context.wgl.handle)
{
wglDeleteContext(window->context.wgl.handle);
window->context.wgl.handle = NULL;
}
}
// Analyzes the specified context for possible recreation // Analyzes the specified context for possible recreation
// //
int _glfwAnalyzeContextWGL(_GLFWwindow* window, int _glfwAnalyzeContextWGL(_GLFWwindow* window,
@ -504,10 +599,10 @@ int _glfwAnalyzeContextWGL(_GLFWwindow* window,
if (_glfw.wgl.extensionsLoaded) if (_glfw.wgl.extensionsLoaded)
return _GLFW_RECREATION_NOT_NEEDED; return _GLFW_RECREATION_NOT_NEEDED;
_glfwPlatformMakeContextCurrent(window); makeContextCurrent(window);
loadExtensions(); loadExtensions();
if (ctxconfig->api == GLFW_OPENGL_API) if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if (ctxconfig->forward) if (ctxconfig->forward)
{ {
@ -590,87 +685,6 @@ int _glfwAnalyzeContextWGL(_GLFWwindow* window,
} }
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
{
if (window)
wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle);
else
wglMakeCurrent(NULL, NULL);
_glfwPlatformSetCurrentContext(window);
}
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
{
// HACK: Use DwmFlush when desktop composition is enabled
if (isCompositionEnabled() && !window->monitor)
{
int count = abs(window->context.wgl.interval);
while (count--)
_glfw_DwmFlush();
}
SwapBuffers(window->context.wgl.dc);
}
void _glfwPlatformSwapInterval(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
window->context.wgl.interval = interval;
// HACK: Disable WGL swap interval when desktop composition is enabled to
// avoid interfering with DWM vsync
if (isCompositionEnabled() && !window->monitor)
interval = 0;
if (_glfw.wgl.EXT_swap_control)
_glfw.wgl.SwapIntervalEXT(interval);
}
int _glfwPlatformExtensionSupported(const char* extension)
{
const char* extensions;
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (_glfw.wgl.GetExtensionsStringEXT)
{
extensions = _glfw.wgl.GetExtensionsStringEXT();
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
if (_glfw.wgl.GetExtensionsStringARB)
{
extensions = _glfw.wgl.GetExtensionsStringARB(window->context.wgl.dc);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
return GLFW_FALSE;
}
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
{
const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
if (proc)
return proc;
return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -680,7 +694,7 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL; return NULL;

View File

@ -96,7 +96,6 @@ typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC,HGLRC);
#define _GLFW_RECREATION_REQUIRED 1 #define _GLFW_RECREATION_REQUIRED 1
#define _GLFW_RECREATION_IMPOSSIBLE 2 #define _GLFW_RECREATION_IMPOSSIBLE 2
#define _GLFW_PLATFORM_FBCONFIG int wgl
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl
@ -149,7 +148,6 @@ void _glfwTerminateWGL(void);
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
void _glfwDestroyContextWGL(_GLFWwindow* window);
int _glfwAnalyzeContextWGL(_GLFWwindow* window, int _glfwAnalyzeContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);

View File

@ -30,6 +30,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <malloc.h> #include <malloc.h>
#include <initguid.h>
DEFINE_GUID(GUID_DEVINTERFACE_HID,0x4d1e55b2,0xf16f,0x11cf,0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30);
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG) #if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
@ -69,12 +71,6 @@ static GLFWbool loadLibraries(void)
return GLFW_FALSE; return GLFW_FALSE;
} }
_glfw.win32.winmm.joyGetDevCaps = (JOYGETDEVCAPS_T)
GetProcAddress(_glfw.win32.winmm.instance, "joyGetDevCapsW");
_glfw.win32.winmm.joyGetPos = (JOYGETPOS_T)
GetProcAddress(_glfw.win32.winmm.instance, "joyGetPos");
_glfw.win32.winmm.joyGetPosEx = (JOYGETPOSEX_T)
GetProcAddress(_glfw.win32.winmm.instance, "joyGetPosEx");
_glfw.win32.winmm.timeGetTime = (TIMEGETTIME_T) _glfw.win32.winmm.timeGetTime = (TIMEGETTIME_T)
GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime"); GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
@ -90,6 +86,40 @@ static GLFWbool loadLibraries(void)
_glfw.win32.user32.ChangeWindowMessageFilterEx = (CHANGEWINDOWMESSAGEFILTEREX_T) _glfw.win32.user32.ChangeWindowMessageFilterEx = (CHANGEWINDOWMESSAGEFILTEREX_T)
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx"); GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
if (_glfw.win32.dinput8.instance)
{
_glfw.win32.dinput8.DirectInput8Create = (DIRECTINPUT8CREATE_T)
GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
}
{
int i;
const char* names[] =
{
"xinput1_4.dll",
"xinput1_3.dll",
"xinput9_1_0.dll",
"xinput1_2.dll",
"xinput1_1.dll",
NULL
};
for (i = 0; names[i]; i++)
{
_glfw.win32.xinput.instance = LoadLibraryA(names[i]);
if (_glfw.win32.xinput.instance)
{
_glfw.win32.xinput.XInputGetCapabilities = (XINPUTGETCAPABILITIES_T)
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
_glfw.win32.xinput.XInputGetState = (XINPUTGETSTATE_T)
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
break;
}
}
}
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll"); _glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
if (_glfw.win32.dwmapi.instance) if (_glfw.win32.dwmapi.instance)
{ {
@ -113,6 +143,12 @@ static GLFWbool loadLibraries(void)
// //
static void freeLibraries(void) static void freeLibraries(void)
{ {
if (_glfw.win32.xinput.instance)
FreeLibrary(_glfw.win32.xinput.instance);
if (_glfw.win32.dinput8.instance)
FreeLibrary(_glfw.win32.dinput8.instance);
if (_glfw.win32.winmm.instance) if (_glfw.win32.winmm.instance)
FreeLibrary(_glfw.win32.winmm.instance); FreeLibrary(_glfw.win32.winmm.instance);
@ -196,6 +232,7 @@ static void createKeyTables(void)
_glfw.win32.publicKeys[0x151] = GLFW_KEY_PAGE_DOWN; _glfw.win32.publicKeys[0x151] = GLFW_KEY_PAGE_DOWN;
_glfw.win32.publicKeys[0x149] = GLFW_KEY_PAGE_UP; _glfw.win32.publicKeys[0x149] = GLFW_KEY_PAGE_UP;
_glfw.win32.publicKeys[0x045] = GLFW_KEY_PAUSE; _glfw.win32.publicKeys[0x045] = GLFW_KEY_PAUSE;
_glfw.win32.publicKeys[0x146] = GLFW_KEY_PAUSE;
_glfw.win32.publicKeys[0x039] = GLFW_KEY_SPACE; _glfw.win32.publicKeys[0x039] = GLFW_KEY_SPACE;
_glfw.win32.publicKeys[0x00F] = GLFW_KEY_TAB; _glfw.win32.publicKeys[0x00F] = GLFW_KEY_TAB;
_glfw.win32.publicKeys[0x03A] = GLFW_KEY_CAPS_LOCK; _glfw.win32.publicKeys[0x03A] = GLFW_KEY_CAPS_LOCK;
@ -272,7 +309,7 @@ static HWND createHelperWindow(void)
L"GLFW helper window", L"GLFW helper window",
WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
0, 0, 1, 1, 0, 0, 1, 1,
NULL, NULL, HWND_MESSAGE, NULL,
GetModuleHandleW(NULL), GetModuleHandleW(NULL),
NULL); NULL);
if (!window) if (!window)
@ -282,7 +319,20 @@ static HWND createHelperWindow(void)
return NULL; return NULL;
} }
return window; // Register for HID device notifications
{
DEV_BROADCAST_DEVICEINTERFACE_W dbi;
ZeroMemory(&dbi, sizeof(dbi));
dbi.dbcc_size = sizeof(dbi);
dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;
RegisterDeviceNotificationW(window,
(DEV_BROADCAST_HDR*) &dbi,
DEVICE_NOTIFY_WINDOW_HANDLE);
}
return window;
} }
@ -371,14 +421,10 @@ int _glfwPlatformInit(void)
_glfwPlatformPollEvents(); _glfwPlatformPollEvents();
#if defined(_GLFW_WGL)
if (!_glfwInitWGL()) if (!_glfwInitWGL())
return GLFW_FALSE; return GLFW_FALSE;
#elif defined(_GLFW_EGL)
if (!_glfwInitEGL())
return GLFW_FALSE;
#endif
_glfwInitEGL();
_glfwInitTimerWin32(); _glfwInitTimerWin32();
_glfwInitJoysticksWin32(); _glfwInitJoysticksWin32();
@ -399,11 +445,8 @@ void _glfwPlatformTerminate(void)
free(_glfw.win32.clipboardString); free(_glfw.win32.clipboardString);
#if defined(_GLFW_WGL)
_glfwTerminateWGL(); _glfwTerminateWGL();
#elif defined(_GLFW_EGL)
_glfwTerminateEGL(); _glfwTerminateEGL();
#endif
_glfwTerminateJoysticksWin32(); _glfwTerminateJoysticksWin32();
_glfwTerminateThreadLocalStorageWin32(); _glfwTerminateThreadLocalStorageWin32();
@ -413,12 +456,7 @@ void _glfwPlatformTerminate(void)
const char* _glfwPlatformGetVersionString(void) const char* _glfwPlatformGetVersionString(void)
{ {
return _GLFW_VERSION_NUMBER " Win32" return _GLFW_VERSION_NUMBER " Win32 WGL EGL"
#if defined(_GLFW_WGL)
" WGL"
#elif defined(_GLFW_EGL)
" EGL"
#endif
#if defined(__MINGW32__) #if defined(__MINGW32__)
" MinGW" " MinGW"
#elif defined(_MSC_VER) #elif defined(_MSC_VER)

View File

@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.2 Win32 - www.glfw.org // GLFW 3.1 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org> // Copyright (c) 2006-2015 Camilla Berglund <elmindreda@elmindreda.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -27,22 +27,623 @@
#include "internal.h" #include "internal.h"
#include <stdlib.h> #include <math.h>
#include <initguid.h>
////////////////////////////////////////////////////////////////////////// #define _GLFW_PRESENCE_ONLY 1
////// GLFW internal API ////// #define _GLFW_UPDATE_STATE 2
//////////////////////////////////////////////////////////////////////////
// Convert axis value to the [-1,1] range #define _GLFW_TYPE_AXIS 0
#define _GLFW_TYPE_SLIDER 1
#define _GLFW_TYPE_BUTTON 2
#define _GLFW_TYPE_POV 3
// Data produced with DirectInput device object enumeration
// //
static float normalizeAxis(DWORD pos, DWORD min, DWORD max) typedef struct _GLFWobjenumWin32
{ {
float fpos = (float) pos; IDirectInputDevice8W* device;
float fmin = (float) min; _GLFWjoyobjectWin32* objects;
float fmax = (float) max; int objectCount;
int axisCount;
int sliderCount;
int buttonCount;
int povCount;
} _GLFWobjenumWin32;
return (2.f * (fpos - fmin) / (fmax - fmin)) - 1.f; // Define only the necessary GUIDs (it's bad enough that we're exporting these)
//
DEFINE_GUID(IID_IDirectInput8W,0xbf798031,0x483a,0x4da2,0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00);
DEFINE_GUID(GUID_XAxis,0xa36d02e0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_YAxis,0xa36d02e1,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_ZAxis,0xa36d02e2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_RxAxis,0xa36d02f4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_RyAxis,0xa36d02f5,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_RzAxis,0xa36d02e3,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_Slider,0xa36d02e4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_Button,0xa36d02f0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_POV,0xa36d02f2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
// Object data array for our clone of c_dfDIJoystick
// Generated with https://github.com/elmindreda/c_dfDIJoystick2
//
static DIOBJECTDATAFORMAT _glfwObjectDataFormats[] =
{
{ &GUID_XAxis,DIJOFS_X,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
{ &GUID_YAxis,DIJOFS_Y,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
{ &GUID_ZAxis,DIJOFS_Z,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
{ &GUID_RxAxis,DIJOFS_RX,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
{ &GUID_RyAxis,DIJOFS_RY,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
{ &GUID_RzAxis,DIJOFS_RZ,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
{ &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
{ &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
{ &GUID_POV,DIJOFS_POV(0),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ &GUID_POV,DIJOFS_POV(1),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ &GUID_POV,DIJOFS_POV(2),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ &GUID_POV,DIJOFS_POV(3),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(0),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(1),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(2),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(3),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(4),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(5),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(6),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(7),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(8),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(9),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(10),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(11),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(12),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(13),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(14),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(15),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(16),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(17),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(18),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(19),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(20),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(21),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(22),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(23),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(24),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(25),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(26),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(27),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(28),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(29),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(30),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
{ NULL,DIJOFS_BUTTON(31),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
};
// Our clone of c_dfDIJoystick
//
static const DIDATAFORMAT _glfwDataFormat =
{
sizeof(DIDATAFORMAT),
sizeof(DIOBJECTDATAFORMAT),
DIDFT_ABSAXIS,
sizeof(DIJOYSTATE),
sizeof(_glfwObjectDataFormats) / sizeof(DIOBJECTDATAFORMAT),
_glfwObjectDataFormats
};
// Returns a description fitting the specified XInput capabilities
//
static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
{
switch (xic->SubType)
{
case XINPUT_DEVSUBTYPE_WHEEL:
return "XInput Wheel";
case XINPUT_DEVSUBTYPE_ARCADE_STICK:
return "XInput Arcade Stick";
case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
return "XInput Flight Stick";
case XINPUT_DEVSUBTYPE_DANCE_PAD:
return "XInput Dance Pad";
case XINPUT_DEVSUBTYPE_GUITAR:
return "XInput Guitar";
case XINPUT_DEVSUBTYPE_DRUM_KIT:
return "XInput Drum Kit";
case XINPUT_DEVSUBTYPE_GAMEPAD:
{
if (xic->Flags & XINPUT_CAPS_WIRELESS)
return "Wireless Xbox 360 Controller";
else
return "Xbox 360 Controller";
}
}
return "Unknown XInput Device";
}
// Lexically compare device objects
//
static int compareJoystickObjects(const void* first, const void* second)
{
const _GLFWjoyobjectWin32* fo = first;
const _GLFWjoyobjectWin32* so = second;
if (fo->type != so->type)
return fo->type - so->type;
return fo->offset - so->offset;
}
// Checks whether the specified device supports XInput
// Technique from FDInputJoystickManager::IsXInputDeviceFast in ZDoom
//
static GLFWbool supportsXInput(const GUID* guid)
{
UINT i, count;
RAWINPUTDEVICELIST* ridl;
GLFWbool result = GLFW_FALSE;
if (GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)) != 0)
return GLFW_FALSE;
ridl = calloc(count, sizeof(RAWINPUTDEVICELIST));
if (GetRawInputDeviceList(ridl, &count, sizeof(RAWINPUTDEVICELIST)) == -1)
{
free(ridl);
return GLFW_FALSE;
}
for (i = 0; i < count; i++)
{
RID_DEVICE_INFO rdi;
char name[256];
UINT size;
if (ridl[i].dwType != RIM_TYPEHID)
continue;
ZeroMemory(&rdi, sizeof(rdi));
rdi.cbSize = sizeof(rdi);
size = sizeof(rdi);
if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
RIDI_DEVICEINFO,
&rdi, &size) == -1)
{
continue;
}
if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) != guid->Data1)
continue;
memset(name, 0, sizeof(name));
size = sizeof(name);
if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
RIDI_DEVICENAME,
name, &size) == -1)
{
break;
}
name[sizeof(name) - 1] = '\0';
if (strstr(name, "IG_"))
{
result = GLFW_TRUE;
break;
}
}
free(ridl);
return result;
}
// Frees all resources associated with the specified joystick
//
static void closeJoystick(_GLFWjoystickWin32* js)
{
if (js->device)
{
IDirectInputDevice8_Unacquire(js->device);
IDirectInputDevice8_Release(js->device);
}
free(js->name);
free(js->axes);
free(js->buttons);
free(js->objects);
memset(js, 0, sizeof(_GLFWjoystickWin32));
_glfwInputJoystickChange((int) (js - _glfw.win32_js), GLFW_DISCONNECTED);
}
// DirectInput device object enumeration callback
// Insights gleaned from SDL2
//
static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
void* user)
{
_GLFWobjenumWin32* data = user;
_GLFWjoyobjectWin32* object = data->objects + data->objectCount;
if (DIDFT_GETTYPE(doi->dwType) & DIDFT_AXIS)
{
DIPROPRANGE dipr;
if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
object->offset = DIJOFS_SLIDER(data->sliderCount);
else if (memcmp(&doi->guidType, &GUID_XAxis, sizeof(GUID)) == 0)
object->offset = DIJOFS_X;
else if (memcmp(&doi->guidType, &GUID_YAxis, sizeof(GUID)) == 0)
object->offset = DIJOFS_Y;
else if (memcmp(&doi->guidType, &GUID_ZAxis, sizeof(GUID)) == 0)
object->offset = DIJOFS_Z;
else if (memcmp(&doi->guidType, &GUID_RxAxis, sizeof(GUID)) == 0)
object->offset = DIJOFS_RX;
else if (memcmp(&doi->guidType, &GUID_RyAxis, sizeof(GUID)) == 0)
object->offset = DIJOFS_RY;
else if (memcmp(&doi->guidType, &GUID_RzAxis, sizeof(GUID)) == 0)
object->offset = DIJOFS_RZ;
else
return DIENUM_CONTINUE;
ZeroMemory(&dipr, sizeof(dipr));
dipr.diph.dwSize = sizeof(dipr);
dipr.diph.dwHeaderSize = sizeof(dipr.diph);
dipr.diph.dwObj = doi->dwType;
dipr.diph.dwHow = DIPH_BYID;
dipr.lMin = -32768;
dipr.lMax = 32767;
if (FAILED(IDirectInputDevice8_SetProperty(data->device,
DIPROP_RANGE,
&dipr.diph)))
{
return DIENUM_CONTINUE;
}
if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
{
object->type = _GLFW_TYPE_SLIDER;
data->sliderCount++;
}
else
{
object->type = _GLFW_TYPE_AXIS;
data->axisCount++;
}
}
else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_BUTTON)
{
object->offset = DIJOFS_BUTTON(data->buttonCount);
object->type = _GLFW_TYPE_BUTTON;
data->buttonCount++;
}
else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_POV)
{
object->offset = DIJOFS_POV(data->povCount);
object->type = _GLFW_TYPE_POV;
data->povCount++;
}
data->objectCount++;
return DIENUM_CONTINUE;
}
// DirectInput device enumeration callback
//
static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
{
int joy = 0;
DIDEVCAPS dc;
DIPROPDWORD dipd;
IDirectInputDevice8* device;
_GLFWobjenumWin32 data;
_GLFWjoystickWin32* js;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
if (memcmp(&_glfw.win32_js[joy].guid, &di->guidInstance, sizeof(GUID)) == 0)
return DIENUM_CONTINUE;
}
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
if (!_glfw.win32_js[joy].present)
break;
}
if (joy > GLFW_JOYSTICK_LAST)
return DIENUM_STOP;
if (supportsXInput(&di->guidProduct))
return DIENUM_CONTINUE;
if (FAILED(IDirectInput8_CreateDevice(_glfw.win32.dinput8.api,
&di->guidInstance,
&device,
NULL)))
{
_glfwInputError(GLFW_PLATFORM_ERROR, "DI: Failed to create device");
return DIENUM_CONTINUE;
}
if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to set device data format");
IDirectInputDevice8_Release(device);
return DIENUM_CONTINUE;
}
ZeroMemory(&dc, sizeof(dc));
dc.dwSize = sizeof(dc);
if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to query device capabilities");
IDirectInputDevice8_Release(device);
return DIENUM_CONTINUE;
}
ZeroMemory(&dipd, sizeof(dipd));
dipd.diph.dwSize = sizeof(dipd);
dipd.diph.dwHeaderSize = sizeof(dipd.diph);
dipd.diph.dwHow = DIPH_DEVICE;
dipd.dwData = DIPROPAXISMODE_ABS;
if (FAILED(IDirectInputDevice8_SetProperty(device,
DIPROP_AXISMODE,
&dipd.diph)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to set device axis mode");
IDirectInputDevice8_Release(device);
return DIENUM_CONTINUE;
}
memset(&data, 0, sizeof(data));
data.device = device;
data.objects = calloc(dc.dwAxes + dc.dwButtons + dc.dwPOVs,
sizeof(_GLFWjoyobjectWin32));
if (FAILED(IDirectInputDevice8_EnumObjects(device,
deviceObjectCallback,
&data,
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to enumerate device objects");
IDirectInputDevice8_Release(device);
free(data.objects);
return DIENUM_CONTINUE;
}
qsort(data.objects, data.objectCount,
sizeof(_GLFWjoyobjectWin32),
compareJoystickObjects);
js = _glfw.win32_js + joy;
js->device = device;
js->guid = di->guidInstance;
js->axisCount = data.axisCount + data.sliderCount;
js->axes = calloc(js->axisCount, sizeof(float));
js->buttonCount += data.buttonCount + data.povCount * 4;
js->buttons = calloc(js->buttonCount, 1);
js->objects = data.objects;
js->objectCount = data.objectCount;
js->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName);
js->present = GLFW_TRUE;
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
return DIENUM_CONTINUE;
}
// Attempt to open the specified joystick device
// TODO: Pack state arrays for non-gamepad devices
//
static GLFWbool openXinputDevice(DWORD index)
{
int joy;
XINPUT_CAPABILITIES xic;
_GLFWjoystickWin32* js;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
if (_glfw.win32_js[joy].present &&
_glfw.win32_js[joy].device == NULL &&
_glfw.win32_js[joy].index == index)
{
return GLFW_FALSE;
}
}
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
if (!_glfw.win32_js[joy].present)
break;
}
if (joy > GLFW_JOYSTICK_LAST)
return GLFW_FALSE;
if (_glfw_XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
return GLFW_FALSE;
js = _glfw.win32_js + joy;
js->axisCount = 6;
js->axes = calloc(js->axisCount, sizeof(float));
js->buttonCount = 14;
js->buttons = calloc(js->buttonCount, 1);
js->present = GLFW_TRUE;
js->name = strdup(getDeviceDescription(&xic));
js->index = index;
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
return GLFW_TRUE;
}
// Polls for and processes events the specified joystick
//
static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode)
{
if (!js->present)
return GLFW_FALSE;
if (js->device)
{
int i, j, ai = 0, bi = 0;
HRESULT result;
DIJOYSTATE state;
IDirectInputDevice8_Poll(js->device);
result = IDirectInputDevice8_GetDeviceState(js->device,
sizeof(state),
&state);
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
{
IDirectInputDevice8_Acquire(js->device);
IDirectInputDevice8_Poll(js->device);
result = IDirectInputDevice8_GetDeviceState(js->device,
sizeof(state),
&state);
}
if (FAILED(result))
{
closeJoystick(js);
return GLFW_FALSE;
}
if (mode == _GLFW_PRESENCE_ONLY)
return GLFW_TRUE;
for (i = 0; i < js->objectCount; i++)
{
const void* data = (char*) &state + js->objects[i].offset;
switch (js->objects[i].type)
{
case _GLFW_TYPE_AXIS:
case _GLFW_TYPE_SLIDER:
{
js->axes[ai++] = (*((LONG*) data) + 0.5f) / 32767.5f;
break;
}
case _GLFW_TYPE_BUTTON:
{
if (*((BYTE*) data) & 0x80)
js->buttons[bi++] = GLFW_PRESS;
else
js->buttons[bi++] = GLFW_RELEASE;
break;
}
case _GLFW_TYPE_POV:
{
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
// Screams of horror are appropriate at this point
int value = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
if (value < 0 || value > 8)
value = 8;
for (j = 0; j < 4; j++)
{
if (directions[value] & (1 << j))
js->buttons[bi++] = GLFW_PRESS;
else
js->buttons[bi++] = GLFW_RELEASE;
}
break;
}
}
}
return GLFW_TRUE;
}
else
{
int i;
DWORD result;
XINPUT_STATE xis;
const WORD buttons[14] =
{
XINPUT_GAMEPAD_A,
XINPUT_GAMEPAD_B,
XINPUT_GAMEPAD_X,
XINPUT_GAMEPAD_Y,
XINPUT_GAMEPAD_LEFT_SHOULDER,
XINPUT_GAMEPAD_RIGHT_SHOULDER,
XINPUT_GAMEPAD_BACK,
XINPUT_GAMEPAD_START,
XINPUT_GAMEPAD_LEFT_THUMB,
XINPUT_GAMEPAD_RIGHT_THUMB,
XINPUT_GAMEPAD_DPAD_UP,
XINPUT_GAMEPAD_DPAD_RIGHT,
XINPUT_GAMEPAD_DPAD_DOWN,
XINPUT_GAMEPAD_DPAD_LEFT
};
result = _glfw_XInputGetState(js->index, &xis);
if (result != ERROR_SUCCESS)
{
if (result == ERROR_DEVICE_NOT_CONNECTED)
closeJoystick(js);
return GLFW_FALSE;
}
if (mode == _GLFW_PRESENCE_ONLY)
return GLFW_TRUE;
if (sqrt((double) (xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY)) >
(double) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
js->axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f;
js->axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f;
}
else
{
js->axes[0] = 0.f;
js->axes[1] = 0.f;
}
if (sqrt((double) (xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX +
xis.Gamepad.sThumbRY * xis.Gamepad.sThumbRY)) >
(double) XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
js->axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f;
js->axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f;
}
else
{
js->axes[2] = 0.f;
js->axes[3] = 0.f;
}
if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
js->axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f;
else
js->axes[4] = -1.f;
if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
js->axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
else
js->axes[5] = -1.f;
for (i = 0; i < 14; i++)
js->buttons[i] = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
return GLFW_TRUE;
}
} }
@ -54,16 +655,70 @@ static float normalizeAxis(DWORD pos, DWORD min, DWORD max)
// //
void _glfwInitJoysticksWin32(void) void _glfwInitJoysticksWin32(void)
{ {
if (_glfw.win32.dinput8.instance)
{
if (FAILED(_glfw_DirectInput8Create(GetModuleHandle(NULL),
DIRECTINPUT_VERSION,
&IID_IDirectInput8W,
(void**) &_glfw.win32.dinput8.api,
NULL)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to create interface");
}
}
_glfwDetectJoystickConnectionWin32();
} }
// Close all opened joystick handles // Close all opened joystick handles
// //
void _glfwTerminateJoysticksWin32(void) void _glfwTerminateJoysticksWin32(void)
{ {
int i; int joy;
for (i = 0; i < GLFW_JOYSTICK_LAST; i++) for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
free(_glfw.win32_js[i].name); closeJoystick(_glfw.win32_js + joy);
if (_glfw.win32.dinput8.api)
IDirectInput8_Release(_glfw.win32.dinput8.api);
}
// Checks for new joysticks after DBT_DEVICEARRIVAL
//
void _glfwDetectJoystickConnectionWin32(void)
{
if (_glfw.win32.xinput.instance)
{
DWORD i;
for (i = 0; i < XUSER_MAX_COUNT; i++)
openXinputDevice(i);
}
if (_glfw.win32.dinput8.api)
{
if (FAILED(IDirectInput8_EnumDevices(_glfw.win32.dinput8.api,
DI8DEVCLASS_GAMECTRL,
deviceCallback,
NULL,
DIEDFL_ALLDEVICES)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Failed to enumerate DirectInput8 devices");
return;
}
}
}
// Checks for joystick disconnection after DBT_DEVICEREMOVECOMPLETE
//
void _glfwDetectJoystickDisconnectionWin32(void)
{
int joy;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
pollJoystickState(_glfw.win32_js + joy, _GLFW_PRESENCE_ONLY);
} }
@ -73,105 +728,36 @@ void _glfwTerminateJoysticksWin32(void)
int _glfwPlatformJoystickPresent(int joy) int _glfwPlatformJoystickPresent(int joy)
{ {
JOYINFO ji; _GLFWjoystickWin32* js = _glfw.win32_js + joy;
return pollJoystickState(js, _GLFW_PRESENCE_ONLY);
if (_glfw_joyGetPos(joy, &ji) != JOYERR_NOERROR)
return GLFW_FALSE;
return GLFW_TRUE;
} }
const float* _glfwPlatformGetJoystickAxes(int joy, int* count) const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
{ {
JOYCAPS jc; _GLFWjoystickWin32* js = _glfw.win32_js + joy;
JOYINFOEX ji; if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
float* axes = _glfw.win32_js[joy].axes;
if (_glfw_joyGetDevCaps(joy, &jc, sizeof(JOYCAPS)) != JOYERR_NOERROR)
return NULL; return NULL;
ji.dwSize = sizeof(JOYINFOEX); *count = js->axisCount;
ji.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | return js->axes;
JOY_RETURNR | JOY_RETURNU | JOY_RETURNV;
if (_glfw_joyGetPosEx(joy, &ji) != JOYERR_NOERROR)
return NULL;
axes[(*count)++] = normalizeAxis(ji.dwXpos, jc.wXmin, jc.wXmax);
axes[(*count)++] = normalizeAxis(ji.dwYpos, jc.wYmin, jc.wYmax);
if (jc.wCaps & JOYCAPS_HASZ)
axes[(*count)++] = normalizeAxis(ji.dwZpos, jc.wZmin, jc.wZmax);
if (jc.wCaps & JOYCAPS_HASR)
axes[(*count)++] = normalizeAxis(ji.dwRpos, jc.wRmin, jc.wRmax);
if (jc.wCaps & JOYCAPS_HASU)
axes[(*count)++] = normalizeAxis(ji.dwUpos, jc.wUmin, jc.wUmax);
if (jc.wCaps & JOYCAPS_HASV)
axes[(*count)++] = normalizeAxis(ji.dwVpos, jc.wVmin, jc.wVmax);
return axes;
} }
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count) const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
{ {
JOYCAPS jc; _GLFWjoystickWin32* js = _glfw.win32_js + joy;
JOYINFOEX ji; if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
unsigned char* buttons = _glfw.win32_js[joy].buttons;
if (_glfw_joyGetDevCaps(joy, &jc, sizeof(JOYCAPS)) != JOYERR_NOERROR)
return NULL; return NULL;
ji.dwSize = sizeof(JOYINFOEX); *count = js->buttonCount;
ji.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOV; return js->buttons;
if (_glfw_joyGetPosEx(joy, &ji) != JOYERR_NOERROR)
return NULL;
while (*count < (int) jc.wNumButtons)
{
buttons[*count] = (unsigned char)
(ji.dwButtons & (1UL << *count) ? GLFW_PRESS : GLFW_RELEASE);
(*count)++;
}
// 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
if ((jc.wCaps & JOYCAPS_HASPOV) && (jc.wCaps & JOYCAPS_POV4DIR))
{
int i, value = ji.dwPOV / 100 / 45;
// Bit fields of button presses for each direction, including nil
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
if (value < 0 || value > 8)
value = 8;
for (i = 0; i < 4; i++)
{
if (directions[value] & (1 << i))
buttons[(*count)++] = GLFW_PRESS;
else
buttons[(*count)++] = GLFW_RELEASE;
}
}
return buttons;
} }
const char* _glfwPlatformGetJoystickName(int joy) const char* _glfwPlatformGetJoystickName(int joy)
{ {
JOYCAPS jc; _GLFWjoystickWin32* js = _glfw.win32_js + joy;
if (!pollJoystickState(js, _GLFW_PRESENCE_ONLY))
if (_glfw_joyGetDevCaps(joy, &jc, sizeof(JOYCAPS)) != JOYERR_NOERROR)
return NULL; return NULL;
free(_glfw.win32_js[joy].name); return js->name;
_glfw.win32_js[joy].name = _glfwCreateUTF8FromWideStringWin32(jc.szPname);
return _glfw.win32_js[joy].name;
} }

View File

@ -30,18 +30,35 @@
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \ #define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
_GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1] _GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1]
// Spoo
//
typedef struct _GLFWjoyobjectWin32
{
int offset;
int type;
} _GLFWjoyobjectWin32;
// Win32-specific per-joystick data // Win32-specific per-joystick data
// //
typedef struct _GLFWjoystickWin32 typedef struct _GLFWjoystickWin32
{ {
float axes[6]; GLFWbool present;
unsigned char buttons[36]; // 32 buttons plus one hat float* axes;
char* name; int axisCount;
unsigned char* buttons;
int buttonCount;
_GLFWjoyobjectWin32* objects;
int objectCount;
char* name;
IDirectInputDevice8W* device;
DWORD index;
GUID guid;
} _GLFWjoystickWin32; } _GLFWjoystickWin32;
void _glfwInitJoysticksWin32(void); void _glfwInitJoysticksWin32(void);
void _glfwTerminateJoysticksWin32(void); void _glfwTerminateJoysticksWin32(void);
void _glfwDetectJoystickConnectionWin32(void);
void _glfwDetectJoystickDisconnectionWin32(void);
#endif // _glfw3_win32_joystick_h_ #endif // _glfw3_win32_joystick_h_

View File

@ -32,13 +32,58 @@
#include <limits.h> #include <limits.h>
#include <malloc.h> #include <malloc.h>
// These constants are missing on MinGW
#ifndef EDS_ROTATEDMODE // Create monitor from an adapter and (optionally) a display
#define EDS_ROTATEDMODE 0x00000004 //
#endif static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
#ifndef DISPLAY_DEVICE_ACTIVE DISPLAY_DEVICEW* display)
#define DISPLAY_DEVICE_ACTIVE 0x00000001 {
#endif _GLFWmonitor* monitor;
char* name;
HDC dc;
if (display)
name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
else
name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
if (!name)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string to UTF-8");
return NULL;
}
dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
monitor = _glfwAllocMonitor(name,
GetDeviceCaps(dc, HORZSIZE),
GetDeviceCaps(dc, VERTSIZE));
DeleteDC(dc);
free(name);
if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)
monitor->win32.modesPruned = GLFW_TRUE;
wcscpy(monitor->win32.adapterName, adapter->DeviceName);
WideCharToMultiByte(CP_UTF8, 0,
adapter->DeviceName, -1,
monitor->win32.publicAdapterName,
sizeof(monitor->win32.publicAdapterName),
NULL, NULL);
if (display)
{
wcscpy(monitor->win32.displayName, display->DeviceName);
WideCharToMultiByte(CP_UTF8, 0,
display->DeviceName, -1,
monitor->win32.publicDisplayName,
sizeof(monitor->win32.publicDisplayName),
NULL, NULL);
}
return monitor;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -104,17 +149,18 @@ void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
_GLFWmonitor** _glfwPlatformGetMonitors(int* count) _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
{ {
int found = 0; int found = 0;
DWORD adapterIndex, displayIndex, primaryIndex = 0;
DISPLAY_DEVICEW adapter, display;
GLFWbool hasDisplays = GLFW_FALSE;
_GLFWmonitor** monitors = NULL; _GLFWmonitor** monitors = NULL;
DWORD adapterIndex, displayIndex;
*count = 0; *count = 0;
// HACK: Check if any active adapters have connected displays
// If not, this is a headless system or a VMware guest
for (adapterIndex = 0; ; adapterIndex++) for (adapterIndex = 0; ; adapterIndex++)
{ {
DISPLAY_DEVICEW adapter;
int widthMM, heightMM;
HDC dc;
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW)); ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
adapter.cb = sizeof(DISPLAY_DEVICEW); adapter.cb = sizeof(DISPLAY_DEVICEW);
@ -124,71 +170,65 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE)) if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue; continue;
dc = CreateDCW(L"DISPLAY", adapter.DeviceName, NULL, NULL); ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
widthMM = GetDeviceCaps(dc, HORZSIZE); display.cb = sizeof(DISPLAY_DEVICEW);
heightMM = GetDeviceCaps(dc, VERTSIZE);
DeleteDC(dc);
for (displayIndex = 0; ; displayIndex++) if (EnumDisplayDevicesW(adapter.DeviceName, 0, &display, 0))
{ {
DISPLAY_DEVICEW display; hasDisplays = GLFW_TRUE;
_GLFWmonitor* monitor; break;
char* name;
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
display.cb = sizeof(DISPLAY_DEVICEW);
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
break;
name = _glfwCreateUTF8FromWideStringWin32(display.DeviceString);
if (!name)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string to UTF-8");
continue;
}
monitor = _glfwAllocMonitor(name, widthMM, heightMM);
free(name);
if (adapter.StateFlags & DISPLAY_DEVICE_MODESPRUNED)
monitor->win32.modesPruned = GLFW_TRUE;
wcscpy(monitor->win32.adapterName, adapter.DeviceName);
wcscpy(monitor->win32.displayName, display.DeviceName);
WideCharToMultiByte(CP_UTF8, 0,
adapter.DeviceName, -1,
monitor->win32.publicAdapterName,
sizeof(monitor->win32.publicAdapterName),
NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0,
display.DeviceName, -1,
monitor->win32.publicDisplayName,
sizeof(monitor->win32.publicDisplayName),
NULL, NULL);
found++;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
monitors[found - 1] = monitor;
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE &&
displayIndex == 0)
{
_GLFW_SWAP_POINTERS(monitors[0], monitors[found - 1]);
}
} }
} }
for (adapterIndex = 0; ; adapterIndex++)
{
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
adapter.cb = sizeof(DISPLAY_DEVICEW);
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
break;
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
primaryIndex = found;
if (hasDisplays)
{
for (displayIndex = 0; ; displayIndex++)
{
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
display.cb = sizeof(DISPLAY_DEVICEW);
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
break;
found++;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
monitors[found - 1] = createMonitor(&adapter, &display);
}
}
else
{
found++;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
monitors[found - 1] = createMonitor(&adapter, NULL);
}
}
_GLFW_SWAP_POINTERS(monitors[0], monitors[primaryIndex]);
*count = found; *count = found;
return monitors; return monitors;
} }
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second) GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
{ {
return wcscmp(first->win32.displayName, second->win32.displayName) == 0; if (wcslen(first->win32.displayName))
return wcscmp(first->win32.displayName, second->win32.displayName) == 0;
else
return wcscmp(first->win32.adapterName, second->win32.adapterName) == 0;
} }
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)

View File

@ -61,8 +61,14 @@
#define _WIN32_WINNT 0x0501 #define _WIN32_WINNT 0x0501
#endif #endif
// GLFW uses DirectInput8 interfaces
#define DIRECTINPUT_VERSION 0x0800
#include <wctype.h>
#include <windows.h> #include <windows.h>
#include <mmsystem.h> #include <mmsystem.h>
#include <dinput.h>
#include <xinput.h>
#include <dbt.h> #include <dbt.h>
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -70,7 +76,7 @@
#define strdup _strdup #define strdup _strdup
#endif #endif
// HACK: Define macros that some older windows.h variants don't // HACK: Define macros that some windows.h variants don't
#ifndef WM_MOUSEHWHEEL #ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E #define WM_MOUSEHWHEEL 0x020E
#endif #endif
@ -92,6 +98,12 @@
#ifndef GET_XBUTTON_WPARAM #ifndef GET_XBUTTON_WPARAM
#define GET_XBUTTON_WPARAM(w) (HIWORD(w)) #define GET_XBUTTON_WPARAM(w) (HIWORD(w))
#endif #endif
#ifndef EDS_ROTATEDMODE
#define EDS_ROTATEDMODE 0x00000004
#endif
#ifndef DISPLAY_DEVICE_ACTIVE
#define DISPLAY_DEVICE_ACTIVE 0x00000001
#endif
#if WINVER < 0x0601 #if WINVER < 0x0601
typedef struct tagCHANGEFILTERSTRUCT typedef struct tagCHANGEFILTERSTRUCT
@ -114,16 +126,54 @@ typedef enum PROCESS_DPI_AWARENESS
} PROCESS_DPI_AWARENESS; } PROCESS_DPI_AWARENESS;
#endif /*DPI_ENUMS_DECLARED*/ #endif /*DPI_ENUMS_DECLARED*/
// HACK: Define macros that some xinput.h variants don't
#ifndef XINPUT_CAPS_WIRELESS
#define XINPUT_CAPS_WIRELESS 0x0002
#endif
#ifndef XINPUT_DEVSUBTYPE_WHEEL
#define XINPUT_DEVSUBTYPE_WHEEL 0x02
#endif
#ifndef XINPUT_DEVSUBTYPE_ARCADE_STICK
#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
#endif
#ifndef XINPUT_DEVSUBTYPE_FLIGHT_STICK
#define XINPUT_DEVSUBTYPE_FLIGHT_STICK 0x04
#endif
#ifndef XINPUT_DEVSUBTYPE_DANCE_PAD
#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
#endif
#ifndef XINPUT_DEVSUBTYPE_GUITAR
#define XINPUT_DEVSUBTYPE_GUITAR 0x06
#endif
#ifndef XINPUT_DEVSUBTYPE_DRUM_KIT
#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
#endif
#ifndef XINPUT_DEVSUBTYPE_ARCADE_PAD
#define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
#endif
#ifndef XUSER_MAX_COUNT
#define XUSER_MAX_COUNT 4
#endif
// HACK: Define macros that some dinput.h variants don't
#ifndef DIDFT_OPTIONAL
#define DIDFT_OPTIONAL 0x80000000
#endif
// winmm.dll function pointer typedefs // winmm.dll function pointer typedefs
typedef MMRESULT (WINAPI * JOYGETDEVCAPS_T)(UINT,LPJOYCAPS,UINT);
typedef MMRESULT (WINAPI * JOYGETPOS_T)(UINT,LPJOYINFO);
typedef MMRESULT (WINAPI * JOYGETPOSEX_T)(UINT,LPJOYINFOEX);
typedef DWORD (WINAPI * TIMEGETTIME_T)(void); typedef DWORD (WINAPI * TIMEGETTIME_T)(void);
#define _glfw_joyGetDevCaps _glfw.win32.winmm.joyGetDevCaps
#define _glfw_joyGetPos _glfw.win32.winmm.joyGetPos
#define _glfw_joyGetPosEx _glfw.win32.winmm.joyGetPosEx
#define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime #define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime
// xinput.dll function pointer typedefs
typedef DWORD (WINAPI * XINPUTGETCAPABILITIES_T)(DWORD,DWORD,XINPUT_CAPABILITIES*);
typedef DWORD (WINAPI * XINPUTGETSTATE_T)(DWORD,XINPUT_STATE*);
#define _glfw_XInputGetCapabilities _glfw.win32.xinput.XInputGetCapabilities
#define _glfw_XInputGetState _glfw.win32.xinput.XInputGetState
// dinput8.dll function pointer typedefs
typedef HRESULT (WINAPI * DIRECTINPUT8CREATE_T)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
#define _glfw_DirectInput8Create _glfw.win32.dinput8.DirectInput8Create
// user32.dll function pointer typedefs // user32.dll function pointer typedefs
typedef BOOL (WINAPI * SETPROCESSDPIAWARE_T)(void); typedef BOOL (WINAPI * SETPROCESSDPIAWARE_T)(void);
typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT); typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);
@ -155,16 +205,8 @@ typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin3
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t); typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t);
#include "win32_joystick.h" #include "win32_joystick.h"
#include "wgl_context.h"
#if defined(_GLFW_WGL) #include "egl_context.h"
#include "wgl_context.h"
#elif defined(_GLFW_EGL)
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->win32.handle)
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
#include "egl_context.h"
#else
#error "No supported context creation API selected"
#endif
#define _GLFW_WNDCLASSNAME L"GLFW30" #define _GLFW_WNDCLASSNAME L"GLFW30"
@ -172,6 +214,9 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle) #define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name) #define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->win32.handle)
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32 #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32 #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time #define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time
@ -185,14 +230,12 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
typedef struct _GLFWwindowWin32 typedef struct _GLFWwindowWin32
{ {
HWND handle; HWND handle;
HICON bigIcon;
HICON smallIcon;
GLFWbool cursorTracked; GLFWbool cursorTracked;
GLFWbool iconified; GLFWbool iconified;
int minwidth, minheight;
int maxwidth, maxheight;
int numer, denom;
// The last received cursor position, regardless of source // The last received cursor position, regardless of source
int cursorPosX, cursorPosY; int cursorPosX, cursorPosY;
@ -210,30 +253,35 @@ typedef struct _GLFWlibraryWin32
short int publicKeys[512]; short int publicKeys[512];
short int nativeKeys[GLFW_KEY_LAST + 1]; short int nativeKeys[GLFW_KEY_LAST + 1];
// winmm.dll
struct { struct {
HINSTANCE instance; HINSTANCE instance;
JOYGETDEVCAPS_T joyGetDevCaps;
JOYGETPOS_T joyGetPos;
JOYGETPOSEX_T joyGetPosEx;
TIMEGETTIME_T timeGetTime; TIMEGETTIME_T timeGetTime;
} winmm; } winmm;
// user32.dll
struct { struct {
HINSTANCE instance; HINSTANCE instance;
SETPROCESSDPIAWARE_T SetProcessDPIAware; DIRECTINPUT8CREATE_T DirectInput8Create;
IDirectInput8W* api;
} dinput8;
struct {
HINSTANCE instance;
XINPUTGETCAPABILITIES_T XInputGetCapabilities;
XINPUTGETSTATE_T XInputGetState;
} xinput;
struct {
HINSTANCE instance;
SETPROCESSDPIAWARE_T SetProcessDPIAware;
CHANGEWINDOWMESSAGEFILTEREX_T ChangeWindowMessageFilterEx; CHANGEWINDOWMESSAGEFILTEREX_T ChangeWindowMessageFilterEx;
} user32; } user32;
// dwmapi.dll
struct { struct {
HINSTANCE instance; HINSTANCE instance;
DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled; DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled;
DWMFLUSH_T DwmFlush; DWMFLUSH_T DwmFlush;
} dwmapi; } dwmapi;
// shcore.dll
struct { struct {
HINSTANCE instance; HINSTANCE instance;
SETPROCESSDPIAWARENESS_T SetProcessDpiAwareness; SETPROCESSDPIAWARENESS_T SetProcessDpiAwareness;
@ -271,8 +319,7 @@ typedef struct _GLFWcursorWin32
typedef struct _GLFWtimeWin32 typedef struct _GLFWtimeWin32
{ {
GLFWbool hasPC; GLFWbool hasPC;
double resolution; uint64_t frequency;
unsigned __int64 base;
} _GLFWtimeWin32; } _GLFWtimeWin32;

View File

@ -28,21 +28,6 @@
#include "internal.h" #include "internal.h"
// Return raw time
//
static unsigned __int64 getRawTime(void)
{
if (_glfw.win32_time.hasPC)
{
unsigned __int64 time;
QueryPerformanceCounter((LARGE_INTEGER*) &time);
return time;
}
else
return (unsigned __int64) _glfw_timeGetTime();
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -51,20 +36,18 @@ static unsigned __int64 getRawTime(void)
// //
void _glfwInitTimerWin32(void) void _glfwInitTimerWin32(void)
{ {
unsigned __int64 frequency; uint64_t frequency;
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency)) if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
{ {
_glfw.win32_time.hasPC = GLFW_TRUE; _glfw.win32_time.hasPC = GLFW_TRUE;
_glfw.win32_time.resolution = 1.0 / (double) frequency; _glfw.win32_time.frequency = frequency;
} }
else else
{ {
_glfw.win32_time.hasPC = GLFW_FALSE; _glfw.win32_time.hasPC = GLFW_FALSE;
_glfw.win32_time.resolution = 0.001; // winmm resolution is 1 ms _glfw.win32_time.frequency = 1000;
} }
_glfw.win32_time.base = getRawTime();
} }
@ -72,15 +55,20 @@ void _glfwInitTimerWin32(void)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
double _glfwPlatformGetTime(void) uint64_t _glfwPlatformGetTimerValue(void)
{ {
return (double) (getRawTime() - _glfw.win32_time.base) * if (_glfw.win32_time.hasPC)
_glfw.win32_time.resolution; {
uint64_t value;
QueryPerformanceCounter((LARGE_INTEGER*) &value);
return value;
}
else
return (uint64_t) _glfw_timeGetTime();
} }
void _glfwPlatformSetTime(double time) uint64_t _glfwPlatformGetTimerFrequency(void)
{ {
_glfw.win32_time.base = getRawTime() - return _glfw.win32_time.frequency;
(unsigned __int64) (time / _glfw.win32_time.resolution);
} }

View File

@ -27,6 +27,7 @@
#include "internal.h" #include "internal.h"
#include <limits.h>
#include <stdlib.h> #include <stdlib.h>
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
@ -41,15 +42,20 @@ static DWORD getWindowStyle(const _GLFWwindow* window)
{ {
DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN; DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
if (window->decorated && !window->monitor) if (window->monitor)
{
style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
if (window->resizable)
style |= WS_MAXIMIZEBOX | WS_SIZEBOX;
}
else
style |= WS_POPUP; style |= WS_POPUP;
else
{
if (window->decorated)
{
style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
if (window->resizable)
style |= WS_MAXIMIZEBOX | WS_THICKFRAME;
}
else
style |= WS_POPUP;
}
return style; return style;
} }
@ -60,12 +66,118 @@ static DWORD getWindowExStyle(const _GLFWwindow* window)
{ {
DWORD style = WS_EX_APPWINDOW; DWORD style = WS_EX_APPWINDOW;
if (window->decorated && !window->monitor) if (window->monitor || window->floating)
style |= WS_EX_WINDOWEDGE; style |= WS_EX_TOPMOST;
return style; return style;
} }
// Returns the image whose area most closely matches the desired one
//
static const GLFWimage* chooseImage(int count, const GLFWimage* images,
int width, int height)
{
int i, leastDiff = INT_MAX;
const GLFWimage* closest = NULL;
for (i = 0; i < count; i++)
{
const int currDiff = abs(images[i].width * images[i].height -
width * height);
if (currDiff < leastDiff)
{
closest = images + i;
leastDiff = currDiff;
}
}
return closest;
}
// Creates an RGBA icon or cursor
//
static HICON createIcon(const GLFWimage* image,
int xhot, int yhot, GLFWbool icon)
{
int i;
HDC dc;
HICON handle;
HBITMAP color, mask;
BITMAPV5HEADER bi;
ICONINFO ii;
unsigned char* target = NULL;
unsigned char* source = image->pixels;
ZeroMemory(&bi, sizeof(bi));
bi.bV5Size = sizeof(BITMAPV5HEADER);
bi.bV5Width = image->width;
bi.bV5Height = -image->height;
bi.bV5Planes = 1;
bi.bV5BitCount = 32;
bi.bV5Compression = BI_BITFIELDS;
bi.bV5RedMask = 0x00ff0000;
bi.bV5GreenMask = 0x0000ff00;
bi.bV5BlueMask = 0x000000ff;
bi.bV5AlphaMask = 0xff000000;
dc = GetDC(NULL);
color = CreateDIBSection(dc,
(BITMAPINFO*) &bi,
DIB_RGB_COLORS,
(void**) &target,
NULL,
(DWORD) 0);
ReleaseDC(NULL, dc);
if (!color)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to create RGBA bitmap");
return NULL;
}
mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
if (!mask)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to create mask bitmap");
DeleteObject(color);
return NULL;
}
for (i = 0; i < image->width * image->height; i++)
{
target[0] = source[2];
target[1] = source[1];
target[2] = source[0];
target[3] = source[3];
target += 4;
source += 4;
}
ZeroMemory(&ii, sizeof(ii));
ii.fIcon = icon;
ii.xHotspot = xhot;
ii.yHotspot = yhot;
ii.hbmMask = mask;
ii.hbmColor = color;
handle = CreateIconIndirect(&ii);
DeleteObject(color);
DeleteObject(mask);
if (!handle)
{
if (icon)
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create icon");
else
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create cursor");
}
return handle;
}
// Translate client window size to full window size according to styles // Translate client window size to full window size according to styles
// //
static void getFullWindowSize(DWORD style, DWORD exStyle, static void getFullWindowSize(DWORD style, DWORD exStyle,
@ -83,8 +195,7 @@ static void getFullWindowSize(DWORD style, DWORD exStyle,
static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area) static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
{ {
int xoff, yoff; int xoff, yoff;
const float ratio = (float) window->win32.numer / const float ratio = (float) window->numer / (float) window->denom;
(float) window->win32.denom;
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
0, 0, &xoff, &yoff); 0, 0, &xoff, &yoff);
@ -221,9 +332,9 @@ static int translateKey(WPARAM wParam, LPARAM lParam)
return _glfw.win32.publicKeys[HIWORD(lParam) & 0x1FF]; return _glfw.win32.publicKeys[HIWORD(lParam) & 0x1FF];
} }
// Enter full screen mode // Make the specified window and its video mode active on its monitor
// //
static GLFWbool enterFullscreenMode(_GLFWwindow* window) static GLFWbool acquireMonitor(_GLFWwindow* window)
{ {
GLFWvidmode mode; GLFWvidmode mode;
GLFWbool status; GLFWbool status;
@ -235,15 +346,21 @@ static GLFWbool enterFullscreenMode(_GLFWwindow* window)
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos); _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
SetWindowPos(window->win32.handle, HWND_TOPMOST, SetWindowPos(window->win32.handle, HWND_TOPMOST,
xpos, ypos, mode.width, mode.height, SWP_NOCOPYBITS); xpos, ypos, mode.width, mode.height,
SWP_NOACTIVATE | SWP_NOCOPYBITS);
_glfwInputMonitorWindowChange(window->monitor, window);
return status; return status;
} }
// Leave full screen mode // Remove the window and restore the original video mode
// //
static void leaveFullscreenMode(_GLFWwindow* window) static void releaseMonitor(_GLFWwindow* window)
{ {
if (window->monitor->window != window)
return;
_glfwInputMonitorWindowChange(window->monitor, NULL);
_glfwRestoreVideoModeWin32(window->monitor); _glfwRestoreVideoModeWin32(window->monitor);
} }
@ -252,18 +369,13 @@ static void leaveFullscreenMode(_GLFWwindow* window)
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam) WPARAM wParam, LPARAM lParam)
{ {
_GLFWwindow* window = (_GLFWwindow*) GetWindowLongPtrW(hWnd, 0); _GLFWwindow* window = (_GLFWwindow*) GetPropW(hWnd, L"GLFW");
if (!window) if (!window)
{ {
// This is the message handling for the hidden helper window
switch (uMsg) switch (uMsg)
{ {
case WM_NCCREATE:
{
CREATESTRUCTW* cs = (CREATESTRUCTW*) lParam;
SetWindowLongPtrW(hWnd, 0, (LONG_PTR) cs->lpCreateParams);
break;
}
case WM_DEVICECHANGE: case WM_DEVICECHANGE:
{ {
if (wParam == DBT_DEVNODES_CHANGED) if (wParam == DBT_DEVNODES_CHANGED)
@ -271,6 +383,24 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
_glfwInputMonitorChange(); _glfwInputMonitorChange();
return TRUE; return TRUE;
} }
else if (wParam == DBT_DEVICEARRIVAL)
{
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
if (dbh)
{
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
_glfwDetectJoystickConnectionWin32();
}
}
else if (wParam == DBT_DEVICEREMOVECOMPLETE)
{
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
if (dbh)
{
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
_glfwDetectJoystickDisconnectionWin32();
}
}
break; break;
} }
@ -483,32 +613,39 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_SIZE: case WM_SIZE:
{ {
const GLFWbool iconified =
!window->win32.iconified && wParam == SIZE_MINIMIZED;
const GLFWbool restored =
window->win32.iconified &&
(wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED);
if (_glfw.cursorWindow == window) if (_glfw.cursorWindow == window)
{ {
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
updateClipRect(window); updateClipRect(window);
} }
if (!window->win32.iconified && wParam == SIZE_MINIMIZED) if (iconified)
{
window->win32.iconified = GLFW_TRUE;
if (window->monitor)
leaveFullscreenMode(window);
_glfwInputWindowIconify(window, GLFW_TRUE); _glfwInputWindowIconify(window, GLFW_TRUE);
} else if (restored)
else if (window->win32.iconified &&
(wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED))
{
window->win32.iconified = GLFW_FALSE;
if (window->monitor)
enterFullscreenMode(window);
_glfwInputWindowIconify(window, GLFW_FALSE); _glfwInputWindowIconify(window, GLFW_FALSE);
}
_glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam)); _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));
_glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam)); _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));
if (iconified)
{
window->win32.iconified = GLFW_TRUE;
if (window->monitor)
releaseMonitor(window);
}
else if (restored)
{
window->win32.iconified = GLFW_FALSE;
if (window->monitor)
acquireMonitor(window);
}
return 0; return 0;
} }
@ -530,8 +667,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_SIZING: case WM_SIZING:
{ {
if (window->win32.numer == GLFW_DONT_CARE || if (window->numer == GLFW_DONT_CARE ||
window->win32.denom == GLFW_DONT_CARE) window->denom == GLFW_DONT_CARE)
{ {
break; break;
} }
@ -545,21 +682,24 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
int xoff, yoff; int xoff, yoff;
MINMAXINFO* mmi = (MINMAXINFO*) lParam; MINMAXINFO* mmi = (MINMAXINFO*) lParam;
if (window->monitor)
break;
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
0, 0, &xoff, &yoff); 0, 0, &xoff, &yoff);
if (window->win32.minwidth != GLFW_DONT_CARE && if (window->minwidth != GLFW_DONT_CARE &&
window->win32.minheight != GLFW_DONT_CARE) window->minheight != GLFW_DONT_CARE)
{ {
mmi->ptMinTrackSize.x = window->win32.minwidth + xoff; mmi->ptMinTrackSize.x = window->minwidth + xoff;
mmi->ptMinTrackSize.y = window->win32.minheight + yoff; mmi->ptMinTrackSize.y = window->minheight + yoff;
} }
if (window->win32.maxwidth != GLFW_DONT_CARE && if (window->maxwidth != GLFW_DONT_CARE &&
window->win32.maxheight != GLFW_DONT_CARE) window->maxheight != GLFW_DONT_CARE)
{ {
mmi->ptMaxTrackSize.x = window->win32.maxwidth + xoff; mmi->ptMaxTrackSize.x = window->maxwidth + xoff;
mmi->ptMaxTrackSize.y = window->win32.maxheight + yoff; mmi->ptMaxTrackSize.y = window->maxheight + yoff;
} }
return 0; return 0;
@ -653,16 +793,18 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
{ {
int xpos, ypos, fullWidth, fullHeight; int xpos, ypos, fullWidth, fullHeight;
WCHAR* wideTitle; WCHAR* wideTitle;
DWORD style = getWindowStyle(window);
DWORD exStyle = getWindowExStyle(window);
if (wndconfig->monitor) if (window->monitor)
{ {
GLFWvidmode mode; GLFWvidmode mode;
// NOTE: This window placement is temporary and approximate, as the // NOTE: This window placement is temporary and approximate, as the
// correct position and size cannot be known until the monitor // correct position and size cannot be known until the monitor
// video mode has been set // video mode has been set
_glfwPlatformGetMonitorPos(wndconfig->monitor, &xpos, &ypos); _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
_glfwPlatformGetVideoMode(wndconfig->monitor, &mode); _glfwPlatformGetVideoMode(window->monitor, &mode);
fullWidth = mode.width; fullWidth = mode.width;
fullHeight = mode.height; fullHeight = mode.height;
} }
@ -671,7 +813,10 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
xpos = CW_USEDEFAULT; xpos = CW_USEDEFAULT;
ypos = CW_USEDEFAULT; ypos = CW_USEDEFAULT;
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), if (wndconfig->maximized)
style |= WS_MAXIMIZE;
getFullWindowSize(style, exStyle,
wndconfig->width, wndconfig->height, wndconfig->width, wndconfig->height,
&fullWidth, &fullHeight); &fullWidth, &fullHeight);
} }
@ -684,16 +829,16 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
return GLFW_FALSE; return GLFW_FALSE;
} }
window->win32.handle = CreateWindowExW(getWindowExStyle(window), window->win32.handle = CreateWindowExW(exStyle,
_GLFW_WNDCLASSNAME, _GLFW_WNDCLASSNAME,
wideTitle, wideTitle,
getWindowStyle(window), style,
xpos, ypos, xpos, ypos,
fullWidth, fullHeight, fullWidth, fullHeight,
NULL, // No parent window NULL, // No parent window
NULL, // No window menu NULL, // No window menu
GetModuleHandleW(NULL), GetModuleHandleW(NULL),
window); // Pass object to WM_CREATE NULL);
free(wideTitle); free(wideTitle);
@ -703,6 +848,8 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
return GLFW_FALSE; return GLFW_FALSE;
} }
SetPropW(window->win32.handle, L"GLFW", window);
if (_glfw_ChangeWindowMessageFilterEx) if (_glfw_ChangeWindowMessageFilterEx)
{ {
_glfw_ChangeWindowMessageFilterEx(window->win32.handle, _glfw_ChangeWindowMessageFilterEx(window->win32.handle,
@ -713,23 +860,8 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL); WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
} }
if (wndconfig->floating && !wndconfig->monitor)
{
SetWindowPos(window->win32.handle,
HWND_TOPMOST,
0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}
DragAcceptFiles(window->win32.handle, TRUE); DragAcceptFiles(window->win32.handle, TRUE);
window->win32.minwidth = GLFW_DONT_CARE;
window->win32.minheight = GLFW_DONT_CARE;
window->win32.maxwidth = GLFW_DONT_CARE;
window->win32.maxheight = GLFW_DONT_CARE;
window->win32.numer = GLFW_DONT_CARE;
window->win32.denom = GLFW_DONT_CARE;
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -739,6 +871,7 @@ static void destroyWindow(_GLFWwindow* window)
{ {
if (window->win32.handle) if (window->win32.handle)
{ {
RemovePropW(window->win32.handle, L"GLFW");
DestroyWindow(window->win32.handle); DestroyWindow(window->win32.handle);
window->win32.handle = NULL; window->win32.handle = NULL;
} }
@ -759,7 +892,6 @@ GLFWbool _glfwRegisterWindowClassWin32(void)
wc.cbSize = sizeof(wc); wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) windowProc; wc.lpfnWndProc = (WNDPROC) windowProc;
wc.cbWndExtra = sizeof(void*) + sizeof(int); // Make room for one pointer
wc.hInstance = GetModuleHandleW(NULL); wc.hInstance = GetModuleHandleW(NULL);
wc.hCursor = LoadCursorW(NULL, IDC_ARROW); wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
wc.lpszClassName = _GLFW_WNDCLASSNAME; wc.lpszClassName = _GLFW_WNDCLASSNAME;
@ -808,61 +940,65 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!createWindow(window, wndconfig)) if (!createWindow(window, wndconfig))
return GLFW_FALSE; return GLFW_FALSE;
if (ctxconfig->api != GLFW_NO_API) if (ctxconfig->client != GLFW_NO_API)
{ {
#if defined(_GLFW_WGL) if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
status = _glfwAnalyzeContextWGL(window, ctxconfig, fbconfig);
if (status == _GLFW_RECREATION_IMPOSSIBLE)
return GLFW_FALSE;
if (status == _GLFW_RECREATION_REQUIRED)
{ {
// Some window hints require us to re-create the context using WGL
// extensions retrieved through the current context, as we cannot
// check for WGL extensions or retrieve WGL entry points before we
// have a current context (actually until we have implicitly loaded
// the vendor ICD)
// Yes, this is strange, and yes, this is the proper way on WGL
// As Windows only allows you to set the pixel format once for
// a window, we need to destroy the current window and create a new
// one to be able to use the new pixel format
// Technically, it may be possible to keep the old window around if
// we're just creating an OpenGL 3.0+ context with the same pixel
// format, but it's not worth the added code complexity
// First we clear the current context (the one we just created)
// This is usually done by glfwDestroyWindow, but as we're not doing
// full GLFW window destruction, it's duplicated here
_glfwPlatformMakeContextCurrent(NULL);
// Next destroy the Win32 window and WGL context (without resetting
// or destroying the GLFW window object)
_glfwDestroyContextWGL(window);
destroyWindow(window);
// ...and then create them again, this time with better APIs
if (!createWindow(window, wndconfig))
return GLFW_FALSE;
if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig)) if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
return GLFW_FALSE; return GLFW_FALSE;
status = _glfwAnalyzeContextWGL(window, ctxconfig, fbconfig);
if (status == _GLFW_RECREATION_IMPOSSIBLE)
return GLFW_FALSE;
if (status == _GLFW_RECREATION_REQUIRED)
{
// Some window hints require us to re-create the context using WGL
// extensions retrieved through the current context, as we cannot
// check for WGL extensions or retrieve WGL entry points before we
// have a current context (actually until we have implicitly loaded
// the vendor ICD)
// Yes, this is strange, and yes, this is the proper way on WGL
// As Windows only allows you to set the pixel format once for
// a window, we need to destroy the current window and create a new
// one to be able to use the new pixel format
// Technically, it may be possible to keep the old window around if
// we're just creating an OpenGL 3.0+ context with the same pixel
// format, but it's not worth the added code complexity
// First we clear the current context (the one we just created)
// This is usually done by glfwDestroyWindow, but as we're not doing
// full GLFW window destruction, it's duplicated here
window->context.makeContextCurrent(NULL);
// Next destroy the Win32 window and WGL context (without resetting
// or destroying the GLFW window object)
window->context.destroyContext(window);
destroyWindow(window);
// ...and then create them again, this time with better APIs
if (!createWindow(window, wndconfig))
return GLFW_FALSE;
if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
}
else
{
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
} }
#elif defined(_GLFW_EGL)
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
#endif
} }
if (window->monitor) if (window->monitor)
{ {
_glfwPlatformShowWindow(window); _glfwPlatformShowWindow(window);
if (!enterFullscreenMode(window)) _glfwPlatformFocusWindow(window);
if (!acquireMonitor(window))
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -872,18 +1008,18 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
void _glfwPlatformDestroyWindow(_GLFWwindow* window) void _glfwPlatformDestroyWindow(_GLFWwindow* window)
{ {
if (window->monitor) if (window->monitor)
leaveFullscreenMode(window); releaseMonitor(window);
if (window->context.api != GLFW_NO_API) if (window->context.client != GLFW_NO_API)
{ window->context.destroyContext(window);
#if defined(_GLFW_WGL)
_glfwDestroyContextWGL(window);
#elif defined(_GLFW_EGL)
_glfwDestroyContextEGL(window);
#endif
}
destroyWindow(window); destroyWindow(window);
if (window->win32.bigIcon)
DestroyIcon(window->win32.bigIcon);
if (window->win32.smallIcon)
DestroyIcon(window->win32.smallIcon);
} }
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
@ -900,6 +1036,45 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
free(wideTitle); free(wideTitle);
} }
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
int count, const GLFWimage* images)
{
HICON bigIcon = NULL, smallIcon = NULL;
if (count)
{
const GLFWimage* bigImage = chooseImage(count, images,
GetSystemMetrics(SM_CXICON),
GetSystemMetrics(SM_CYICON));
const GLFWimage* smallImage = chooseImage(count, images,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON));
bigIcon = createIcon(bigImage, 0, 0, GLFW_TRUE);
smallIcon = createIcon(smallImage, 0, 0, GLFW_TRUE);
}
else
{
bigIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICON);
smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM);
}
SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
if (window->win32.bigIcon)
DestroyIcon(window->win32.bigIcon);
if (window->win32.smallIcon)
DestroyIcon(window->win32.smallIcon);
if (count)
{
window->win32.bigIcon = bigIcon;
window->win32.smallIcon = smallIcon;
}
}
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
{ {
POINT pos = { 0, 0 }; POINT pos = { 0, 0 };
@ -934,15 +1109,17 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{ {
if (window->monitor) if (window->monitor)
enterFullscreenMode(window); {
if (window->monitor->window == window)
acquireMonitor(window);
}
else else
{ {
int fullWidth, fullHeight; RECT rect = { 0, 0, width, height };
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), AdjustWindowRectEx(&rect, getWindowStyle(window),
width, height, &fullWidth, &fullHeight); FALSE, getWindowExStyle(window));
SetWindowPos(window->win32.handle, HWND_TOP, SetWindowPos(window->win32.handle, HWND_TOP,
0, 0, fullWidth, fullHeight, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER); SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);
} }
} }
@ -953,11 +1130,6 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
{ {
RECT area; RECT area;
window->win32.minwidth = minwidth;
window->win32.minheight = minheight;
window->win32.maxwidth = maxwidth;
window->win32.maxheight = maxheight;
if ((minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) && if ((minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) &&
(maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)) (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE))
{ {
@ -975,9 +1147,6 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom
{ {
RECT area; RECT area;
window->win32.numer = numer;
window->win32.denom = denom;
if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE) if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
return; return;
@ -1026,15 +1195,12 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
ShowWindow(window->win32.handle, SW_RESTORE); ShowWindow(window->win32.handle, SW_RESTORE);
} }
void _glfwPlatformShowWindow(_GLFWwindow* window) void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{ {
ShowWindow(window->win32.handle, SW_SHOW); ShowWindow(window->win32.handle, SW_MAXIMIZE);
BringWindowToTop(window->win32.handle);
SetForegroundWindow(window->win32.handle);
SetFocus(window->win32.handle);
} }
void _glfwPlatformUnhideWindow(_GLFWwindow* window) void _glfwPlatformShowWindow(_GLFWwindow* window)
{ {
ShowWindow(window->win32.handle, SW_SHOW); ShowWindow(window->win32.handle, SW_SHOW);
} }
@ -1044,6 +1210,99 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
ShowWindow(window->win32.handle, SW_HIDE); ShowWindow(window->win32.handle, SW_HIDE);
} }
void _glfwPlatformFocusWindow(_GLFWwindow* window)
{
BringWindowToTop(window->win32.handle);
SetForegroundWindow(window->win32.handle);
SetFocus(window->win32.handle);
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
if (window->monitor == monitor)
{
if (monitor)
{
if (monitor->window == window)
acquireMonitor(window);
}
else
{
RECT rect = { xpos, ypos, xpos + width, ypos + height };
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
SetWindowPos(window->win32.handle, HWND_TOP,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOZORDER);
}
return;
}
if (window->monitor)
releaseMonitor(window);
_glfwInputWindowMonitorChange(window, monitor);
if (monitor)
{
GLFWvidmode mode;
DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
UINT flags = SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS;
if (window->decorated)
{
style &= ~WS_OVERLAPPEDWINDOW;
style |= getWindowStyle(window);
SetWindowLongW(window->win32.handle, GWL_STYLE, style);
flags |= SWP_FRAMECHANGED;
}
_glfwPlatformGetVideoMode(monitor, &mode);
_glfwPlatformGetMonitorPos(monitor, &xpos, &ypos);
SetWindowPos(window->win32.handle, HWND_TOPMOST,
xpos, ypos, mode.width, mode.height,
flags);
acquireMonitor(window);
}
else
{
HWND after;
RECT rect = { xpos, ypos, xpos + width, ypos + height };
DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
UINT flags = SWP_NOACTIVATE | SWP_NOCOPYBITS;
if (window->decorated)
{
style &= ~WS_POPUP;
style |= getWindowStyle(window);
SetWindowLongW(window->win32.handle, GWL_STYLE, style);
flags |= SWP_FRAMECHANGED;
}
if (window->floating)
after = HWND_TOPMOST;
else
after = HWND_NOTOPMOST;
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
SetWindowPos(window->win32.handle, after,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
flags);
}
}
int _glfwPlatformWindowFocused(_GLFWwindow* window) int _glfwPlatformWindowFocused(_GLFWwindow* window)
{ {
return window->win32.handle == GetActiveWindow(); return window->win32.handle == GetActiveWindow();
@ -1059,6 +1318,11 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window)
return IsWindowVisible(window->win32.handle); return IsWindowVisible(window->win32.handle);
} }
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
{
return IsZoomed(window->win32.handle);
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
MSG msg; MSG msg;
@ -1131,6 +1395,13 @@ void _glfwPlatformWaitEvents(void)
_glfwPlatformPollEvents(); _glfwPlatformPollEvents();
} }
void _glfwPlatformWaitEventsTimeout(double timeout)
{
MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLEVENTS);
_glfwPlatformPollEvents();
}
void _glfwPlatformPostEmptyEvent(void) void _glfwPlatformPostEmptyEvent(void)
{ {
_GLFWwindow* window = _glfw.windowListHead; _GLFWwindow* window = _glfw.windowListHead;
@ -1218,61 +1489,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image, const GLFWimage* image,
int xhot, int yhot) int xhot, int yhot)
{ {
HDC dc; cursor->win32.handle = (HCURSOR) createIcon(image, xhot, yhot, GLFW_FALSE);
HBITMAP bitmap, mask;
BITMAPV5HEADER bi;
ICONINFO ii;
DWORD* target = 0;
BYTE* source = (BYTE*) image->pixels;
int i;
ZeroMemory(&bi, sizeof(bi));
bi.bV5Size = sizeof(BITMAPV5HEADER);
bi.bV5Width = image->width;
bi.bV5Height = -image->height;
bi.bV5Planes = 1;
bi.bV5BitCount = 32;
bi.bV5Compression = BI_BITFIELDS;
bi.bV5RedMask = 0x00ff0000;
bi.bV5GreenMask = 0x0000ff00;
bi.bV5BlueMask = 0x000000ff;
bi.bV5AlphaMask = 0xff000000;
dc = GetDC(NULL);
bitmap = CreateDIBSection(dc, (BITMAPINFO*) &bi, DIB_RGB_COLORS,
(void**) &target, NULL, (DWORD) 0);
ReleaseDC(NULL, dc);
if (!bitmap)
return GLFW_FALSE;
mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
if (!mask)
{
DeleteObject(bitmap);
return GLFW_FALSE;
}
for (i = 0; i < image->width * image->height; i++, target++, source += 4)
{
*target = (source[3] << 24) |
(source[0] << 16) |
(source[1] << 8) |
source[2];
}
ZeroMemory(&ii, sizeof(ii));
ii.fIcon = FALSE;
ii.xHotspot = xhot;
ii.yHotspot = yhot;
ii.hbmMask = mask;
ii.hbmColor = bitmap;
cursor->win32.handle = (HCURSOR) CreateIconIndirect(&ii);
DeleteObject(bitmap);
DeleteObject(mask);
if (!cursor->win32.handle) if (!cursor->win32.handle)
return GLFW_FALSE; return GLFW_FALSE;
@ -1301,6 +1518,7 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{ {
RECT area;
POINT pos; POINT pos;
if (_glfw.cursorWindow != window) if (_glfw.cursorWindow != window)
@ -1315,6 +1533,13 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
if (WindowFromPoint(pos) != window->win32.handle) if (WindowFromPoint(pos) != window->win32.handle)
return; return;
GetClientRect(window->win32.handle, &area);
ClientToScreen(window->win32.handle, (POINT*) &area.left);
ClientToScreen(window->win32.handle, (POINT*) &area.right);
if (!PtInRect(&area, pos))
return;
if (cursor) if (cursor)
SetCursor(cursor->win32.handle); SetCursor(cursor->win32.handle);
else else
@ -1403,7 +1628,7 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
return _glfw.win32.clipboardString; return _glfw.win32.clipboardString;
} }
char** _glfwPlatformGetRequiredInstanceExtensions(int* count) char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
{ {
char** extensions; char** extensions;
@ -1422,7 +1647,7 @@ char** _glfwPlatformGetRequiredInstanceExtensions(int* count)
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
unsigned int queuefamily) uint32_t queuefamily)
{ {
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR = PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR =
(PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR) (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)

View File

@ -31,6 +31,7 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <float.h>
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -109,6 +110,11 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window)
window->callbacks.close((GLFWwindow*) window); window->callbacks.close((GLFWwindow*) window);
} }
void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor)
{
window->monitor = monitor;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW public API ////// ////// GLFW public API //////
@ -125,44 +131,37 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
_GLFWwindow* window; _GLFWwindow* window;
_GLFWwindow* previous; _GLFWwindow* previous;
assert(title); assert(title != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (width <= 0 || height <= 0) if (width <= 0 || height <= 0)
{ {
_glfwInputError(GLFW_INVALID_VALUE, "Invalid window size"); _glfwInputError(GLFW_INVALID_VALUE,
"Invalid window size %ix%i",
width, height);
return NULL; return NULL;
} }
fbconfig = _glfw.hints.framebuffer; fbconfig = _glfw.hints.framebuffer;
ctxconfig = _glfw.hints.context; ctxconfig = _glfw.hints.context;
wndconfig = _glfw.hints.window; wndconfig = _glfw.hints.window;
fbconfig.transparent = _glfw.hints.framebuffer.transparent;
wndconfig.width = width; wndconfig.width = width;
wndconfig.height = height; wndconfig.height = height;
wndconfig.title = title; wndconfig.title = title;
wndconfig.monitor = (_GLFWmonitor*) monitor; ctxconfig.share = (_GLFWwindow*) share;
ctxconfig.share = (_GLFWwindow*) share;
wndconfig.transparent = _glfw.hints.framebuffer.transparent;
if (ctxconfig.share) if (ctxconfig.share)
{ {
if (ctxconfig.share->context.api == GLFW_NO_API) if (ctxconfig.share->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL; return NULL;
} }
} }
if (wndconfig.monitor)
{
wndconfig.resizable = GLFW_TRUE;
wndconfig.visible = GLFW_TRUE;
wndconfig.focused = GLFW_TRUE;
}
if (!_glfwIsValidContextConfig(&ctxconfig)) if (!_glfwIsValidContextConfig(&ctxconfig))
return NULL; return NULL;
@ -177,7 +176,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->videoMode.blueBits = fbconfig.blueBits; window->videoMode.blueBits = fbconfig.blueBits;
window->videoMode.refreshRate = _glfw.hints.refreshRate; window->videoMode.refreshRate = _glfw.hints.refreshRate;
window->monitor = wndconfig.monitor; window->monitor = (_GLFWmonitor*) monitor;
window->resizable = wndconfig.resizable; window->resizable = wndconfig.resizable;
window->decorated = wndconfig.decorated; window->decorated = wndconfig.decorated;
window->autoIconify = wndconfig.autoIconify; window->autoIconify = wndconfig.autoIconify;
@ -185,42 +184,43 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->transparent = wndconfig.transparent; window->transparent = wndconfig.transparent;
window->cursorMode = GLFW_CURSOR_NORMAL; window->cursorMode = GLFW_CURSOR_NORMAL;
window->minwidth = GLFW_DONT_CARE;
window->minheight = GLFW_DONT_CARE;
window->maxwidth = GLFW_DONT_CARE;
window->maxheight = GLFW_DONT_CARE;
window->numer = GLFW_DONT_CARE;
window->denom = GLFW_DONT_CARE;
// Save the currently current context so it can be restored later // Save the currently current context so it can be restored later
previous = _glfwPlatformGetCurrentContext(); previous = _glfwPlatformGetCurrentContext();
if (ctxconfig.client != GLFW_NO_API)
glfwMakeContextCurrent(NULL);
// Open the actual window and create its context // Open the actual window and create its context
if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig)) if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
{ {
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwDestroyWindow((GLFWwindow*) window); glfwDestroyWindow((GLFWwindow*) window);
_glfwPlatformMakeContextCurrent(previous);
return NULL; return NULL;
} }
if (ctxconfig.api != GLFW_NO_API) if (ctxconfig.client != GLFW_NO_API)
{ {
_glfwPlatformMakeContextCurrent(window); window->context.makeContextCurrent(window);
// Retrieve the actual (as opposed to requested) context attributes // Retrieve the actual (as opposed to requested) context attributes
if (!_glfwRefreshContextAttribs(&ctxconfig)) if (!_glfwRefreshContextAttribs(&ctxconfig))
{ {
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwDestroyWindow((GLFWwindow*) window); glfwDestroyWindow((GLFWwindow*) window);
_glfwPlatformMakeContextCurrent(previous);
return NULL;
}
// Verify the context against the requested parameters
if (!_glfwIsValidContext(&ctxconfig))
{
glfwDestroyWindow((GLFWwindow*) window);
_glfwPlatformMakeContextCurrent(previous);
return NULL; return NULL;
} }
// Restore the previously current context (or NULL) // Restore the previously current context (or NULL)
_glfwPlatformMakeContextCurrent(previous); glfwMakeContextCurrent((GLFWwindow*) previous);
} }
if (wndconfig.monitor) if (window->monitor)
{ {
int width, height; int width, height;
_glfwPlatformGetWindowSize(window, &width, &height); _glfwPlatformGetWindowSize(window, &width, &height);
@ -234,10 +234,9 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
{ {
if (wndconfig.visible) if (wndconfig.visible)
{ {
_glfwPlatformShowWindow(window);
if (wndconfig.focused) if (wndconfig.focused)
_glfwPlatformShowWindow(window); _glfwPlatformFocusWindow(window);
else
_glfwPlatformUnhideWindow(window);
} }
} }
@ -251,9 +250,10 @@ void glfwDefaultWindowHints(void)
memset(&_glfw.hints, 0, sizeof(_glfw.hints)); memset(&_glfw.hints, 0, sizeof(_glfw.hints));
// The default is OpenGL with minimum version 1.0 // The default is OpenGL with minimum version 1.0
_glfw.hints.context.api = GLFW_OPENGL_API; _glfw.hints.context.client = GLFW_OPENGL_API;
_glfw.hints.context.major = 1; _glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
_glfw.hints.context.minor = 0; _glfw.hints.context.major = 1;
_glfw.hints.context.minor = 0;
// The default is a focused, visible, resizable window with decorations // The default is a focused, visible, resizable window with decorations
_glfw.hints.window.resizable = GLFW_TRUE; _glfw.hints.window.resizable = GLFW_TRUE;
@ -346,11 +346,17 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_FLOATING: case GLFW_FLOATING:
_glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
break; break;
case GLFW_MAXIMIZED:
_glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
break;
case GLFW_VISIBLE: case GLFW_VISIBLE:
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
break; break;
case GLFW_CLIENT_API: case GLFW_CLIENT_API:
_glfw.hints.context.api = value; _glfw.hints.context.client = value;
break;
case GLFW_CONTEXT_CREATION_API:
_glfw.hints.context.source = value;
break; break;
case GLFW_CONTEXT_VERSION_MAJOR: case GLFW_CONTEXT_VERSION_MAJOR:
_glfw.hints.context.major = value; _glfw.hints.context.major = value;
@ -380,7 +386,7 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.refreshRate = value; _glfw.hints.refreshRate = value;
break; break;
default: default:
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint"); _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint %i", hint);
break; break;
} }
} }
@ -401,7 +407,7 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
// The window's context must not be current on another thread when the // The window's context must not be current on another thread when the
// window is destroyed // window is destroyed
if (window == _glfwPlatformGetCurrentContext()) if (window == _glfwPlatformGetCurrentContext())
_glfwPlatformMakeContextCurrent(NULL); glfwMakeContextCurrent(NULL);
// Clear the focused window pointer if this is the focused window // Clear the focused window pointer if this is the focused window
if (_glfw.cursorWindow == window) if (_glfw.cursorWindow == window)
@ -425,7 +431,7 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle) GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(0); _GLFW_REQUIRE_INIT_OR_RETURN(0);
return window->closed; return window->closed;
@ -434,7 +440,7 @@ GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle)
GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value) GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
window->closed = value; window->closed = value;
@ -443,18 +449,30 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title) GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
assert(title); assert(title != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_glfwPlatformSetWindowTitle(window, title); _glfwPlatformSetWindowTitle(window, title);
} }
GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,
int count, const GLFWimage* images)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(count >= 0);
assert(count == 0 || images != NULL);
_GLFW_REQUIRE_INIT();
_glfwPlatformSetWindowIcon(window, count, images);
}
GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos) GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
if (xpos) if (xpos)
*xpos = 0; *xpos = 0;
@ -468,16 +486,12 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos)
GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos) GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (window->monitor) if (window->monitor)
{
_glfwInputError(GLFW_INVALID_VALUE,
"Full screen windows cannot be moved");
return; return;
}
_glfwPlatformSetWindowPos(window, xpos, ypos); _glfwPlatformSetWindowPos(window, xpos, ypos);
} }
@ -485,7 +499,7 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos)
GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height) GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
if (width) if (width)
*width = 0; *width = 0;
@ -499,15 +513,12 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height)
GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height) GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (window->monitor) window->videoMode.width = width;
{ window->videoMode.height = height;
window->videoMode.width = width;
window->videoMode.height = height;
}
_glfwPlatformSetWindowSize(window, width, height); _glfwPlatformSetWindowSize(window, width, height);
} }
@ -517,10 +528,22 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle,
int maxwidth, int maxheight) int maxwidth, int maxheight)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (minwidth < 0 || minheight < 0 ||
maxwidth < minwidth || maxheight < minheight)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid window size limits");
return;
}
window->minwidth = minwidth;
window->minheight = minheight;
window->maxwidth = maxwidth;
window->maxheight = maxheight;
if (window->monitor || !window->resizable) if (window->monitor || !window->resizable)
return; return;
@ -532,19 +555,22 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle,
GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom) GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (window->monitor || !window->resizable) if (numer <= 0 || denom <= 0)
return;
if (!denom)
{ {
_glfwInputError(GLFW_INVALID_VALUE, "Denominator cannot be zero"); _glfwInputError(GLFW_INVALID_VALUE, "Invalid window aspect ratio");
return; return;
} }
window->numer = numer;
window->denom = denom;
if (window->monitor || !window->resizable)
return;
_glfwPlatformSetWindowAspectRatio(window, numer, denom); _glfwPlatformSetWindowAspectRatio(window, numer, denom);
} }
@ -567,7 +593,7 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
int* right, int* bottom) int* right, int* bottom)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
if (left) if (left)
*left = 0; *left = 0;
@ -585,7 +611,7 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
GLFWAPI void glfwIconifyWindow(GLFWwindow* handle) GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_glfwPlatformIconifyWindow(window); _glfwPlatformIconifyWindow(window);
@ -594,16 +620,23 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
GLFWAPI void glfwRestoreWindow(GLFWwindow* handle) GLFWAPI void glfwRestoreWindow(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_glfwPlatformRestoreWindow(window); _glfwPlatformRestoreWindow(window);
} }
GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT();
_glfwPlatformMaximizeWindow(window);
}
GLFWAPI void glfwShowWindow(GLFWwindow* handle) GLFWAPI void glfwShowWindow(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
@ -611,12 +644,13 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle)
return; return;
_glfwPlatformShowWindow(window); _glfwPlatformShowWindow(window);
_glfwPlatformFocusWindow(window);
} }
GLFWAPI void glfwHideWindow(GLFWwindow* handle) GLFWAPI void glfwHideWindow(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
@ -626,10 +660,20 @@ GLFWAPI void glfwHideWindow(GLFWwindow* handle)
_glfwPlatformHideWindow(window); _glfwPlatformHideWindow(window);
} }
GLFWAPI void glfwFocusWindow(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT();
_glfwPlatformFocusWindow(window);
}
GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(0); _GLFW_REQUIRE_INIT_OR_RETURN(0);
@ -641,6 +685,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return _glfwPlatformWindowIconified(window); return _glfwPlatformWindowIconified(window);
case GLFW_VISIBLE: case GLFW_VISIBLE:
return _glfwPlatformWindowVisible(window); return _glfwPlatformWindowVisible(window);
case GLFW_MAXIMIZED:
return _glfwPlatformWindowMaximized(window);
case GLFW_RESIZABLE: case GLFW_RESIZABLE:
return window->resizable; return window->resizable;
case GLFW_DECORATED: case GLFW_DECORATED:
@ -648,7 +694,9 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
case GLFW_FLOATING: case GLFW_FLOATING:
return window->floating; return window->floating;
case GLFW_CLIENT_API: case GLFW_CLIENT_API:
return window->context.api; return window->context.client;
case GLFW_CONTEXT_CREATION_API:
return window->context.source;
case GLFW_CONTEXT_VERSION_MAJOR: case GLFW_CONTEXT_VERSION_MAJOR:
return window->context.major; return window->context.major;
case GLFW_CONTEXT_VERSION_MINOR: case GLFW_CONTEXT_VERSION_MINOR:
@ -669,23 +717,44 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return window->context.noerror; return window->context.noerror;
} }
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute"); _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute %i", attrib);
return 0; return 0;
} }
GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle) GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return (GLFWmonitor*) window->monitor; return (GLFWmonitor*) window->monitor;
} }
GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
GLFWmonitor* mh,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
_GLFWwindow* window = (_GLFWwindow*) wh;
_GLFWmonitor* monitor = (_GLFWmonitor*) mh;
assert(window);
_GLFW_REQUIRE_INIT();
window->videoMode.width = width;
window->videoMode.height = height;
window->videoMode.refreshRate = refreshRate;
_glfwPlatformSetWindowMonitor(window, monitor,
xpos, ypos, width, height,
refreshRate);
}
GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer) GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
window->userPointer = pointer; window->userPointer = pointer;
@ -694,7 +763,7 @@ GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer)
GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle) GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return window->userPointer; return window->userPointer;
@ -704,7 +773,7 @@ GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle,
GLFWwindowposfun cbfun) GLFWwindowposfun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.pos, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.pos, cbfun);
@ -715,7 +784,7 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle,
GLFWwindowsizefun cbfun) GLFWwindowsizefun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.size, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.size, cbfun);
@ -726,7 +795,7 @@ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle,
GLFWwindowclosefun cbfun) GLFWwindowclosefun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.close, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.close, cbfun);
@ -737,7 +806,7 @@ GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle,
GLFWwindowrefreshfun cbfun) GLFWwindowrefreshfun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.refresh, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.refresh, cbfun);
@ -748,7 +817,7 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle,
GLFWwindowfocusfun cbfun) GLFWwindowfocusfun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.focus, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.focus, cbfun);
@ -759,7 +828,7 @@ GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
GLFWwindowiconifyfun cbfun) GLFWwindowiconifyfun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.iconify, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.iconify, cbfun);
@ -770,7 +839,7 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle
GLFWframebuffersizefun cbfun) GLFWframebuffersizefun cbfun)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.fbsize, cbfun); _GLFW_SWAP_POINTERS(window->callbacks.fbsize, cbfun);
@ -793,6 +862,19 @@ GLFWAPI void glfwWaitEvents(void)
_glfwPlatformWaitEvents(); _glfwPlatformWaitEvents();
} }
GLFWAPI void glfwWaitEventsTimeout(double timeout)
{
_GLFW_REQUIRE_INIT();
if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout);
return;
}
_glfwPlatformWaitEventsTimeout(timeout);
}
GLFWAPI void glfwPostEmptyEvent(void) GLFWAPI void glfwPostEmptyEvent(void)
{ {
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();

View File

@ -84,12 +84,7 @@ static void pointerHandleMotion(void* data,
return; return;
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
/* TODO */
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: GLFW_CURSOR_DISABLED not supported");
return; return;
}
else else
{ {
window->wl.cursorPosX = wl_fixed_to_double(sx); window->wl.cursorPosX = wl_fixed_to_double(sx);
@ -413,6 +408,20 @@ static void registryHandleGlobal(void* data,
wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL); wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
} }
} }
else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)
{
_glfw.wl.relativePointerManager =
wl_registry_bind(registry, name,
&zwp_relative_pointer_manager_v1_interface,
1);
}
else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0)
{
_glfw.wl.pointerConstraints =
wl_registry_bind(registry, name,
&zwp_pointer_constraints_v1_interface,
1);
}
} }
static void registryHandleGlobalRemove(void *data, static void registryHandleGlobalRemove(void *data,

View File

@ -244,13 +244,15 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{ {
// TODO // TODO
fprintf(stderr, "_glfwPlatformGetGammaRamp not implemented yet\n"); _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Gamma ramp getting not supported yet");
} }
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{ {
// TODO // TODO
fprintf(stderr, "_glfwPlatformSetGammaRamp not implemented yet\n"); _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Gamma ramp setting not supported yet");
} }

View File

@ -49,12 +49,10 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#include "posix_time.h" #include "posix_time.h"
#include "linux_joystick.h" #include "linux_joystick.h"
#include "xkb_unicode.h" #include "xkb_unicode.h"
#include "egl_context.h"
#if defined(_GLFW_EGL) #include "wayland-relative-pointer-unstable-v1-client-protocol.h"
#include "egl_context.h" #include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
#else
#error "The Wayland backend depends on EGL platform support"
#endif
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle) #define _glfw_dlclose(handle) dlclose(handle)
@ -68,6 +66,9 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWayland wl #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWayland wl
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWayland wl #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWayland wl
#define _GLFW_PLATFORM_CONTEXT_STATE
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
// Wayland-specific video mode data // Wayland-specific video mode data
// //
@ -80,6 +81,7 @@ typedef struct _GLFWwindowWayland
{ {
int width, height; int width, height;
GLFWbool visible; GLFWbool visible;
GLFWbool maximized;
struct wl_surface* surface; struct wl_surface* surface;
struct wl_egl_window* native; struct wl_egl_window* native;
struct wl_shell_surface* shell_surface; struct wl_shell_surface* shell_surface;
@ -88,6 +90,8 @@ typedef struct _GLFWwindowWayland
_GLFWcursor* currentCursor; _GLFWcursor* currentCursor;
double cursorPosX, cursorPosY; double cursorPosX, cursorPosY;
char* title;
// We need to track the monitors the window spans on to calculate the // We need to track the monitors the window spans on to calculate the
// optimal scaling factor. // optimal scaling factor.
int scale; int scale;
@ -95,6 +99,10 @@ typedef struct _GLFWwindowWayland
int monitorsCount; int monitorsCount;
int monitorsSize; int monitorsSize;
struct {
struct zwp_relative_pointer_v1* relativePointer;
struct zwp_locked_pointer_v1* lockedPointer;
} pointerLock;
} _GLFWwindowWayland; } _GLFWwindowWayland;
@ -110,6 +118,8 @@ typedef struct _GLFWlibraryWayland
struct wl_seat* seat; struct wl_seat* seat;
struct wl_pointer* pointer; struct wl_pointer* pointer;
struct wl_keyboard* keyboard; struct wl_keyboard* keyboard;
struct zwp_relative_pointer_manager_v1* relativePointerManager;
struct zwp_pointer_constraints_v1* pointerConstraints;
int wl_compositor_version; int wl_compositor_version;

View File

@ -55,7 +55,32 @@ static void handleConfigure(void* data,
int32_t height) int32_t height)
{ {
_GLFWwindow* window = data; _GLFWwindow* window = data;
_glfwInputFramebufferSize(window, width, height); float aspectRatio;
float targetRatio;
if (!window->monitor)
{
if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
{
aspectRatio = (float)width / (float)height;
targetRatio = (float)window->numer / (float)window->denom;
if (aspectRatio < targetRatio)
height = width / targetRatio;
else if (aspectRatio > targetRatio)
width = height * targetRatio;
}
if (window->minwidth != GLFW_DONT_CARE && width < window->minwidth)
width = window->minwidth;
else if (window->maxwidth != GLFW_DONT_CARE && width > window->maxwidth)
width = window->maxwidth;
if (window->minheight != GLFW_DONT_CARE && height < window->minheight)
height = window->minheight;
else if (window->maxheight != GLFW_DONT_CARE && height > window->maxheight)
height = window->maxheight;
}
_glfwInputWindowSize(window, width, height); _glfwInputWindowSize(window, width, height);
_glfwPlatformSetWindowSize(window, width, height); _glfwPlatformSetWindowSize(window, width, height);
_glfwInputWindowDamage(window); _glfwInputWindowDamage(window);
@ -80,8 +105,7 @@ static void checkScaleChange(_GLFWwindow* window)
int monitorScale; int monitorScale;
// Check if we will be able to set the buffer scale or not. // Check if we will be able to set the buffer scale or not.
if (_glfw.wl.wl_compositor_version < if (_glfw.wl.wl_compositor_version < 3)
WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
return; return;
// Get the scale factor from the highest scale monitor. // Get the scale factor from the highest scale monitor.
@ -150,6 +174,21 @@ static const struct wl_surface_listener surfaceListener = {
handleLeave handleLeave
}; };
// Makes the surface considered as XRGB instead of ARGB.
static void setOpaqueRegion(_GLFWwindow* window)
{
struct wl_region* region;
region = wl_compositor_create_region(_glfw.wl.compositor);
if (!region)
return;
wl_region_add(region, 0, 0, window->wl.width, window->wl.height);
wl_surface_set_opaque_region(window->wl.surface, region);
wl_surface_commit(window->wl.surface);
wl_region_destroy(region);
}
static GLFWbool createSurface(_GLFWwindow* window, static GLFWbool createSurface(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig) const _GLFWwndconfig* wndconfig)
{ {
@ -169,6 +208,18 @@ static GLFWbool createSurface(_GLFWwindow* window,
if (!window->wl.native) if (!window->wl.native)
return GLFW_FALSE; return GLFW_FALSE;
window->wl.width = wndconfig->width;
window->wl.height = wndconfig->height;
window->wl.scale = 1;
// TODO: make this optional once issue #197 is fixed.
setOpaqueRegion(window);
return GLFW_TRUE;
}
static GLFWbool createShellSurface(_GLFWwindow* window)
{
window->wl.shell_surface = wl_shell_get_shell_surface(_glfw.wl.shell, window->wl.shell_surface = wl_shell_get_shell_surface(_glfw.wl.shell,
window->wl.surface); window->wl.surface);
if (!window->wl.shell_surface) if (!window->wl.shell_surface)
@ -178,9 +229,25 @@ static GLFWbool createSurface(_GLFWwindow* window,
&shellSurfaceListener, &shellSurfaceListener,
window); window);
window->wl.width = wndconfig->width; if (window->wl.title)
window->wl.height = wndconfig->height; wl_shell_surface_set_title(window->wl.shell_surface, window->wl.title);
window->wl.scale = 1;
if (window->monitor)
{
wl_shell_surface_set_fullscreen(
window->wl.shell_surface,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
0,
window->monitor->wl.output);
}
else if (window->wl.maximized)
{
wl_shell_surface_set_maximized(window->wl.shell_surface, NULL);
}
else
{
wl_shell_surface_set_toplevel(window->wl.shell_surface);
}
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -324,23 +391,26 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!createSurface(window, wndconfig)) if (!createSurface(window, wndconfig))
return GLFW_FALSE; return GLFW_FALSE;
if (ctxconfig->api != GLFW_NO_API) if (ctxconfig->client != GLFW_NO_API)
{ {
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE; return GLFW_FALSE;
} }
if (wndconfig->monitor) if (wndconfig->title)
window->wl.title = strdup(wndconfig->title);
if (wndconfig->visible)
{ {
wl_shell_surface_set_fullscreen( if (!createShellSurface(window))
window->wl.shell_surface, return GLFW_FALSE;
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
0, window->wl.visible = GLFW_TRUE;
wndconfig->monitor->wl.output);
} }
else else
{ {
wl_shell_surface_set_toplevel(window->wl.shell_surface); window->wl.shell_surface = NULL;
window->wl.visible = GLFW_FALSE;
} }
window->wl.currentCursor = NULL; window->wl.currentCursor = NULL;
@ -365,7 +435,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
_glfwInputWindowFocus(window, GLFW_FALSE); _glfwInputWindowFocus(window, GLFW_FALSE);
} }
_glfwDestroyContextEGL(window); if (window->context.client != GLFW_NO_API)
window->context.destroyContext(window);
if (window->wl.native) if (window->wl.native)
wl_egl_window_destroy(window->wl.native); wl_egl_window_destroy(window->wl.native);
@ -376,12 +447,24 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
if (window->wl.surface) if (window->wl.surface)
wl_surface_destroy(window->wl.surface); wl_surface_destroy(window->wl.surface);
free(window->wl.title);
free(window->wl.monitors); free(window->wl.monitors);
} }
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
{ {
wl_shell_surface_set_title(window->wl.shell_surface, title); if (window->wl.title)
free(window->wl.title);
window->wl.title = strdup(title);
if (window->wl.shell_surface)
wl_shell_surface_set_title(window->wl.shell_surface, title);
}
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
int count, const GLFWimage* images)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Setting window icon not supported");
} }
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
@ -416,6 +499,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
window->wl.width = width; window->wl.width = width;
window->wl.height = height; window->wl.height = height;
wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0); wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
setOpaqueRegion(window);
_glfwInputFramebufferSize(window, scaledWidth, scaledHeight); _glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
} }
@ -423,14 +507,14 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight, int minwidth, int minheight,
int maxwidth, int maxheight) int maxwidth, int maxheight)
{ {
// TODO // TODO: find out how to trigger a resize.
fprintf(stderr, "_glfwPlatformSetWindowSizeLimits not implemented yet\n"); // The actual limits are checked in the wl_shell_surface::configure handler.
} }
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom) void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
{ {
// TODO // TODO: find out how to trigger a resize.
fprintf(stderr, "_glfwPlatformSetWindowAspectRatio not implemented yet\n"); // The actual limits are checked in the wl_shell_surface::configure handler.
} }
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
@ -444,55 +528,108 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
int* left, int* top, int* left, int* top,
int* right, int* bottom) int* right, int* bottom)
{ {
// TODO // TODO: will need a proper implementation once decorations are
fprintf(stderr, "_glfwPlatformGetWindowFrameSize not implemented yet\n"); // implemented, but for now just leave everything as 0.
} }
void _glfwPlatformIconifyWindow(_GLFWwindow* window) void _glfwPlatformIconifyWindow(_GLFWwindow* window)
{ {
// TODO // TODO: move to xdg_shell instead of wl_shell.
fprintf(stderr, "_glfwPlatformIconifyWindow not implemented yet\n"); _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Iconify window not supported");
} }
void _glfwPlatformRestoreWindow(_GLFWwindow* window) void _glfwPlatformRestoreWindow(_GLFWwindow* window)
{ {
// TODO // TODO: also do the same for iconified.
fprintf(stderr, "_glfwPlatformRestoreWindow not implemented yet\n"); if (window->monitor || window->wl.maximized)
{
if (window->wl.shell_surface)
wl_shell_surface_set_toplevel(window->wl.shell_surface);
window->wl.maximized = GLFW_FALSE;
}
}
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{
if (!window->monitor && !window->wl.maximized)
{
if (window->wl.shell_surface)
{
// Let the compositor select the best output.
wl_shell_surface_set_maximized(window->wl.shell_surface, NULL);
}
window->wl.maximized = GLFW_TRUE;
}
} }
void _glfwPlatformShowWindow(_GLFWwindow* window) void _glfwPlatformShowWindow(_GLFWwindow* window)
{ {
wl_shell_surface_set_toplevel(window->wl.shell_surface); if (!window->monitor)
} {
if (!window->wl.shell_surface)
void _glfwPlatformUnhideWindow(_GLFWwindow* window) createShellSurface(window);
{ window->wl.visible = GLFW_TRUE;
// TODO }
fprintf(stderr, "_glfwPlatformUnhideWindow not implemented yet\n");
} }
void _glfwPlatformHideWindow(_GLFWwindow* window) void _glfwPlatformHideWindow(_GLFWwindow* window)
{ {
wl_surface_attach(window->wl.surface, NULL, 0, 0); if (!window->monitor)
wl_surface_commit(window->wl.surface); {
if (window->wl.shell_surface)
wl_shell_surface_destroy(window->wl.shell_surface);
window->wl.visible = GLFW_FALSE;
}
}
void _glfwPlatformFocusWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Focusing a window requires user interaction");
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
if (monitor)
{
wl_shell_surface_set_fullscreen(
window->wl.shell_surface,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
refreshRate * 1000, // Convert Hz to mHz.
monitor->wl.output);
}
else
{
wl_shell_surface_set_toplevel(window->wl.shell_surface);
}
_glfwInputWindowMonitorChange(window, monitor);
} }
int _glfwPlatformWindowFocused(_GLFWwindow* window) int _glfwPlatformWindowFocused(_GLFWwindow* window)
{ {
// TODO return _glfw.wl.keyboardFocus == window;
return GLFW_FALSE;
} }
int _glfwPlatformWindowIconified(_GLFWwindow* window) int _glfwPlatformWindowIconified(_GLFWwindow* window)
{ {
// TODO // TODO: move to xdg_shell, wl_shell doesn't have any iconified concept.
return GLFW_FALSE; return GLFW_FALSE;
} }
int _glfwPlatformWindowVisible(_GLFWwindow* window) int _glfwPlatformWindowVisible(_GLFWwindow* window)
{ {
// TODO return window->wl.visible;
return GLFW_FALSE; }
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
{
return window->wl.maximized;
} }
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
@ -505,6 +642,11 @@ void _glfwPlatformWaitEvents(void)
handleEvents(-1); handleEvents(-1);
} }
void _glfwPlatformWaitEventsTimeout(double timeout)
{
handleEvents((int) (timeout * 1e3));
}
void _glfwPlatformPostEmptyEvent(void) void _glfwPlatformPostEmptyEvent(void)
{ {
wl_display_sync(_glfw.wl.display); wl_display_sync(_glfw.wl.display);
@ -518,11 +660,17 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
*ypos = window->wl.cursorPosY; *ypos = window->wl.cursorPosY;
} }
static GLFWbool isPointerLocked(_GLFWwindow* window);
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
{ {
// A Wayland client can not set the cursor position if (isPointerLocked(window))
_glfwInputError(GLFW_PLATFORM_ERROR, {
"Wayland: Cursor position setting not supported"); zwp_locked_pointer_v1_set_cursor_position_hint(
window->wl.pointerLock.lockedPointer,
wl_fixed_from_double(x), wl_fixed_from_double(y));
wl_surface_commit(window->wl.surface);
}
} }
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
@ -550,7 +698,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
if (fd < 0) if (fd < 0)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Creating a buffer file for %d B failed: %m\n", "Wayland: Creating a buffer file for %d B failed: %m",
length); length);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -559,7 +707,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
if (data == MAP_FAILED) if (data == MAP_FAILED)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Cursor mmap failed: %m\n"); "Wayland: Cursor mmap failed: %m");
close(fd); close(fd);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -571,10 +719,12 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
unsigned char* target = data; unsigned char* target = data;
for (i = 0; i < image->width * image->height; i++, source += 4) for (i = 0; i < image->width * image->height; i++, source += 4)
{ {
*target++ = source[2]; unsigned int alpha = source[3];
*target++ = source[1];
*target++ = source[0]; *target++ = (unsigned char) ((source[2] * alpha) / 255);
*target++ = source[3]; *target++ = (unsigned char) ((source[1] * alpha) / 255);
*target++ = (unsigned char) ((source[0] * alpha) / 255);
*target++ = (unsigned char) alpha;
} }
cursor->wl.buffer = cursor->wl.buffer =
@ -620,6 +770,103 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
wl_buffer_destroy(cursor->wl.buffer); wl_buffer_destroy(cursor->wl.buffer);
} }
static void handleRelativeMotion(void* data,
struct zwp_relative_pointer_v1* pointer,
uint32_t timeHi,
uint32_t timeLo,
wl_fixed_t dx,
wl_fixed_t dy,
wl_fixed_t dxUnaccel,
wl_fixed_t dyUnaccel)
{
_GLFWwindow* window = data;
if (window->cursorMode != GLFW_CURSOR_DISABLED)
return;
_glfwInputCursorMotion(window,
wl_fixed_to_double(dxUnaccel),
wl_fixed_to_double(dyUnaccel));
}
static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
handleRelativeMotion
};
static void handleLocked(void* data,
struct zwp_locked_pointer_v1* lockedPointer)
{
}
static void unlockPointer(_GLFWwindow* window)
{
struct zwp_relative_pointer_v1* relativePointer =
window->wl.pointerLock.relativePointer;
struct zwp_locked_pointer_v1* lockedPointer =
window->wl.pointerLock.lockedPointer;
zwp_relative_pointer_v1_destroy(relativePointer);
zwp_locked_pointer_v1_destroy(lockedPointer);
window->wl.pointerLock.relativePointer = NULL;
window->wl.pointerLock.lockedPointer = NULL;
}
static void lockPointer(_GLFWwindow* window);
static void handleUnlocked(void* data,
struct zwp_locked_pointer_v1* lockedPointer)
{
}
static const struct zwp_locked_pointer_v1_listener lockedPointerListener = {
handleLocked,
handleUnlocked
};
static void lockPointer(_GLFWwindow* window)
{
struct zwp_relative_pointer_v1* relativePointer;
struct zwp_locked_pointer_v1* lockedPointer;
if (!_glfw.wl.relativePointerManager)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: no relative pointer manager");
return;
}
relativePointer =
zwp_relative_pointer_manager_v1_get_relative_pointer(
_glfw.wl.relativePointerManager,
_glfw.wl.pointer);
zwp_relative_pointer_v1_add_listener(relativePointer,
&relativePointerListener,
window);
lockedPointer =
zwp_pointer_constraints_v1_lock_pointer(
_glfw.wl.pointerConstraints,
window->wl.surface,
_glfw.wl.pointer,
NULL,
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
zwp_locked_pointer_v1_add_listener(lockedPointer,
&lockedPointerListener,
window);
window->wl.pointerLock.relativePointer = relativePointer;
window->wl.pointerLock.lockedPointer = lockedPointer;
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
NULL, 0, 0);
}
static GLFWbool isPointerLocked(_GLFWwindow* window)
{
return window->wl.pointerLock.lockedPointer != NULL;
}
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{ {
struct wl_buffer* buffer; struct wl_buffer* buffer;
@ -637,6 +884,10 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
if (window != _glfw.wl.pointerFocus) if (window != _glfw.wl.pointerFocus)
return; return;
// Unlock possible pointer lock if no longer disabled.
if (window->cursorMode != GLFW_CURSOR_DISABLED && isPointerLocked(window))
unlockPointer(window);
if (window->cursorMode == GLFW_CURSOR_NORMAL) if (window->cursorMode == GLFW_CURSOR_NORMAL)
{ {
if (cursor) if (cursor)
@ -680,26 +931,34 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
wl_surface_commit(surface); wl_surface_commit(surface);
} }
} }
else /* Cursor is hidden set cursor surface to NULL */ else if (window->cursorMode == GLFW_CURSOR_DISABLED)
{ {
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial, NULL, 0, 0); if (!isPointerLocked(window))
lockPointer(window);
}
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
{
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
NULL, 0, 0);
} }
} }
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
{ {
// TODO // TODO
fprintf(stderr, "_glfwPlatformSetClipboardString not implemented yet\n"); _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Clipboard setting not implemented yet");
} }
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
{ {
// TODO // TODO
fprintf(stderr, "_glfwPlatformGetClipboardString not implemented yet\n"); _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Clipboard getting not implemented yet");
return NULL; return NULL;
} }
char** _glfwPlatformGetRequiredInstanceExtensions(int* count) char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
{ {
char** extensions; char** extensions;
@ -718,7 +977,7 @@ char** _glfwPlatformGetRequiredInstanceExtensions(int* count)
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
unsigned int queuefamily) uint32_t queuefamily)
{ {
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR = PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR =
(PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR) (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)

View File

@ -356,16 +356,13 @@ static Atom getSupportedAtom(Atom* supportedAtoms,
unsigned long atomCount, unsigned long atomCount,
const char* atomName) const char* atomName)
{ {
Atom atom = XInternAtom(_glfw.x11.display, atomName, True); unsigned long i;
if (atom != None) const Atom atom = XInternAtom(_glfw.x11.display, atomName, False);
{
unsigned long i;
for (i = 0; i < atomCount; i++) for (i = 0; i < atomCount; i++)
{ {
if (supportedAtoms[i] == atom) if (supportedAtoms[i] == atom)
return atom; return atom;
}
} }
return None; return None;
@ -378,13 +375,11 @@ static void detectEWMH(void)
Window* windowFromRoot = NULL; Window* windowFromRoot = NULL;
Window* windowFromChild = NULL; Window* windowFromChild = NULL;
// First we need a couple of atoms, which should already be there // First we need a couple of atoms
Atom supportingWmCheck = const Atom supportingWmCheck =
XInternAtom(_glfw.x11.display, "_NET_SUPPORTING_WM_CHECK", True); XInternAtom(_glfw.x11.display, "_NET_SUPPORTING_WM_CHECK", False);
Atom wmSupported = const Atom wmSupported =
XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", True); XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False);
if (supportingWmCheck == None || wmSupported == None)
return;
// Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window // Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window
if (_glfwGetWindowPropertyX11(_glfw.x11.root, if (_glfwGetWindowPropertyX11(_glfw.x11.root,
@ -444,24 +439,22 @@ static void detectEWMH(void)
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE"); getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE");
_glfw.x11.NET_WM_STATE_FULLSCREEN = _glfw.x11.NET_WM_STATE_FULLSCREEN =
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN"); getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT =
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ =
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ");
_glfw.x11.NET_WM_FULLSCREEN_MONITORS = _glfw.x11.NET_WM_FULLSCREEN_MONITORS =
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS"); getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
_glfw.x11.NET_WM_NAME = _glfw.x11.NET_WM_WINDOW_TYPE =
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_NAME"); getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");
_glfw.x11.NET_WM_ICON_NAME = _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL =
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_ICON_NAME"); getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");
_glfw.x11.NET_WM_PID =
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_PID");
_glfw.x11.NET_WM_PING =
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_PING");
_glfw.x11.NET_ACTIVE_WINDOW = _glfw.x11.NET_ACTIVE_WINDOW =
getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW"); getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");
_glfw.x11.NET_FRAME_EXTENTS = _glfw.x11.NET_FRAME_EXTENTS =
getSupportedAtom(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS"); getSupportedAtom(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS");
_glfw.x11.NET_REQUEST_FRAME_EXTENTS = _glfw.x11.NET_REQUEST_FRAME_EXTENTS =
getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS"); getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
_glfw.x11.NET_WM_BYPASS_COMPOSITOR =
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_BYPASS_COMPOSITOR");
XFree(supportedAtoms); XFree(supportedAtoms);
} }
@ -470,18 +463,6 @@ static void detectEWMH(void)
// //
static GLFWbool initExtensions(void) static GLFWbool initExtensions(void)
{ {
// Find or create window manager atoms
_glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display,
"WM_PROTOCOLS",
False);
_glfw.x11.WM_STATE = XInternAtom(_glfw.x11.display, "WM_STATE", False);
_glfw.x11.WM_DELETE_WINDOW = XInternAtom(_glfw.x11.display,
"WM_DELETE_WINDOW",
False);
_glfw.x11.MOTIF_WM_HINTS = XInternAtom(_glfw.x11.display,
"_MOTIF_WM_HINTS",
False);
#if defined(_GLFW_HAS_XF86VM) #if defined(_GLFW_HAS_XF86VM)
// Check for XF86VidMode extension // Check for XF86VidMode extension
_glfw.x11.vidmode.available = _glfw.x11.vidmode.available =
@ -540,25 +521,6 @@ static GLFWbool initExtensions(void)
_glfw.x11.xinerama.available = GLFW_TRUE; _glfw.x11.xinerama.available = GLFW_TRUE;
} }
#if defined(_GLFW_HAS_XINPUT)
if (XQueryExtension(_glfw.x11.display,
"XInputExtension",
&_glfw.x11.xi.majorOpcode,
&_glfw.x11.xi.eventBase,
&_glfw.x11.xi.errorBase))
{
_glfw.x11.xi.major = 2;
_glfw.x11.xi.minor = 0;
if (XIQueryVersion(_glfw.x11.display,
&_glfw.x11.xi.major,
&_glfw.x11.xi.minor) != BadRequest)
{
_glfw.x11.xi.available = GLFW_TRUE;
}
}
#endif /*_GLFW_HAS_XINPUT*/
// Check if Xkb is supported on this display // Check if Xkb is supported on this display
_glfw.x11.xkb.major = 1; _glfw.x11.xkb.major = 1;
_glfw.x11.xkb.minor = 0; _glfw.x11.xkb.minor = 0;
@ -596,7 +558,7 @@ static GLFWbool initExtensions(void)
// Detect whether an EWMH-conformant window manager is running // Detect whether an EWMH-conformant window manager is running
detectEWMH(); detectEWMH();
// Find or create string format atoms // String format atoms
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
_glfw.x11.UTF8_STRING = _glfw.x11.UTF8_STRING =
XInternAtom(_glfw.x11.display, "UTF8_STRING", False); XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
@ -604,38 +566,62 @@ static GLFWbool initExtensions(void)
XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False); XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False);
_glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False); _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False);
// Find or create selection property atom // Custom selection property atom
_glfw.x11.GLFW_SELECTION = _glfw.x11.GLFW_SELECTION =
XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False); XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False);
// Find or create standard clipboard atoms // ICCCM standard clipboard atoms
_glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False);
_glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False); _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False);
_glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False);
// Find or create clipboard manager atoms // Clipboard manager atoms
_glfw.x11.CLIPBOARD_MANAGER = _glfw.x11.CLIPBOARD_MANAGER =
XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False); XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False);
_glfw.x11.SAVE_TARGETS = _glfw.x11.SAVE_TARGETS =
XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False);
// Find Xdnd (drag and drop) atoms, if available // Xdnd (drag and drop) atoms
_glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", True); _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", False);
_glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", True); _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", False);
_glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", True); _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", False);
_glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", True); _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False);
_glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", True); _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False);
_glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", True); _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False);
_glfw.x11.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", True); _glfw.x11.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", False);
_glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", True); _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False);
_glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", True); _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False);
// ICCCM, EWMH and Motif window property atoms
// These can be set safely even without WM support
// The EWMH atoms that require WM support are handled in detectEWMH
_glfw.x11.WM_PROTOCOLS =
XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", False);
_glfw.x11.WM_STATE =
XInternAtom(_glfw.x11.display, "WM_STATE", False);
_glfw.x11.WM_DELETE_WINDOW =
XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False);
_glfw.x11.NET_WM_ICON =
XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False);
_glfw.x11.NET_WM_PING =
XInternAtom(_glfw.x11.display, "_NET_WM_PING", False);
_glfw.x11.NET_WM_PID =
XInternAtom(_glfw.x11.display, "_NET_WM_PID", False);
_glfw.x11.NET_WM_NAME =
XInternAtom(_glfw.x11.display, "_NET_WM_NAME", False);
_glfw.x11.NET_WM_ICON_NAME =
XInternAtom(_glfw.x11.display, "_NET_WM_ICON_NAME", False);
_glfw.x11.NET_WM_BYPASS_COMPOSITOR =
XInternAtom(_glfw.x11.display, "_NET_WM_BYPASS_COMPOSITOR", False);
_glfw.x11.MOTIF_WM_HINTS =
XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False);
return GLFW_TRUE; return GLFW_TRUE;
} }
// Create a blank cursor for hidden and disabled cursor modes // Create a blank cursor for hidden and disabled cursor modes
// //
static Cursor createNULLCursor(void) static Cursor createHiddenCursor(void)
{ {
unsigned char pixels[16 * 16 * 4]; unsigned char pixels[16 * 16 * 4];
GLFWimage image = { 16, 16, pixels }; GLFWimage image = { 16, 16, pixels };
@ -705,10 +691,12 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
for (i = 0; i < image->width * image->height; i++, target++, source += 4) for (i = 0; i < image->width * image->height; i++, target++, source += 4)
{ {
*target = (source[3] << 24) | unsigned int alpha = source[3];
(source[0] << 16) |
(source[1] << 8) | *target = (alpha << 24) |
source[2]; ((unsigned char) ((source[0] * alpha) / 255) << 16) |
((unsigned char) ((source[1] * alpha) / 255) << 8) |
((unsigned char) ((source[2] * alpha) / 255) << 0);
} }
cursor = XcursorImageLoadCursor(_glfw.x11.display, native); cursor = XcursorImageLoadCursor(_glfw.x11.display, native);
@ -758,7 +746,7 @@ int _glfwPlatformInit(void)
if (!initExtensions()) if (!initExtensions())
return GLFW_FALSE; return GLFW_FALSE;
_glfw.x11.cursor = createNULLCursor(); _glfw.x11.cursor = createHiddenCursor();
if (XSupportsLocale()) if (XSupportsLocale())
{ {
@ -778,17 +766,13 @@ int _glfwPlatformInit(void)
if (!_glfwInitThreadLocalStoragePOSIX()) if (!_glfwInitThreadLocalStoragePOSIX())
return GLFW_FALSE; return GLFW_FALSE;
#if defined(_GLFW_GLX)
if (!_glfwInitGLX()) if (!_glfwInitGLX())
return GLFW_FALSE; return GLFW_FALSE;
#elif defined(_GLFW_EGL)
if (!_glfwInitEGL())
return GLFW_FALSE;
#endif
if (!_glfwInitJoysticksLinux()) if (!_glfwInitJoysticksLinux())
return GLFW_FALSE; return GLFW_FALSE;
_glfwInitEGL();
_glfwInitTimerPOSIX(); _glfwInitTimerPOSIX();
return GLFW_TRUE; return GLFW_TRUE;
@ -816,9 +800,7 @@ void _glfwPlatformTerminate(void)
_glfw.x11.im = NULL; _glfw.x11.im = NULL;
} }
#if defined(_GLFW_EGL)
_glfwTerminateEGL(); _glfwTerminateEGL();
#endif
if (_glfw.x11.display) if (_glfw.x11.display)
{ {
@ -828,9 +810,7 @@ void _glfwPlatformTerminate(void)
// NOTE: This needs to be done after XCloseDisplay, as libGL registers // NOTE: This needs to be done after XCloseDisplay, as libGL registers
// cleanup callbacks that get called by it // cleanup callbacks that get called by it
#if defined(_GLFW_GLX)
_glfwTerminateGLX(); _glfwTerminateGLX();
#endif
_glfwTerminateJoysticksLinux(); _glfwTerminateJoysticksLinux();
_glfwTerminateThreadLocalStoragePOSIX(); _glfwTerminateThreadLocalStoragePOSIX();
@ -838,12 +818,7 @@ void _glfwPlatformTerminate(void)
const char* _glfwPlatformGetVersionString(void) const char* _glfwPlatformGetVersionString(void)
{ {
return _GLFW_VERSION_NUMBER " X11" return _GLFW_VERSION_NUMBER " X11 GLX EGL"
#if defined(_GLFW_GLX)
" GLX"
#elif defined(_GLFW_EGL)
" EGL"
#endif
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK) #if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
" clock_gettime" " clock_gettime"
#else #else
@ -852,9 +827,6 @@ const char* _glfwPlatformGetVersionString(void)
#if defined(__linux__) #if defined(__linux__)
" /dev/js" " /dev/js"
#endif #endif
#if defined(_GLFW_HAS_XINPUT)
" XI"
#endif
#if defined(_GLFW_HAS_XF86VM) #if defined(_GLFW_HAS_XF86VM)
" Xf86vm" " Xf86vm"
#endif #endif

View File

@ -47,11 +47,6 @@
// The Xinerama extension provides legacy monitor indices // The Xinerama extension provides legacy monitor indices
#include <X11/extensions/Xinerama.h> #include <X11/extensions/Xinerama.h>
#if defined(_GLFW_HAS_XINPUT)
// The XInput2 extension provides improved input events
#include <X11/extensions/XInput2.h>
#endif
#if defined(_GLFW_HAS_XF86VM) #if defined(_GLFW_HAS_XF86VM)
// The Xf86VidMode extension provides fallback gamma control // The Xf86VidMode extension provides fallback gamma control
#include <X11/extensions/xf86vmode.h> #include <X11/extensions/xf86vmode.h>
@ -92,21 +87,16 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(Vk
#include "posix_time.h" #include "posix_time.h"
#include "linux_joystick.h" #include "linux_joystick.h"
#include "xkb_unicode.h" #include "xkb_unicode.h"
#include "glx_context.h"
#if defined(_GLFW_GLX) #include "egl_context.h"
#include "glx_context.h"
#elif defined(_GLFW_EGL)
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->x11.handle)
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display)
#include "egl_context.h"
#else
#error "No supported context creation API selected"
#endif
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle) #define _glfw_dlclose(handle) dlclose(handle)
#define _glfw_dlsym(handle, name) dlsym(handle, name) #define _glfw_dlsym(handle, name) dlsym(handle, name)
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->x11.handle)
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display)
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11 #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11 #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11 #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11
@ -121,6 +111,8 @@ typedef struct _GLFWwindowX11
Window handle; Window handle;
XIC ic; XIC ic;
GLFWbool overrideRedirect;
// Cached position and size used to filter out duplicate events // Cached position and size used to filter out duplicate events
int width, height; int width, height;
int xpos, ypos; int xpos, ypos;
@ -170,11 +162,16 @@ typedef struct _GLFWlibraryX11
Atom WM_DELETE_WINDOW; Atom WM_DELETE_WINDOW;
Atom NET_WM_NAME; Atom NET_WM_NAME;
Atom NET_WM_ICON_NAME; Atom NET_WM_ICON_NAME;
Atom NET_WM_ICON;
Atom NET_WM_PID; Atom NET_WM_PID;
Atom NET_WM_PING; Atom NET_WM_PING;
Atom NET_WM_WINDOW_TYPE;
Atom NET_WM_WINDOW_TYPE_NORMAL;
Atom NET_WM_STATE; Atom NET_WM_STATE;
Atom NET_WM_STATE_ABOVE; Atom NET_WM_STATE_ABOVE;
Atom NET_WM_STATE_FULLSCREEN; Atom NET_WM_STATE_FULLSCREEN;
Atom NET_WM_STATE_MAXIMIZED_VERT;
Atom NET_WM_STATE_MAXIMIZED_HORZ;
Atom NET_WM_BYPASS_COMPOSITOR; Atom NET_WM_BYPASS_COMPOSITOR;
Atom NET_WM_FULLSCREEN_MONITORS; Atom NET_WM_FULLSCREEN_MONITORS;
Atom NET_ACTIVE_WINDOW; Atom NET_ACTIVE_WINDOW;
@ -248,17 +245,6 @@ typedef struct _GLFWlibraryX11
XGETXCBCONNECTION_T XGetXCBConnection; XGETXCBCONNECTION_T XGetXCBConnection;
} x11xcb; } x11xcb;
#if defined(_GLFW_HAS_XINPUT)
struct {
GLFWbool available;
int majorOpcode;
int eventBase;
int errorBase;
int major;
int minor;
} xi;
#endif /*_GLFW_HAS_XINPUT*/
#if defined(_GLFW_HAS_XF86VM) #if defined(_GLFW_HAS_XF86VM)
struct { struct {
GLFWbool available; GLFWbool available;

File diff suppressed because it is too large Load Diff

View File

@ -30,17 +30,18 @@ add_executable(reopen reopen.c ${GLAD})
add_executable(cursor cursor.c ${GLAD}) add_executable(cursor cursor.c ${GLAD})
add_executable(empty WIN32 MACOSX_BUNDLE empty.c ${TINYCTHREAD} ${GLAD}) add_executable(empty WIN32 MACOSX_BUNDLE empty.c ${TINYCTHREAD} ${GLAD})
add_executable(icon WIN32 MACOSX_BUNDLE icon.c ${GLAD})
add_executable(sharing WIN32 MACOSX_BUNDLE sharing.c ${GLAD}) add_executable(sharing WIN32 MACOSX_BUNDLE sharing.c ${GLAD})
add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GETOPT} ${GLAD}) add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GETOPT} ${GLAD})
add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD} ${GLAD}) add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD} ${GLAD})
add_executable(transparent_threads WIN32 MACOSX_BUNDLE transparent_threads.c ${TINYCTHREAD} ${GLAD}) add_executable(timeout WIN32 MACOSX_BUNDLE timeout.c ${GLAD})
add_executable(title WIN32 MACOSX_BUNDLE title.c ${GLAD}) add_executable(title WIN32 MACOSX_BUNDLE title.c ${GLAD})
add_executable(windows WIN32 MACOSX_BUNDLE windows.c ${GLAD}) add_executable(windows WIN32 MACOSX_BUNDLE windows.c ${GETOPT} ${GLAD})
target_link_libraries(empty "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}") target_link_libraries(empty "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
target_link_libraries(threads "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}") target_link_libraries(threads "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
set(WINDOWS_BINARIES empty sharing tearing threads transparent_threads title windows) set(WINDOWS_BINARIES empty icon sharing tearing threads timeout title windows)
set(CONSOLE_BINARIES clipboard events msaa gamma glfwinfo set(CONSOLE_BINARIES clipboard events msaa gamma glfwinfo
iconify joysticks monitors reopen cursor) iconify joysticks monitors reopen cursor)
@ -65,7 +66,7 @@ if (APPLE)
set_target_properties(sharing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Sharing") set_target_properties(sharing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Sharing")
set_target_properties(tearing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Tearing") set_target_properties(tearing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Tearing")
set_target_properties(threads PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Threads") set_target_properties(threads PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Threads")
set_target_properties(transparent_threads PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Transparent threads") set_target_properties(timeout PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Timeout")
set_target_properties(title PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Title") set_target_properties(title PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Title")
set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows") set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows")

View File

@ -195,6 +195,7 @@ int main(void)
int i; int i;
GLFWwindow* window; GLFWwindow* window;
GLFWcursor* star_cursors[CURSOR_FRAME_COUNT]; GLFWcursor* star_cursors[CURSOR_FRAME_COUNT];
GLFWcursor* current_frame = NULL;
glfwSetErrorCallback(error_callback); glfwSetErrorCallback(error_callback);
@ -279,11 +280,22 @@ int main(void)
if (animate_cursor) if (animate_cursor)
{ {
const int i = (int) (glfwGetTime() * 30.0) % CURSOR_FRAME_COUNT; const int i = (int) (glfwGetTime() * 30.0) % CURSOR_FRAME_COUNT;
glfwSetCursor(window, star_cursors[i]); if (current_frame != star_cursors[i])
{
glfwSetCursor(window, star_cursors[i]);
current_frame = star_cursors[i];
}
} }
else
current_frame = NULL;
if (wait_events) if (wait_events)
glfwWaitEvents(); {
if (animate_cursor)
glfwWaitEventsTimeout(1.0 / 30.0);
else
glfwWaitEvents();
}
else else
glfwPollEvents(); glfwPollEvents();

View File

@ -451,6 +451,29 @@ static void monitor_callback(GLFWmonitor* monitor, int event)
} }
} }
static void joystick_callback(int joy, int event)
{
if (event == GLFW_CONNECTED)
{
int axisCount, buttonCount;
glfwGetJoystickAxes(joy, &axisCount);
glfwGetJoystickButtons(joy, &buttonCount);
printf("%08x at %0.3f: Joystick %i (%s) was connected with %i axes and %i buttons\n",
counter++, glfwGetTime(),
joy,
glfwGetJoystickName(joy),
axisCount,
buttonCount);
}
else
{
printf("%08x at %0.3f: Joystick %i was disconnected\n",
counter++, glfwGetTime(), joy);
}
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
Slot* slots; Slot* slots;
@ -467,6 +490,7 @@ int main(int argc, char** argv)
printf("Library initialized\n"); printf("Library initialized\n");
glfwSetMonitorCallback(monitor_callback); glfwSetMonitorCallback(monitor_callback);
glfwSetJoystickCallback(joystick_callback);
while ((ch = getopt(argc, argv, "hfn:")) != -1) while ((ch = getopt(argc, argv, "hfn:")) != -1)
{ {

View File

@ -23,8 +23,9 @@
// //
//======================================================================== //========================================================================
#include <glad/glad.h> #define VK_NO_PROTOTYPES
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <stdio.h> #include <stdio.h>
@ -40,6 +41,9 @@
#define API_NAME_OPENGL "gl" #define API_NAME_OPENGL "gl"
#define API_NAME_OPENGL_ES "es" #define API_NAME_OPENGL_ES "es"
#define API_NAME_NATIVE "native"
#define API_NAME_EGL "egl"
#define PROFILE_NAME_CORE "core" #define PROFILE_NAME_CORE "core"
#define PROFILE_NAME_COMPAT "compat" #define PROFILE_NAME_COMPAT "compat"
@ -59,6 +63,9 @@ static void usage(void)
printf(" -b, --behavior=BEHAVIOR the release behavior to use (" printf(" -b, --behavior=BEHAVIOR the release behavior to use ("
BEHAVIOR_NAME_NONE " or " BEHAVIOR_NAME_NONE " or "
BEHAVIOR_NAME_FLUSH ")\n"); BEHAVIOR_NAME_FLUSH ")\n");
printf(" -c, --context-api=API the context creation API to use ("
API_NAME_NATIVE " or "
API_NAME_EGL ")\n");
printf(" -d, --debug request a debug context\n"); printf(" -d, --debug request a debug context\n");
printf(" -f, --forward require a forward-compatible context\n"); printf(" -f, --forward require a forward-compatible context\n");
printf(" -h, --help show this help\n"); printf(" -h, --help show this help\n");
@ -164,15 +171,15 @@ static const char* get_strategy_name_glfw(int strategy)
return "unknown"; return "unknown";
} }
static void list_context_extensions(int api, int major, int minor) static void list_context_extensions(int client, int major, int minor)
{ {
int i; int i;
GLint count; GLint count;
const GLubyte* extensions; const GLubyte* extensions;
printf("%s context extensions:\n", get_api_name(api)); printf("%s context extensions:\n", get_api_name(client));
if (api == GLFW_OPENGL_API && major > 2) if (client == GLFW_OPENGL_API && major > 2)
{ {
glGetIntegerv(GL_NUM_EXTENSIONS, &count); glGetIntegerv(GL_NUM_EXTENSIONS, &count);
@ -350,12 +357,13 @@ static void print_version(void)
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
int ch, api, major, minor, revision, profile; int ch, client, context, major, minor, revision, profile;
GLint redbits, greenbits, bluebits, alphabits, depthbits, stencilbits; GLint redbits, greenbits, bluebits, alphabits, depthbits, stencilbits;
int list_extensions = GLFW_FALSE, list_layers = GLFW_FALSE; int list_extensions = GLFW_FALSE, list_layers = GLFW_FALSE;
GLenum error;
GLFWwindow* window; GLFWwindow* window;
enum { API, BEHAVIOR, DEBUG, FORWARD, HELP, EXTENSIONS, LAYERS, enum { CLIENT, CONTEXT, BEHAVIOR, DEBUG, FORWARD, HELP, EXTENSIONS, LAYERS,
MAJOR, MINOR, PROFILE, ROBUSTNESS, VERSION, MAJOR, MINOR, PROFILE, ROBUSTNESS, VERSION,
REDBITS, GREENBITS, BLUEBITS, ALPHABITS, DEPTHBITS, STENCILBITS, REDBITS, GREENBITS, BLUEBITS, ALPHABITS, DEPTHBITS, STENCILBITS,
ACCUMREDBITS, ACCUMGREENBITS, ACCUMBLUEBITS, ACCUMALPHABITS, ACCUMREDBITS, ACCUMGREENBITS, ACCUMBLUEBITS, ACCUMALPHABITS,
@ -363,7 +371,8 @@ int main(int argc, char** argv)
const struct option options[] = const struct option options[] =
{ {
{ "behavior", 1, NULL, BEHAVIOR }, { "behavior", 1, NULL, BEHAVIOR },
{ "client-api", 1, NULL, API }, { "client-api", 1, NULL, CLIENT },
{ "context-api", 1, NULL, CONTEXT },
{ "debug", 0, NULL, DEBUG }, { "debug", 0, NULL, DEBUG },
{ "forward", 0, NULL, FORWARD }, { "forward", 0, NULL, FORWARD },
{ "help", 0, NULL, HELP }, { "help", 0, NULL, HELP },
@ -408,7 +417,7 @@ int main(int argc, char** argv)
switch (ch) switch (ch)
{ {
case 'a': case 'a':
case API: case CLIENT:
if (strcasecmp(optarg, API_NAME_OPENGL) == 0) if (strcasecmp(optarg, API_NAME_OPENGL) == 0)
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
else if (strcasecmp(optarg, API_NAME_OPENGL_ES) == 0) else if (strcasecmp(optarg, API_NAME_OPENGL_ES) == 0)
@ -437,6 +446,18 @@ int main(int argc, char** argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
break; break;
case 'c':
case CONTEXT:
if (strcasecmp(optarg, API_NAME_NATIVE) == 0)
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API);
else if (strcasecmp(optarg, API_NAME_EGL) == 0)
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
else
{
usage();
exit(EXIT_FAILURE);
}
break;
case 'd': case 'd':
case DEBUG: case DEBUG:
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
@ -608,32 +629,37 @@ int main(int argc, char** argv)
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
error = glGetError();
if (error != GL_NO_ERROR)
printf("*** OpenGL error after make current: 0x%08x ***\n", error);
// Report client API version // Report client API version
api = glfwGetWindowAttrib(window, GLFW_CLIENT_API); client = glfwGetWindowAttrib(window, GLFW_CLIENT_API);
context = glfwGetWindowAttrib(window, GLFW_CONTEXT_CREATION_API);
major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR); major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR); minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
revision = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION); revision = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION);
profile = glfwGetWindowAttrib(window, GLFW_OPENGL_PROFILE); profile = glfwGetWindowAttrib(window, GLFW_OPENGL_PROFILE);
printf("%s context version string: \"%s\"\n", printf("%s context version string: \"%s\"\n",
get_api_name(api), get_api_name(client),
glGetString(GL_VERSION)); glGetString(GL_VERSION));
printf("%s context version parsed by GLFW: %u.%u.%u\n", printf("%s context version parsed by GLFW: %u.%u.%u\n",
get_api_name(api), get_api_name(client),
major, minor, revision); major, minor, revision);
// Report client API context properties // Report client API context properties
if (api == GLFW_OPENGL_API) if (client == GLFW_OPENGL_API)
{ {
if (major >= 3) if (major >= 3)
{ {
GLint flags; GLint flags;
glGetIntegerv(GL_CONTEXT_FLAGS, &flags); glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
printf("%s context flags (0x%08x):", get_api_name(api), flags); printf("%s context flags (0x%08x):", get_api_name(client), flags);
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
printf(" forward-compatible"); printf(" forward-compatible");
@ -645,7 +671,7 @@ int main(int argc, char** argv)
printf(" no-error"); printf(" no-error");
putchar('\n'); putchar('\n');
printf("%s context flags parsed by GLFW:", get_api_name(api)); printf("%s context flags parsed by GLFW:", get_api_name(client));
if (glfwGetWindowAttrib(window, GLFW_OPENGL_FORWARD_COMPAT)) if (glfwGetWindowAttrib(window, GLFW_OPENGL_FORWARD_COMPAT))
printf(" forward-compatible"); printf(" forward-compatible");
@ -664,12 +690,12 @@ int main(int argc, char** argv)
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask); glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
printf("%s profile mask (0x%08x): %s\n", printf("%s profile mask (0x%08x): %s\n",
get_api_name(api), get_api_name(client),
mask, mask,
get_profile_name_gl(mask)); get_profile_name_gl(mask));
printf("%s profile mask parsed by GLFW: %s\n", printf("%s profile mask parsed by GLFW: %s\n",
get_api_name(api), get_api_name(client),
get_profile_name_glfw(profile)); get_profile_name_glfw(profile));
} }
@ -680,33 +706,33 @@ int main(int argc, char** argv)
glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy); glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
printf("%s robustness strategy (0x%08x): %s\n", printf("%s robustness strategy (0x%08x): %s\n",
get_api_name(api), get_api_name(client),
strategy, strategy,
get_strategy_name_gl(strategy)); get_strategy_name_gl(strategy));
printf("%s robustness strategy parsed by GLFW: %s\n", printf("%s robustness strategy parsed by GLFW: %s\n",
get_api_name(api), get_api_name(client),
get_strategy_name_glfw(robustness)); get_strategy_name_glfw(robustness));
} }
} }
printf("%s context renderer string: \"%s\"\n", printf("%s context renderer string: \"%s\"\n",
get_api_name(api), get_api_name(client),
glGetString(GL_RENDERER)); glGetString(GL_RENDERER));
printf("%s context vendor string: \"%s\"\n", printf("%s context vendor string: \"%s\"\n",
get_api_name(api), get_api_name(client),
glGetString(GL_VENDOR)); glGetString(GL_VENDOR));
if (major >= 2) if (major >= 2)
{ {
printf("%s context shading language version: \"%s\"\n", printf("%s context shading language version: \"%s\"\n",
get_api_name(api), get_api_name(client),
glGetString(GL_SHADING_LANGUAGE_VERSION)); glGetString(GL_SHADING_LANGUAGE_VERSION));
} }
printf("%s framebuffer:\n", get_api_name(api)); printf("%s framebuffer:\n", get_api_name(client));
if (api == GLFW_OPENGL_API && profile == GLFW_OPENGL_CORE_PROFILE) if (client == GLFW_OPENGL_API && profile == GLFW_OPENGL_CORE_PROFILE)
{ {
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT, GL_BACK_LEFT,
@ -746,7 +772,7 @@ int main(int argc, char** argv)
printf(" red: %u green: %u blue: %u alpha: %u depth: %u stencil: %u\n", printf(" red: %u green: %u blue: %u alpha: %u depth: %u stencil: %u\n",
redbits, greenbits, bluebits, alphabits, depthbits, stencilbits); redbits, greenbits, bluebits, alphabits, depthbits, stencilbits);
if (api == GLFW_OPENGL_ES_API || if (client == GLFW_OPENGL_ES_API ||
glfwExtensionSupported("GL_ARB_multisample") || glfwExtensionSupported("GL_ARB_multisample") ||
major > 1 || minor >= 3) major > 1 || minor >= 3)
{ {
@ -757,7 +783,7 @@ int main(int argc, char** argv)
printf(" samples: %u sample buffers: %u\n", samples, samplebuffers); printf(" samples: %u sample buffers: %u\n", samples, samplebuffers);
} }
if (api == GLFW_OPENGL_API && profile != GLFW_OPENGL_CORE_PROFILE) if (client == GLFW_OPENGL_API && profile != GLFW_OPENGL_CORE_PROFILE)
{ {
GLint accumredbits, accumgreenbits, accumbluebits, accumalphabits; GLint accumredbits, accumgreenbits, accumbluebits, accumalphabits;
GLint auxbuffers; GLint auxbuffers;
@ -773,7 +799,7 @@ int main(int argc, char** argv)
} }
if (list_extensions) if (list_extensions)
list_context_extensions(api, major, minor); list_context_extensions(client, major, minor);
printf("Vulkan loader: %s\n", printf("Vulkan loader: %s\n",
glfwVulkanSupported() ? "available" : "missing"); glfwVulkanSupported() ? "available" : "missing");
@ -792,7 +818,7 @@ int main(int argc, char** argv)
PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
re = glfwGetRequiredInstanceExtensions((int*) &re_count); re = glfwGetRequiredInstanceExtensions(&re_count);
printf("Vulkan required instance extensions:"); printf("Vulkan required instance extensions:");
for (i = 0; i < re_count; i++) for (i = 0; i < re_count; i++)
@ -800,9 +826,7 @@ int main(int argc, char** argv)
putchar('\n'); putchar('\n');
if (list_extensions) if (list_extensions)
{
list_vulkan_instance_extensions(); list_vulkan_instance_extensions();
}
if (list_layers) if (list_layers)
list_vulkan_instance_layers(); list_vulkan_instance_layers();
@ -812,7 +836,7 @@ int main(int argc, char** argv)
ai.applicationVersion = GLFW_VERSION_MAJOR; ai.applicationVersion = GLFW_VERSION_MAJOR;
ai.pEngineName = "GLFW"; ai.pEngineName = "GLFW";
ai.engineVersion = GLFW_VERSION_MAJOR; ai.engineVersion = GLFW_VERSION_MAJOR;
ai.apiVersion = VK_API_VERSION; ai.apiVersion = VK_API_VERSION_1_0;
ici.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; ici.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
ici.pApplicationInfo = &ai; ici.pApplicationInfo = &ai;

148
tests/icon.c Normal file
View File

@ -0,0 +1,148 @@
//========================================================================
// Window icon test program
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.org>
//
// 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 icon feature.
//
//========================================================================
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// a simple glfw logo
const char* const logo[] =
{
"................",
"................",
"...0000..0......",
"...0.....0......",
"...0.00..0......",
"...0..0..0......",
"...0000..0000...",
"................",
"................",
"...000..0...0...",
"...0....0...0...",
"...000..0.0.0...",
"...0....0.0.0...",
"...0....00000...",
"................",
"................"
};
const unsigned char icon_colors[5][4] =
{
{ 0, 0, 0, 255 }, // black
{ 255, 0, 0, 255 }, // red
{ 0, 255, 0, 255 }, // green
{ 0, 0, 255, 255 }, // blue
{ 255, 255, 255, 255 } // white
};
static int cur_icon_color = 0;
static void set_icon(GLFWwindow* window, int icon_color)
{
int x, y;
unsigned char pixels[16 * 16 * 4];
unsigned char* target = pixels;
GLFWimage img = { 16, 16, pixels };
for (y = 0; y < img.width; y++)
{
for (x = 0; x < img.height; x++)
{
if (logo[y][x] == '0')
memcpy(target, icon_colors[icon_color], 4);
else
memset(target, 0, 4);
target += 4;
}
}
glfwSetWindowIcon(window, 1, &img);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
case GLFW_KEY_SPACE:
cur_icon_color = (cur_icon_color + 1) % 5;
set_icon(window, cur_icon_color);
break;
case GLFW_KEY_X:
glfwSetWindowIcon(window, 0, NULL);
break;
}
}
int main(int argc, char** argv)
{
GLFWwindow* window;
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
exit(EXIT_FAILURE);
}
window = glfwCreateWindow(200, 200, "Window Icon", NULL, NULL);
if (!window)
{
glfwTerminate();
fprintf(stderr, "Failed to open GLFW window\n");
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSetKeyCallback(window, key_callback);
set_icon(window, cur_icon_color);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -36,6 +36,8 @@
#include "getopt.h" #include "getopt.h"
static int windowed_xpos, windowed_ypos, windowed_width, windowed_height;
static void usage(void) static void usage(void)
{ {
printf("Usage: iconify [-h] [-f [-a] [-n]]\n"); printf("Usage: iconify [-h] [-f [-a] [-n]]\n");
@ -62,12 +64,47 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
switch (key) switch (key)
{ {
case GLFW_KEY_SPACE: case GLFW_KEY_I:
glfwIconifyWindow(window); glfwIconifyWindow(window);
break; break;
case GLFW_KEY_M:
glfwMaximizeWindow(window);
break;
case GLFW_KEY_R:
glfwRestoreWindow(window);
break;
case GLFW_KEY_ESCAPE: case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE); glfwSetWindowShouldClose(window, GLFW_TRUE);
break; break;
case GLFW_KEY_F11:
case GLFW_KEY_ENTER:
{
if (mods != GLFW_MOD_ALT)
return;
if (glfwGetWindowMonitor(window))
{
glfwSetWindowMonitor(window, NULL,
windowed_xpos, windowed_ypos,
windowed_width, windowed_height,
0);
}
else
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
if (monitor)
{
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwGetWindowPos(window, &windowed_xpos, &windowed_ypos);
glfwGetWindowSize(window, &windowed_width, &windowed_height);
glfwSetWindowMonitor(window, monitor,
0, 0, mode->width, mode->height,
mode->refreshRate);
}
}
break;
}
} }
} }
@ -240,7 +277,7 @@ int main(int argc, char** argv)
for (;;) for (;;)
{ {
glfwPollEvents(); glfwWaitEvents();
for (i = 0; i < window_count; i++) for (i = 0; i < window_count; i++)
{ {

View File

@ -39,17 +39,7 @@
#define strdup(x) _strdup(x) #define strdup(x) _strdup(x)
#endif #endif
typedef struct Joystick static int joysticks[GLFW_JOYSTICK_LAST + 1];
{
int present;
char* name;
float* axes;
unsigned char* buttons;
int axis_count;
int button_count;
} Joystick;
static Joystick joysticks[GLFW_JOYSTICK_LAST - GLFW_JOYSTICK_1 + 1];
static int joystick_count = 0; static int joystick_count = 0;
static void error_callback(int error, const char* description) static void error_callback(int error, const char* description)
@ -62,19 +52,23 @@ static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
} }
static void draw_joystick(Joystick* j, int x, int y, int width, int height) static void draw_joystick(int index, int x, int y, int width, int height)
{ {
int i; int i;
int axis_count, button_count;
const float* axes;
const unsigned char* buttons;
const int axis_height = 3 * height / 4; const int axis_height = 3 * height / 4;
const int button_height = height / 4; const int button_height = height / 4;
if (j->axis_count) axes = glfwGetJoystickAxes(joysticks[index], &axis_count);
if (axis_count)
{ {
const int axis_width = width / j->axis_count; const int axis_width = width / axis_count;
for (i = 0; i < j->axis_count; i++) for (i = 0; i < axis_count; i++)
{ {
float value = j->axes[i] / 2.f + 0.5f; float value = axes[i] / 2.f + 0.5f;
glColor3f(0.3f, 0.3f, 0.3f); glColor3f(0.3f, 0.3f, 0.3f);
glRecti(x + i * axis_width, glRecti(x + i * axis_width,
@ -90,13 +84,14 @@ static void draw_joystick(Joystick* j, int x, int y, int width, int height)
} }
} }
if (j->button_count) buttons = glfwGetJoystickButtons(joysticks[index], &button_count);
if (button_count)
{ {
const int button_width = width / j->button_count; const int button_width = width / button_count;
for (i = 0; i < j->button_count; i++) for (i = 0; i < button_count; i++)
{ {
if (j->buttons[i]) if (buttons[i])
glColor3f(1.f, 1.f, 1.f); glColor3f(1.f, 1.f, 1.f);
else else
glColor3f(0.3f, 0.3f, 0.3f); glColor3f(0.3f, 0.3f, 0.3f);
@ -120,79 +115,58 @@ static void draw_joysticks(GLFWwindow* window)
glOrtho(0.f, width, height, 0.f, 1.f, -1.f); glOrtho(0.f, width, height, 0.f, 1.f, -1.f);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
for (i = 0; i < sizeof(joysticks) / sizeof(Joystick); i++) for (i = 0; i < joystick_count; i++)
{ {
Joystick* j = joysticks + i; draw_joystick(i,
0, offset * height / joystick_count,
if (j->present) width, height / joystick_count);
{ offset++;
draw_joystick(j,
0, offset * height / joystick_count,
width, height / joystick_count);
offset++;
}
} }
} }
static void refresh_joysticks(void) static void joystick_callback(int joy, int event)
{ {
int i; if (event == GLFW_CONNECTED)
for (i = 0; i < sizeof(joysticks) / sizeof(Joystick); i++)
{ {
Joystick* j = joysticks + i; int axis_count, button_count;
if (glfwJoystickPresent(GLFW_JOYSTICK_1 + i)) glfwGetJoystickAxes(joy, &axis_count);
glfwGetJoystickButtons(joy, &button_count);
printf("Found joystick %i named \'%s\' with %i axes, %i buttons\n",
joy + 1,
glfwGetJoystickName(joy),
axis_count,
button_count);
joysticks[joystick_count++] = joy;
}
else if (event == GLFW_DISCONNECTED)
{
int i;
for (i = 0; i < joystick_count; i++)
{ {
const float* axes; if (joysticks[i] == joy)
const unsigned char* buttons; break;
int axis_count, button_count;
free(j->name);
j->name = strdup(glfwGetJoystickName(GLFW_JOYSTICK_1 + i));
axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1 + i, &axis_count);
if (axis_count != j->axis_count)
{
j->axis_count = axis_count;
j->axes = realloc(j->axes, j->axis_count * sizeof(float));
}
memcpy(j->axes, axes, axis_count * sizeof(float));
buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1 + i, &button_count);
if (button_count != j->button_count)
{
j->button_count = button_count;
j->buttons = realloc(j->buttons, j->button_count);
}
memcpy(j->buttons, buttons, button_count * sizeof(unsigned char));
if (!j->present)
{
printf("Found joystick %i named \'%s\' with %i axes, %i buttons\n",
i + 1, j->name, j->axis_count, j->button_count);
joystick_count++;
}
j->present = GLFW_TRUE;
} }
else
{
if (j->present)
{
printf("Lost joystick %i named \'%s\'\n", i + 1, j->name);
free(j->name); for (i = i + 1; i < joystick_count; i++)
free(j->axes); joysticks[i - 1] = joysticks[i];
free(j->buttons);
memset(j, 0, sizeof(Joystick));
joystick_count--; printf("Lost joystick %i\n", joy + 1);
} joystick_count--;
} }
}
static void find_joysticks(void)
{
int joy;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
if (glfwJoystickPresent(joy))
joystick_callback(joy, GLFW_CONNECTED);
} }
} }
@ -207,6 +181,9 @@ int main(void)
if (!glfwInit()) if (!glfwInit())
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
find_joysticks();
glfwSetJoystickCallback(joystick_callback);
window = glfwCreateWindow(640, 480, "Joystick Test", NULL, NULL); window = glfwCreateWindow(640, 480, "Joystick Test", NULL, NULL);
if (!window) if (!window)
{ {
@ -224,11 +201,13 @@ int main(void)
{ {
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
refresh_joysticks();
draw_joysticks(window); draw_joysticks(window);
glfwSwapBuffers(window); glfwSwapBuffers(window);
glfwPollEvents(); glfwPollEvents();
// Workaround for an issue with msvcrt and mintty
fflush(stdout);
} }
glfwTerminate(); glfwTerminate();

97
tests/timeout.c Normal file
View File

@ -0,0 +1,97 @@
//========================================================================
// Event wait timeout test
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.org>
//
// 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 is intended to verify that waiting for events with timeout works
//
//========================================================================
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <time.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
static float nrand(void)
{
return (float) rand() / (float) RAND_MAX;
}
int main(void)
{
GLFWwindow* window;
srand((unsigned int) time(NULL));
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(640, 480, "Event Wait Timeout Test", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSetKeyCallback(window, key_callback);
while (!glfwWindowShouldClose(window))
{
int width, height;
float r = nrand(), g = nrand(), b = nrand();
float l = (float) sqrt(r * r + g * g + b * b);
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClearColor(r / l, g / l, b / l, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEventsTimeout(1.0);
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1732,7 +1732,7 @@ static void demo_init_vk(struct demo *demo) {
} }
/* Look for instance extensions */ /* Look for instance extensions */
required_extensions = glfwGetRequiredInstanceExtensions((int*) &required_extension_count); required_extensions = glfwGetRequiredInstanceExtensions(&required_extension_count);
if (!required_extensions) { if (!required_extensions) {
ERR_EXIT("glfwGetRequiredInstanceExtensions failed to find the " ERR_EXIT("glfwGetRequiredInstanceExtensions failed to find the "
"platform surface extensions.\n\nDo you have a compatible " "platform surface extensions.\n\nDo you have a compatible "
@ -1778,7 +1778,7 @@ static void demo_init_vk(struct demo *demo) {
.applicationVersion = 0, .applicationVersion = 0,
.pEngineName = APP_SHORT_NAME, .pEngineName = APP_SHORT_NAME,
.engineVersion = 0, .engineVersion = 0,
.apiVersion = VK_API_VERSION, .apiVersion = VK_API_VERSION_1_0,
}; };
VkInstanceCreateInfo inst_info = { VkInstanceCreateInfo inst_info = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
@ -2106,8 +2106,7 @@ static void demo_init_connection(struct demo *demo) {
} }
if (!glfwVulkanSupported()) { if (!glfwVulkanSupported()) {
printf("Cannot find a compatible Vulkan installable client driver " printf("GLFW failed to find the Vulkan loader.\nExiting ...\n");
"(ICD).\nExiting ...\n");
fflush(stdout); fflush(stdout);
exit(1); exit(1);
} }

View File

@ -33,6 +33,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "getopt.h"
static const char* titles[] = static const char* titles[] =
{ {
"Red", "Red",
@ -52,6 +54,14 @@ static const struct
{ 0.98f, 0.74f, 0.04f } { 0.98f, 0.74f, 0.04f }
}; };
static void usage(void)
{
printf("Usage: windows [-h] [-b]\n");
printf("Options:\n");
printf(" -b create decorated windows\n");
printf(" -h show this help\n");
}
static void error_callback(int error, const char* description) static void error_callback(int error, const char* description)
{ {
fprintf(stderr, "Error: %s\n", description); fprintf(stderr, "Error: %s\n", description);
@ -80,16 +90,33 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
int i; int i, ch;
int decorated = GLFW_FALSE;
int running = GLFW_TRUE; int running = GLFW_TRUE;
GLFWwindow* windows[4]; GLFWwindow* windows[4];
while ((ch = getopt(argc, argv, "bh")) != -1)
{
switch (ch)
{
case 'b':
decorated = GLFW_TRUE;
break;
case 'h':
usage();
exit(EXIT_SUCCESS);
default:
usage();
exit(EXIT_FAILURE);
}
}
glfwSetErrorCallback(error_callback); glfwSetErrorCallback(error_callback);
if (!glfwInit()) if (!glfwInit())
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); glfwWindowHint(GLFW_DECORATED, decorated);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
@ -130,7 +157,7 @@ int main(int argc, char** argv)
running = GLFW_FALSE; running = GLFW_FALSE;
} }
glfwPollEvents(); glfwWaitEvents();
} }
glfwTerminate(); glfwTerminate();