mirror of
https://github.com/glfw/glfw.git
synced 2025-04-20 23:52:51 +00:00
Merge branch 'master' of https://github.com/glfw/glfw
Resolved .gitignore conflict
This commit is contained in:
commit
4fba735d5e
@ -7,11 +7,6 @@ branches:
|
|||||||
- master
|
- master
|
||||||
- 3.3-stable
|
- 3.3-stable
|
||||||
skip_tags: true
|
skip_tags: true
|
||||||
skip_commits:
|
|
||||||
files:
|
|
||||||
- README.md
|
|
||||||
- LICENSE.md
|
|
||||||
- docs/*
|
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- GENERATOR: MinGW Makefiles
|
- GENERATOR: MinGW Makefiles
|
||||||
|
19
.gitignore
vendored
19
.gitignore
vendored
@ -7,18 +7,24 @@ _ReSharper*
|
|||||||
*.dir
|
*.dir
|
||||||
*.vcxproj*
|
*.vcxproj*
|
||||||
*.sln
|
*.sln
|
||||||
.vs/
|
.vs
|
||||||
|
CMakeSettings.json
|
||||||
Win32
|
Win32
|
||||||
x64
|
x64
|
||||||
Debug
|
Debug
|
||||||
Release
|
Release
|
||||||
MinSizeRel
|
MinSizeRel
|
||||||
RelWithDebInfo
|
RelWithDebInfo
|
||||||
*.xcodeproj
|
*.opensdf
|
||||||
bin
|
|
||||||
bin-int
|
|
||||||
|
|
||||||
# CMake files
|
# Xcode clutter
|
||||||
|
GLFW.build
|
||||||
|
GLFW.xcodeproj
|
||||||
|
|
||||||
|
# macOS clutter
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Makefile generator clutter
|
||||||
Makefile
|
Makefile
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
CMakeFiles
|
CMakeFiles
|
||||||
@ -85,3 +91,6 @@ tests/title
|
|||||||
tests/triangle-vulkan
|
tests/triangle-vulkan
|
||||||
tests/windows
|
tests/windows
|
||||||
|
|
||||||
|
# Hazel-specific
|
||||||
|
bin
|
||||||
|
bin-int
|
||||||
|
@ -75,12 +75,14 @@ matrix:
|
|||||||
env:
|
env:
|
||||||
- BUILD_SHARED_LIBS=ON
|
- BUILD_SHARED_LIBS=ON
|
||||||
- CFLAGS=-Werror
|
- CFLAGS=-Werror
|
||||||
|
- MACOSX_DEPLOYMENT_TARGET=10.8
|
||||||
- os: osx
|
- os: osx
|
||||||
sudo: false
|
sudo: false
|
||||||
name: "Cocoa static library"
|
name: "Cocoa static library"
|
||||||
env:
|
env:
|
||||||
- BUILD_SHARED_LIBS=OFF
|
- BUILD_SHARED_LIBS=OFF
|
||||||
- CFLAGS=-Werror
|
- CFLAGS=-Werror
|
||||||
|
- MACOSX_DEPLOYMENT_TARGET=10.8
|
||||||
script:
|
script:
|
||||||
- if grep -Inr '\s$' src include docs tests examples CMake *.md .gitattributes .gitignore; then
|
- if grep -Inr '\s$' src include docs tests examples CMake *.md .gitattributes .gitignore; then
|
||||||
echo Trailing whitespace found, aborting;
|
echo Trailing whitespace found, aborting;
|
||||||
|
3
CMake/glfw3Config.cmake.in
Normal file
3
CMake/glfw3Config.cmake.in
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
include(CMakeFindDependencyMacro)
|
||||||
|
find_dependency(Threads)
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/glfw3Targets.cmake")
|
@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.1)
|
||||||
|
|
||||||
project(GLFW VERSION 3.4.0 LANGUAGES C)
|
project(GLFW VERSION 3.4.0 LANGUAGES C)
|
||||||
|
|
||||||
@ -37,10 +37,6 @@ cmake_dependent_option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF
|
|||||||
cmake_dependent_option(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC runtime library DLL" ON
|
cmake_dependent_option(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC runtime library DLL" ON
|
||||||
"MSVC" OFF)
|
"MSVC" OFF)
|
||||||
|
|
||||||
if (BUILD_SHARED_LIBS)
|
|
||||||
set(_GLFW_BUILD_DLL 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (BUILD_SHARED_LIBS AND UNIX)
|
if (BUILD_SHARED_LIBS AND UNIX)
|
||||||
# On Unix-like systems, shared libraries can use the soname system.
|
# On Unix-like systems, shared libraries can use the soname system.
|
||||||
set(GLFW_LIB_NAME glfw)
|
set(GLFW_LIB_NAME glfw)
|
||||||
@ -75,7 +71,7 @@ if (MSVC)
|
|||||||
include(CheckIncludeFile)
|
include(CheckIncludeFile)
|
||||||
check_include_file(dinput.h DINPUT_H_FOUND)
|
check_include_file(dinput.h DINPUT_H_FOUND)
|
||||||
if (NOT DINPUT_H_FOUND)
|
if (NOT DINPUT_H_FOUND)
|
||||||
message(FATAL_ERROR "DirectX 9 SDK not found")
|
message(FATAL_ERROR "DirectX 9 headers not found; install DirectX 9 SDK")
|
||||||
endif()
|
endif()
|
||||||
# Workaround for VS 2008 not shipping with stdint.h
|
# Workaround for VS 2008 not shipping with stdint.h
|
||||||
list(APPEND glfw_INCLUDE_DIRS "${GLFW_SOURCE_DIR}/deps/vs2008")
|
list(APPEND glfw_INCLUDE_DIRS "${GLFW_SOURCE_DIR}/deps/vs2008")
|
||||||
@ -199,42 +195,33 @@ if (_GLFW_X11)
|
|||||||
|
|
||||||
find_package(X11 REQUIRED)
|
find_package(X11 REQUIRED)
|
||||||
|
|
||||||
list(APPEND glfw_PKG_DEPS "x11")
|
|
||||||
|
|
||||||
# Set up library and include paths
|
# Set up library and include paths
|
||||||
list(APPEND glfw_INCLUDE_DIRS "${X11_X11_INCLUDE_PATH}")
|
list(APPEND glfw_INCLUDE_DIRS "${X11_X11_INCLUDE_PATH}")
|
||||||
list(APPEND glfw_LIBRARIES "${X11_X11_LIB}" "${CMAKE_THREAD_LIBS_INIT}")
|
|
||||||
|
|
||||||
# Check for XRandR (modern resolution switching and gamma control)
|
# Check for XRandR (modern resolution switching and gamma control)
|
||||||
if (NOT X11_Xrandr_INCLUDE_PATH)
|
if (NOT X11_Xrandr_INCLUDE_PATH)
|
||||||
message(FATAL_ERROR "The RandR headers were not found")
|
message(FATAL_ERROR "RandR headers not found; install libxrandr development package")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Check for Xinerama (legacy multi-monitor support)
|
# Check for Xinerama (legacy multi-monitor support)
|
||||||
if (NOT X11_Xinerama_INCLUDE_PATH)
|
if (NOT X11_Xinerama_INCLUDE_PATH)
|
||||||
message(FATAL_ERROR "The Xinerama headers were not found")
|
message(FATAL_ERROR "Xinerama headers not found; install libxinerama development package")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Check for Xkb (X keyboard extension)
|
# Check for Xkb (X keyboard extension)
|
||||||
if (NOT X11_Xkb_INCLUDE_PATH)
|
if (NOT X11_Xkb_INCLUDE_PATH)
|
||||||
message(FATAL_ERROR "The X keyboard extension headers were not found")
|
message(FATAL_ERROR "XKB headers not found; install X11 development package")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Check for Xcursor (cursor creation from RGBA images)
|
# Check for Xcursor (cursor creation from RGBA images)
|
||||||
if (NOT X11_Xcursor_INCLUDE_PATH)
|
if (NOT X11_Xcursor_INCLUDE_PATH)
|
||||||
message(FATAL_ERROR "The Xcursor headers were not found")
|
message(FATAL_ERROR "Xcursor headers not found; install libxcursor development package")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Check for XInput (modern HID input)
|
# Check for XInput (modern HID input)
|
||||||
if (NOT X11_Xi_INCLUDE_PATH)
|
if (NOT X11_Xi_INCLUDE_PATH)
|
||||||
message(FATAL_ERROR "The XInput headers were not found")
|
message(FATAL_ERROR "XInput headers not found; install libxi development package")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND glfw_INCLUDE_DIRS "${X11_Xrandr_INCLUDE_PATH}"
|
|
||||||
"${X11_Xinerama_INCLUDE_PATH}"
|
|
||||||
"${X11_Xkb_INCLUDE_PATH}"
|
|
||||||
"${X11_Xcursor_INCLUDE_PATH}"
|
|
||||||
"${X11_Xi_INCLUDE_PATH}")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
@ -248,10 +235,10 @@ if (_GLFW_WAYLAND)
|
|||||||
find_package(WaylandScanner REQUIRED)
|
find_package(WaylandScanner REQUIRED)
|
||||||
find_package(WaylandProtocols 1.15 REQUIRED)
|
find_package(WaylandProtocols 1.15 REQUIRED)
|
||||||
|
|
||||||
list(APPEND glfw_PKG_DEPS "wayland-egl")
|
list(APPEND glfw_PKG_DEPS "wayland-client")
|
||||||
|
|
||||||
list(APPEND glfw_INCLUDE_DIRS "${Wayland_INCLUDE_DIRS}")
|
list(APPEND glfw_INCLUDE_DIRS "${Wayland_INCLUDE_DIRS}")
|
||||||
list(APPEND glfw_LIBRARIES "${Wayland_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
|
list(APPEND glfw_LIBRARIES "${Wayland_LIBRARIES}")
|
||||||
|
|
||||||
find_package(XKBCommon REQUIRED)
|
find_package(XKBCommon REQUIRED)
|
||||||
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
|
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
|
||||||
@ -275,7 +262,6 @@ endif()
|
|||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
if (_GLFW_OSMESA)
|
if (_GLFW_OSMESA)
|
||||||
find_package(OSMesa REQUIRED)
|
find_package(OSMesa REQUIRED)
|
||||||
list(APPEND glfw_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
@ -286,11 +272,10 @@ if (_GLFW_COCOA)
|
|||||||
list(APPEND glfw_LIBRARIES
|
list(APPEND glfw_LIBRARIES
|
||||||
"-framework Cocoa"
|
"-framework Cocoa"
|
||||||
"-framework IOKit"
|
"-framework IOKit"
|
||||||
"-framework CoreFoundation"
|
"-framework CoreFoundation")
|
||||||
"-framework CoreVideo")
|
|
||||||
|
|
||||||
set(glfw_PKG_DEPS "")
|
set(glfw_PKG_DEPS "")
|
||||||
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework CoreVideo")
|
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
@ -317,7 +302,7 @@ include(CMakePackageConfigHelpers)
|
|||||||
|
|
||||||
set(GLFW_CONFIG_PATH "${CMAKE_INSTALL_LIBDIR}/cmake/glfw3")
|
set(GLFW_CONFIG_PATH "${CMAKE_INSTALL_LIBDIR}/cmake/glfw3")
|
||||||
|
|
||||||
configure_package_config_file(src/glfw3Config.cmake.in
|
configure_package_config_file(CMake/glfw3Config.cmake.in
|
||||||
src/glfw3Config.cmake
|
src/glfw3Config.cmake
|
||||||
INSTALL_DESTINATION "${GLFW_CONFIG_PATH}"
|
INSTALL_DESTINATION "${GLFW_CONFIG_PATH}"
|
||||||
NO_CHECK_REQUIRED_COMPONENTS_MACRO)
|
NO_CHECK_REQUIRED_COMPONENTS_MACRO)
|
||||||
@ -326,9 +311,7 @@ write_basic_package_version_file(src/glfw3ConfigVersion.cmake
|
|||||||
VERSION ${GLFW_VERSION}
|
VERSION ${GLFW_VERSION}
|
||||||
COMPATIBILITY SameMajorVersion)
|
COMPATIBILITY SameMajorVersion)
|
||||||
|
|
||||||
configure_file(src/glfw_config.h.in src/glfw_config.h @ONLY)
|
configure_file(CMake/glfw3.pc.in src/glfw3.pc @ONLY)
|
||||||
|
|
||||||
configure_file(src/glfw3.pc.in src/glfw3.pc @ONLY)
|
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
# Add subdirectories
|
# Add subdirectories
|
||||||
@ -365,6 +348,11 @@ if (GLFW_INSTALL)
|
|||||||
install(FILES "${GLFW_BINARY_DIR}/src/glfw3.pc"
|
install(FILES "${GLFW_BINARY_DIR}/src/glfw3.pc"
|
||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||||
|
|
||||||
|
if (DOXYGEN_FOUND AND GLFW_BUILD_DOCS)
|
||||||
|
install(DIRECTORY "${GLFW_BINARY_DIR}/docs/html"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_DOCDIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Only generate this target if no higher-level project already has
|
# Only generate this target if no higher-level project already has
|
||||||
if (NOT TARGET uninstall)
|
if (NOT TARGET uninstall)
|
||||||
configure_file(CMake/cmake_uninstall.cmake.in
|
configure_file(CMake/cmake_uninstall.cmake.in
|
||||||
|
55
README.md
55
README.md
@ -11,7 +11,7 @@ application development. It provides a simple, platform-independent API for
|
|||||||
creating windows, contexts and surfaces, reading input, handling events, etc.
|
creating windows, contexts and surfaces, reading input, handling events, etc.
|
||||||
|
|
||||||
GLFW natively supports Windows, macOS and Linux and other Unix-like systems. On
|
GLFW natively supports Windows, macOS and Linux and other Unix-like systems. On
|
||||||
Linux both X11 and Wayland is supported.
|
Linux both X11 and Wayland are supported.
|
||||||
|
|
||||||
GLFW is licensed under the [zlib/libpng
|
GLFW is licensed under the [zlib/libpng
|
||||||
license](http://www.glfw.org/license.html).
|
license](http://www.glfw.org/license.html).
|
||||||
@ -85,10 +85,11 @@ in the documentation for more information.
|
|||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
GLFW itself depends only on the headers and libraries for your window system.
|
GLFW itself needs only CMake 3.1 or later and the headers and libraries for your
|
||||||
|
OS and window system.
|
||||||
|
|
||||||
The (experimental) Wayland backend also depends on the `extra-cmake-modules`
|
The (experimental) Wayland backend also depends on the `extra-cmake-modules`
|
||||||
package, which is used to generated Wayland protocol headers.
|
package, which is used to generate Wayland protocol headers.
|
||||||
|
|
||||||
The examples and test programs depend on a number of tiny libraries. These are
|
The examples and test programs depend on a number of tiny libraries. These are
|
||||||
located in the `deps/` directory.
|
located in the `deps/` directory.
|
||||||
@ -123,29 +124,70 @@ information on what to include when reporting a bug.
|
|||||||
- Added `GLFW_RESIZE_EW_CURSOR` alias for `GLFW_HRESIZE_CURSOR` (#427)
|
- Added `GLFW_RESIZE_EW_CURSOR` alias for `GLFW_HRESIZE_CURSOR` (#427)
|
||||||
- Added `GLFW_RESIZE_NS_CURSOR` alias for `GLFW_VRESIZE_CURSOR` (#427)
|
- Added `GLFW_RESIZE_NS_CURSOR` alias for `GLFW_VRESIZE_CURSOR` (#427)
|
||||||
- Added `GLFW_POINTING_HAND_CURSOR` alias for `GLFW_HAND_CURSOR` (#427)
|
- Added `GLFW_POINTING_HAND_CURSOR` alias for `GLFW_HAND_CURSOR` (#427)
|
||||||
|
- Updated the minimum required CMake version to 3.1
|
||||||
- Disabled tests and examples by default when built as a CMake subdirectory
|
- Disabled tests and examples by default when built as a CMake subdirectory
|
||||||
- Bugfix: The CMake config-file package used an absolute path and was not
|
- Bugfix: The CMake config-file package used an absolute path and was not
|
||||||
relocatable (#1470)
|
relocatable (#1470)
|
||||||
- Bugfix: Video modes with a duplicate screen area were discarded (#1555,#1556)
|
- Bugfix: Video modes with a duplicate screen area were discarded (#1555,#1556)
|
||||||
- Bugfix: Compiling with -Wextra-semi caused warnings (#1440)
|
- Bugfix: Compiling with -Wextra-semi caused warnings (#1440)
|
||||||
|
- Bugfix: Built-in mappings failed because some OEMs re-used VID/PID (#1583)
|
||||||
- [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access
|
- [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access
|
||||||
to the window menu
|
to the window menu
|
||||||
|
- [Win32] Added a version info resource to the GLFW DLL
|
||||||
- [Win32] Bugfix: `GLFW_INCLUDE_VULKAN` plus `VK_USE_PLATFORM_WIN32_KHR` caused
|
- [Win32] Bugfix: `GLFW_INCLUDE_VULKAN` plus `VK_USE_PLATFORM_WIN32_KHR` caused
|
||||||
symbol redefinition (#1524)
|
symbol redefinition (#1524)
|
||||||
- [Win32] Bugfix: The cursor position event was emitted before its cursor enter
|
- [Win32] Bugfix: The cursor position event was emitted before its cursor enter
|
||||||
event (#1490)
|
event (#1490)
|
||||||
- [Win32] Bugfix: The window hint `GLFW_MAXIMIZED` did not move or resize the
|
- [Win32] Bugfix: The window hint `GLFW_MAXIMIZED` did not move or resize the
|
||||||
window (#1499)
|
window (#1499)
|
||||||
|
- [Win32] Bugfix: Disabled cursor mode interfered with some non-client actions
|
||||||
|
- [Win32] Bugfix: Super key was not released after Win+V hotkey (#1622)
|
||||||
|
- [Win32] Bugfix: `glfwGetKeyName` could access out of bounds and return an
|
||||||
|
invalid pointer
|
||||||
|
- [Win32] Bugfix: Some synthetic key events were reported as `GLFW_KEY_UNKNOWN`
|
||||||
|
(#1623)
|
||||||
|
- [Cocoa] Added support for `VK_EXT_metal_surface` (#1619)
|
||||||
|
- [Cocoa] Added locating the Vulkan loader at runtime in an application bundle
|
||||||
|
- [Cocoa] Moved main menu creation to GLFW initialization time (#1649)
|
||||||
|
- [Cocoa] Removed dependency on the CoreVideo framework
|
||||||
- [Cocoa] Bugfix: `glfwSetWindowSize` used a bottom-left anchor point (#1553)
|
- [Cocoa] Bugfix: `glfwSetWindowSize` used a bottom-left anchor point (#1553)
|
||||||
- [Cocoa] Bugfix: Window remained on screen after destruction until event poll
|
- [Cocoa] Bugfix: Window remained on screen after destruction until event poll
|
||||||
(#1412)
|
(#1412)
|
||||||
|
- [Cocoa] Bugfix: Event processing before window creation would assert (#1543)
|
||||||
|
- [Cocoa] Bugfix: Undecorated windows could not be iconified on recent macOS
|
||||||
|
- [Cocoa] Bugfix: Touching event queue from secondary thread before main thread
|
||||||
|
would abort (#1649)
|
||||||
- [X11] Bugfix: The CMake files did not check for the XInput headers (#1480)
|
- [X11] Bugfix: The CMake files did not check for the XInput headers (#1480)
|
||||||
- [X11] Bugfix: Key names were not updated when the keyboard layout changed
|
- [X11] Bugfix: Key names were not updated when the keyboard layout changed
|
||||||
(#1462,#1528)
|
(#1462,#1528)
|
||||||
- [X11] Bugfix: Decorations could not be enabled after window creation (#1566)
|
- [X11] Bugfix: Decorations could not be enabled after window creation (#1566)
|
||||||
- [X11] Bugfix: Content scale fallback value could be inconsistent (#1578)
|
- [X11] Bugfix: Content scale fallback value could be inconsistent (#1578)
|
||||||
|
- [X11] Bugfix: `glfwMaximizeWindow` had no effect on hidden windows
|
||||||
|
- [X11] Bugfix: Clearing `GLFW_FLOATING` on a hidden window caused invalid read
|
||||||
|
- [X11] Bugfix: Changing `GLFW_FLOATING` on a hidden window could silently fail
|
||||||
|
- [X11] Bugfix: Disabled cursor mode was interrupted by indicator windows
|
||||||
|
- [X11] Bugfix: Monitor physical dimensions could be reported as zero mm
|
||||||
|
- [X11] Bugfix: Window position events were not emitted during resizing (#1613)
|
||||||
|
- [X11] Bugfix: `glfwFocusWindow` could terminate on older WMs or without a WM
|
||||||
|
- [X11] Bugfix: Querying a disconnected monitor could segfault (#1602)
|
||||||
|
- [X11] Bugfix: IME input of CJK was broken for "C" locale (#1587,#1636)
|
||||||
|
- [X11] Bugfix: Termination would segfault if the IM had been destroyed
|
||||||
|
- [X11] Bugfix: Any IM started after initialization would not be detected
|
||||||
|
- [X11] Bugfix: Xlib errors caused by other parts of the application could be
|
||||||
|
reported as GLFW errors
|
||||||
|
- [X11] Bugfix: A handle race condition could cause a `BadWindow` error (#1633)
|
||||||
|
- [X11] Bugfix: XKB path used keysyms instead of physical locations for
|
||||||
|
non-printable keys (#1598)
|
||||||
|
- [X11] Bugfix: Function keys were mapped to `GLFW_KEY_UNKNOWN` for some layout
|
||||||
|
combinaitons (#1598)
|
||||||
|
- [Wayland] Removed support for `wl_shell` (#1443)
|
||||||
- [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432)
|
- [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432)
|
||||||
|
- [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled
|
||||||
|
- [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled
|
||||||
- [NSGL] Removed enforcement of forward-compatible flag for core contexts
|
- [NSGL] Removed enforcement of forward-compatible flag for core contexts
|
||||||
|
- [NSGL] Bugfix: `GLFW_COCOA_RETINA_FRAMEBUFFER` had no effect on newer
|
||||||
|
macOS versions (#1442)
|
||||||
|
- [NSGL] Bugfix: Workaround for swap interval on 10.14 broke on 10.12 (#1483)
|
||||||
|
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
@ -218,6 +260,7 @@ skills.
|
|||||||
- GeO4d
|
- GeO4d
|
||||||
- Marcus Geelnard
|
- Marcus Geelnard
|
||||||
- Charles Giessen
|
- Charles Giessen
|
||||||
|
- Ryan C. Gordon
|
||||||
- Stephen Gowen
|
- Stephen Gowen
|
||||||
- Kovid Goyal
|
- Kovid Goyal
|
||||||
- Eloi Marín Gratacós
|
- Eloi Marín Gratacós
|
||||||
@ -238,6 +281,7 @@ skills.
|
|||||||
- Cem Karan
|
- Cem Karan
|
||||||
- Osman Keskin
|
- Osman Keskin
|
||||||
- Josh Kilmer
|
- Josh Kilmer
|
||||||
|
- Byunghoon Kim
|
||||||
- Cameron King
|
- Cameron King
|
||||||
- Peter Knut
|
- Peter Knut
|
||||||
- Christoph Kubisch
|
- Christoph Kubisch
|
||||||
@ -245,6 +289,7 @@ skills.
|
|||||||
- Rokas Kupstys
|
- Rokas Kupstys
|
||||||
- Konstantin Käfer
|
- Konstantin Käfer
|
||||||
- Eric Larson
|
- Eric Larson
|
||||||
|
- Francis Lecavalier
|
||||||
- Robin Leffmann
|
- Robin Leffmann
|
||||||
- Glenn Lewis
|
- Glenn Lewis
|
||||||
- Shane Liesegang
|
- Shane Liesegang
|
||||||
@ -253,6 +298,7 @@ skills.
|
|||||||
- Eyal Lotem
|
- Eyal Lotem
|
||||||
- Aaron Loucks
|
- Aaron Loucks
|
||||||
- Luflosi
|
- Luflosi
|
||||||
|
- lukect
|
||||||
- Tristam MacDonald
|
- Tristam MacDonald
|
||||||
- Hans Mackowiak
|
- Hans Mackowiak
|
||||||
- Дмитри Малышев
|
- Дмитри Малышев
|
||||||
@ -298,6 +344,7 @@ skills.
|
|||||||
- Alexandre Pretyman
|
- Alexandre Pretyman
|
||||||
- Pablo Prietz
|
- Pablo Prietz
|
||||||
- przemekmirek
|
- przemekmirek
|
||||||
|
- pthom
|
||||||
- Guillaume Racicot
|
- Guillaume Racicot
|
||||||
- Philip Rideout
|
- Philip Rideout
|
||||||
- Eddie Ringle
|
- Eddie Ringle
|
||||||
@ -312,6 +359,7 @@ skills.
|
|||||||
- Matt Sealey
|
- Matt Sealey
|
||||||
- Steve Sexton
|
- Steve Sexton
|
||||||
- Arkady Shapkin
|
- Arkady Shapkin
|
||||||
|
- Ali Sherief
|
||||||
- Yoshiki Shibukawa
|
- Yoshiki Shibukawa
|
||||||
- Dmitri Shuralyov
|
- Dmitri Shuralyov
|
||||||
- Daniel Skorupski
|
- Daniel Skorupski
|
||||||
@ -328,6 +376,7 @@ skills.
|
|||||||
- Paul Sultana
|
- Paul Sultana
|
||||||
- Nathan Sweet
|
- Nathan Sweet
|
||||||
- TTK-Bandit
|
- TTK-Bandit
|
||||||
|
- Jared Tiala
|
||||||
- Sergey Tikhomirov
|
- Sergey Tikhomirov
|
||||||
- Arthur Tombs
|
- Arthur Tombs
|
||||||
- Ioannis Tsakpinis
|
- Ioannis Tsakpinis
|
||||||
|
197
deps/linmath.h
vendored
197
deps/linmath.h
vendored
@ -3,31 +3,40 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
/* 2020-03-02 Camilla Löwy <elmindreda@elmindreda.org>
|
||||||
#define inline __inline
|
* - Added inclusion of string.h for memcpy
|
||||||
|
* - Replaced tan and acos with tanf and acosf
|
||||||
|
* - Replaced double constants with float equivalents
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef LINMATH_NO_INLINE
|
||||||
|
#define LINMATH_H_FUNC static
|
||||||
|
#else
|
||||||
|
#define LINMATH_H_FUNC static inline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LINMATH_H_DEFINE_VEC(n) \
|
#define LINMATH_H_DEFINE_VEC(n) \
|
||||||
typedef float vec##n[n]; \
|
typedef float vec##n[n]; \
|
||||||
static inline void vec##n##_add(vec##n r, vec##n const a, vec##n const b) \
|
LINMATH_H_FUNC void vec##n##_add(vec##n r, vec##n const a, vec##n const b) \
|
||||||
{ \
|
{ \
|
||||||
int i; \
|
int i; \
|
||||||
for(i=0; i<n; ++i) \
|
for(i=0; i<n; ++i) \
|
||||||
r[i] = a[i] + b[i]; \
|
r[i] = a[i] + b[i]; \
|
||||||
} \
|
} \
|
||||||
static inline void vec##n##_sub(vec##n r, vec##n const a, vec##n const b) \
|
LINMATH_H_FUNC void vec##n##_sub(vec##n r, vec##n const a, vec##n const b) \
|
||||||
{ \
|
{ \
|
||||||
int i; \
|
int i; \
|
||||||
for(i=0; i<n; ++i) \
|
for(i=0; i<n; ++i) \
|
||||||
r[i] = a[i] - b[i]; \
|
r[i] = a[i] - b[i]; \
|
||||||
} \
|
} \
|
||||||
static inline void vec##n##_scale(vec##n r, vec##n const v, float const s) \
|
LINMATH_H_FUNC void vec##n##_scale(vec##n r, vec##n const v, float const s) \
|
||||||
{ \
|
{ \
|
||||||
int i; \
|
int i; \
|
||||||
for(i=0; i<n; ++i) \
|
for(i=0; i<n; ++i) \
|
||||||
r[i] = v[i] * s; \
|
r[i] = v[i] * s; \
|
||||||
} \
|
} \
|
||||||
static inline float vec##n##_mul_inner(vec##n const a, vec##n const b) \
|
LINMATH_H_FUNC float vec##n##_mul_inner(vec##n const a, vec##n const b) \
|
||||||
{ \
|
{ \
|
||||||
float p = 0.; \
|
float p = 0.; \
|
||||||
int i; \
|
int i; \
|
||||||
@ -35,28 +44,40 @@ static inline float vec##n##_mul_inner(vec##n const a, vec##n const b) \
|
|||||||
p += b[i]*a[i]; \
|
p += b[i]*a[i]; \
|
||||||
return p; \
|
return p; \
|
||||||
} \
|
} \
|
||||||
static inline float vec##n##_len(vec##n const v) \
|
LINMATH_H_FUNC float vec##n##_len(vec##n const v) \
|
||||||
{ \
|
{ \
|
||||||
return (float) sqrt(vec##n##_mul_inner(v,v)); \
|
return sqrtf(vec##n##_mul_inner(v,v)); \
|
||||||
} \
|
} \
|
||||||
static inline void vec##n##_norm(vec##n r, vec##n const v) \
|
LINMATH_H_FUNC void vec##n##_norm(vec##n r, vec##n const v) \
|
||||||
{ \
|
{ \
|
||||||
float k = 1.f / vec##n##_len(v); \
|
float k = 1.f / vec##n##_len(v); \
|
||||||
vec##n##_scale(r, v, k); \
|
vec##n##_scale(r, v, k); \
|
||||||
|
} \
|
||||||
|
LINMATH_H_FUNC void vec##n##_min(vec##n r, vec##n const a, vec##n const b) \
|
||||||
|
{ \
|
||||||
|
int i; \
|
||||||
|
for(i=0; i<n; ++i) \
|
||||||
|
r[i] = a[i]<b[i] ? a[i] : b[i]; \
|
||||||
|
} \
|
||||||
|
LINMATH_H_FUNC void vec##n##_max(vec##n r, vec##n const a, vec##n const b) \
|
||||||
|
{ \
|
||||||
|
int i; \
|
||||||
|
for(i=0; i<n; ++i) \
|
||||||
|
r[i] = a[i]>b[i] ? a[i] : b[i]; \
|
||||||
}
|
}
|
||||||
|
|
||||||
LINMATH_H_DEFINE_VEC(2)
|
LINMATH_H_DEFINE_VEC(2)
|
||||||
LINMATH_H_DEFINE_VEC(3)
|
LINMATH_H_DEFINE_VEC(3)
|
||||||
LINMATH_H_DEFINE_VEC(4)
|
LINMATH_H_DEFINE_VEC(4)
|
||||||
|
|
||||||
static inline void vec3_mul_cross(vec3 r, vec3 const a, vec3 const b)
|
LINMATH_H_FUNC void vec3_mul_cross(vec3 r, vec3 const a, vec3 const b)
|
||||||
{
|
{
|
||||||
r[0] = a[1]*b[2] - a[2]*b[1];
|
r[0] = a[1]*b[2] - a[2]*b[1];
|
||||||
r[1] = a[2]*b[0] - a[0]*b[2];
|
r[1] = a[2]*b[0] - a[0]*b[2];
|
||||||
r[2] = a[0]*b[1] - a[1]*b[0];
|
r[2] = a[0]*b[1] - a[1]*b[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void vec3_reflect(vec3 r, vec3 const v, vec3 const n)
|
LINMATH_H_FUNC void vec3_reflect(vec3 r, vec3 const v, vec3 const n)
|
||||||
{
|
{
|
||||||
float p = 2.f*vec3_mul_inner(v, n);
|
float p = 2.f*vec3_mul_inner(v, n);
|
||||||
int i;
|
int i;
|
||||||
@ -64,7 +85,7 @@ static inline void vec3_reflect(vec3 r, vec3 const v, vec3 const n)
|
|||||||
r[i] = v[i] - p*n[i];
|
r[i] = v[i] - p*n[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void vec4_mul_cross(vec4 r, vec4 a, vec4 b)
|
LINMATH_H_FUNC void vec4_mul_cross(vec4 r, vec4 a, vec4 b)
|
||||||
{
|
{
|
||||||
r[0] = a[1]*b[2] - a[2]*b[1];
|
r[0] = a[1]*b[2] - a[2]*b[1];
|
||||||
r[1] = a[2]*b[0] - a[0]*b[2];
|
r[1] = a[2]*b[0] - a[0]*b[2];
|
||||||
@ -72,7 +93,7 @@ static inline void vec4_mul_cross(vec4 r, vec4 a, vec4 b)
|
|||||||
r[3] = 1.f;
|
r[3] = 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void vec4_reflect(vec4 r, vec4 v, vec4 n)
|
LINMATH_H_FUNC void vec4_reflect(vec4 r, vec4 v, vec4 n)
|
||||||
{
|
{
|
||||||
float p = 2.f*vec4_mul_inner(v, n);
|
float p = 2.f*vec4_mul_inner(v, n);
|
||||||
int i;
|
int i;
|
||||||
@ -81,58 +102,58 @@ static inline void vec4_reflect(vec4 r, vec4 v, vec4 n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef vec4 mat4x4[4];
|
typedef vec4 mat4x4[4];
|
||||||
static inline void mat4x4_identity(mat4x4 M)
|
LINMATH_H_FUNC void mat4x4_identity(mat4x4 M)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
for(i=0; i<4; ++i)
|
for(i=0; i<4; ++i)
|
||||||
for(j=0; j<4; ++j)
|
for(j=0; j<4; ++j)
|
||||||
M[i][j] = i==j ? 1.f : 0.f;
|
M[i][j] = i==j ? 1.f : 0.f;
|
||||||
}
|
}
|
||||||
static inline void mat4x4_dup(mat4x4 M, mat4x4 N)
|
LINMATH_H_FUNC void mat4x4_dup(mat4x4 M, mat4x4 N)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
for(i=0; i<4; ++i)
|
for(i=0; i<4; ++i)
|
||||||
for(j=0; j<4; ++j)
|
for(j=0; j<4; ++j)
|
||||||
M[i][j] = N[i][j];
|
M[i][j] = N[i][j];
|
||||||
}
|
}
|
||||||
static inline void mat4x4_row(vec4 r, mat4x4 M, int i)
|
LINMATH_H_FUNC void mat4x4_row(vec4 r, mat4x4 M, int i)
|
||||||
{
|
{
|
||||||
int k;
|
int k;
|
||||||
for(k=0; k<4; ++k)
|
for(k=0; k<4; ++k)
|
||||||
r[k] = M[k][i];
|
r[k] = M[k][i];
|
||||||
}
|
}
|
||||||
static inline void mat4x4_col(vec4 r, mat4x4 M, int i)
|
LINMATH_H_FUNC void mat4x4_col(vec4 r, mat4x4 M, int i)
|
||||||
{
|
{
|
||||||
int k;
|
int k;
|
||||||
for(k=0; k<4; ++k)
|
for(k=0; k<4; ++k)
|
||||||
r[k] = M[i][k];
|
r[k] = M[i][k];
|
||||||
}
|
}
|
||||||
static inline void mat4x4_transpose(mat4x4 M, mat4x4 N)
|
LINMATH_H_FUNC void mat4x4_transpose(mat4x4 M, mat4x4 N)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
for(j=0; j<4; ++j)
|
for(j=0; j<4; ++j)
|
||||||
for(i=0; i<4; ++i)
|
for(i=0; i<4; ++i)
|
||||||
M[i][j] = N[j][i];
|
M[i][j] = N[j][i];
|
||||||
}
|
}
|
||||||
static inline void mat4x4_add(mat4x4 M, mat4x4 a, mat4x4 b)
|
LINMATH_H_FUNC void mat4x4_add(mat4x4 M, mat4x4 a, mat4x4 b)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<4; ++i)
|
for(i=0; i<4; ++i)
|
||||||
vec4_add(M[i], a[i], b[i]);
|
vec4_add(M[i], a[i], b[i]);
|
||||||
}
|
}
|
||||||
static inline void mat4x4_sub(mat4x4 M, mat4x4 a, mat4x4 b)
|
LINMATH_H_FUNC void mat4x4_sub(mat4x4 M, mat4x4 a, mat4x4 b)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<4; ++i)
|
for(i=0; i<4; ++i)
|
||||||
vec4_sub(M[i], a[i], b[i]);
|
vec4_sub(M[i], a[i], b[i]);
|
||||||
}
|
}
|
||||||
static inline void mat4x4_scale(mat4x4 M, mat4x4 a, float k)
|
LINMATH_H_FUNC void mat4x4_scale(mat4x4 M, mat4x4 a, float k)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<4; ++i)
|
for(i=0; i<4; ++i)
|
||||||
vec4_scale(M[i], a[i], k);
|
vec4_scale(M[i], a[i], k);
|
||||||
}
|
}
|
||||||
static inline void mat4x4_scale_aniso(mat4x4 M, mat4x4 a, float x, float y, float z)
|
LINMATH_H_FUNC void mat4x4_scale_aniso(mat4x4 M, mat4x4 a, float x, float y, float z)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
vec4_scale(M[0], a[0], x);
|
vec4_scale(M[0], a[0], x);
|
||||||
@ -142,7 +163,7 @@ static inline void mat4x4_scale_aniso(mat4x4 M, mat4x4 a, float x, float y, floa
|
|||||||
M[3][i] = a[3][i];
|
M[3][i] = a[3][i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static inline void mat4x4_mul(mat4x4 M, mat4x4 a, mat4x4 b)
|
LINMATH_H_FUNC void mat4x4_mul(mat4x4 M, mat4x4 a, mat4x4 b)
|
||||||
{
|
{
|
||||||
mat4x4 temp;
|
mat4x4 temp;
|
||||||
int k, r, c;
|
int k, r, c;
|
||||||
@ -153,7 +174,7 @@ static inline void mat4x4_mul(mat4x4 M, mat4x4 a, mat4x4 b)
|
|||||||
}
|
}
|
||||||
mat4x4_dup(M, temp);
|
mat4x4_dup(M, temp);
|
||||||
}
|
}
|
||||||
static inline void mat4x4_mul_vec4(vec4 r, mat4x4 M, vec4 v)
|
LINMATH_H_FUNC void mat4x4_mul_vec4(vec4 r, mat4x4 M, vec4 v)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
for(j=0; j<4; ++j) {
|
for(j=0; j<4; ++j) {
|
||||||
@ -162,14 +183,14 @@ static inline void mat4x4_mul_vec4(vec4 r, mat4x4 M, vec4 v)
|
|||||||
r[j] += M[i][j] * v[i];
|
r[j] += M[i][j] * v[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static inline void mat4x4_translate(mat4x4 T, float x, float y, float z)
|
LINMATH_H_FUNC void mat4x4_translate(mat4x4 T, float x, float y, float z)
|
||||||
{
|
{
|
||||||
mat4x4_identity(T);
|
mat4x4_identity(T);
|
||||||
T[3][0] = x;
|
T[3][0] = x;
|
||||||
T[3][1] = y;
|
T[3][1] = y;
|
||||||
T[3][2] = z;
|
T[3][2] = z;
|
||||||
}
|
}
|
||||||
static inline void mat4x4_translate_in_place(mat4x4 M, float x, float y, float z)
|
LINMATH_H_FUNC void mat4x4_translate_in_place(mat4x4 M, float x, float y, float z)
|
||||||
{
|
{
|
||||||
vec4 t = {x, y, z, 0};
|
vec4 t = {x, y, z, 0};
|
||||||
vec4 r;
|
vec4 r;
|
||||||
@ -179,33 +200,32 @@ static inline void mat4x4_translate_in_place(mat4x4 M, float x, float y, float z
|
|||||||
M[3][i] += vec4_mul_inner(r, t);
|
M[3][i] += vec4_mul_inner(r, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static inline void mat4x4_from_vec3_mul_outer(mat4x4 M, vec3 a, vec3 b)
|
LINMATH_H_FUNC void mat4x4_from_vec3_mul_outer(mat4x4 M, vec3 a, vec3 b)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
for(i=0; i<4; ++i) for(j=0; j<4; ++j)
|
for(i=0; i<4; ++i) for(j=0; j<4; ++j)
|
||||||
M[i][j] = i<3 && j<3 ? a[i] * b[j] : 0.f;
|
M[i][j] = i<3 && j<3 ? a[i] * b[j] : 0.f;
|
||||||
}
|
}
|
||||||
static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z, float angle)
|
LINMATH_H_FUNC void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z, float angle)
|
||||||
{
|
{
|
||||||
float s = sinf(angle);
|
float s = sinf(angle);
|
||||||
float c = cosf(angle);
|
float c = cosf(angle);
|
||||||
vec3 u = {x, y, z};
|
vec3 u = {x, y, z};
|
||||||
|
|
||||||
if(vec3_len(u) > 1e-4) {
|
if(vec3_len(u) > 1e-4) {
|
||||||
mat4x4 T, C, S = {{0}};
|
|
||||||
|
|
||||||
vec3_norm(u, u);
|
vec3_norm(u, u);
|
||||||
|
mat4x4 T;
|
||||||
mat4x4_from_vec3_mul_outer(T, u, u);
|
mat4x4_from_vec3_mul_outer(T, u, u);
|
||||||
|
|
||||||
S[1][2] = u[0];
|
mat4x4 S = {
|
||||||
S[2][1] = -u[0];
|
{ 0, u[2], -u[1], 0},
|
||||||
S[2][0] = u[1];
|
{-u[2], 0, u[0], 0},
|
||||||
S[0][2] = -u[1];
|
{ u[1], -u[0], 0, 0},
|
||||||
S[0][1] = u[2];
|
{ 0, 0, 0, 0}
|
||||||
S[1][0] = -u[2];
|
};
|
||||||
|
|
||||||
mat4x4_scale(S, S, s);
|
mat4x4_scale(S, S, s);
|
||||||
|
|
||||||
|
mat4x4 C;
|
||||||
mat4x4_identity(C);
|
mat4x4_identity(C);
|
||||||
mat4x4_sub(C, C, T);
|
mat4x4_sub(C, C, T);
|
||||||
|
|
||||||
@ -220,7 +240,7 @@ static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z,
|
|||||||
mat4x4_dup(R, M);
|
mat4x4_dup(R, M);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static inline void mat4x4_rotate_X(mat4x4 Q, mat4x4 M, float angle)
|
LINMATH_H_FUNC void mat4x4_rotate_X(mat4x4 Q, mat4x4 M, float angle)
|
||||||
{
|
{
|
||||||
float s = sinf(angle);
|
float s = sinf(angle);
|
||||||
float c = cosf(angle);
|
float c = cosf(angle);
|
||||||
@ -232,7 +252,7 @@ static inline void mat4x4_rotate_X(mat4x4 Q, mat4x4 M, float angle)
|
|||||||
};
|
};
|
||||||
mat4x4_mul(Q, M, R);
|
mat4x4_mul(Q, M, R);
|
||||||
}
|
}
|
||||||
static inline void mat4x4_rotate_Y(mat4x4 Q, mat4x4 M, float angle)
|
LINMATH_H_FUNC void mat4x4_rotate_Y(mat4x4 Q, mat4x4 M, float angle)
|
||||||
{
|
{
|
||||||
float s = sinf(angle);
|
float s = sinf(angle);
|
||||||
float c = cosf(angle);
|
float c = cosf(angle);
|
||||||
@ -244,7 +264,7 @@ static inline void mat4x4_rotate_Y(mat4x4 Q, mat4x4 M, float angle)
|
|||||||
};
|
};
|
||||||
mat4x4_mul(Q, M, R);
|
mat4x4_mul(Q, M, R);
|
||||||
}
|
}
|
||||||
static inline void mat4x4_rotate_Z(mat4x4 Q, mat4x4 M, float angle)
|
LINMATH_H_FUNC void mat4x4_rotate_Z(mat4x4 Q, mat4x4 M, float angle)
|
||||||
{
|
{
|
||||||
float s = sinf(angle);
|
float s = sinf(angle);
|
||||||
float c = cosf(angle);
|
float c = cosf(angle);
|
||||||
@ -256,9 +276,8 @@ static inline void mat4x4_rotate_Z(mat4x4 Q, mat4x4 M, float angle)
|
|||||||
};
|
};
|
||||||
mat4x4_mul(Q, M, R);
|
mat4x4_mul(Q, M, R);
|
||||||
}
|
}
|
||||||
static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
|
LINMATH_H_FUNC void mat4x4_invert(mat4x4 T, mat4x4 M)
|
||||||
{
|
{
|
||||||
float idet;
|
|
||||||
float s[6];
|
float s[6];
|
||||||
float c[6];
|
float c[6];
|
||||||
s[0] = M[0][0]*M[1][1] - M[1][0]*M[0][1];
|
s[0] = M[0][0]*M[1][1] - M[1][0]*M[0][1];
|
||||||
@ -276,7 +295,7 @@ static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
|
|||||||
c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3];
|
c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3];
|
||||||
|
|
||||||
/* Assumes it is invertible */
|
/* Assumes it is invertible */
|
||||||
idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] );
|
float idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] );
|
||||||
|
|
||||||
T[0][0] = ( M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet;
|
T[0][0] = ( M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet;
|
||||||
T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet;
|
T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet;
|
||||||
@ -298,17 +317,12 @@ static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
|
|||||||
T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet;
|
T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet;
|
||||||
T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet;
|
T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet;
|
||||||
}
|
}
|
||||||
static inline void mat4x4_orthonormalize(mat4x4 R, mat4x4 M)
|
LINMATH_H_FUNC void mat4x4_orthonormalize(mat4x4 R, mat4x4 M)
|
||||||
{
|
{
|
||||||
|
mat4x4_dup(R, M);
|
||||||
float s = 1.;
|
float s = 1.;
|
||||||
vec3 h;
|
vec3 h;
|
||||||
|
|
||||||
mat4x4_dup(R, M);
|
|
||||||
vec3_norm(R[2], R[2]);
|
|
||||||
|
|
||||||
s = vec3_mul_inner(R[1], R[2]);
|
|
||||||
vec3_scale(h, R[2], s);
|
|
||||||
vec3_sub(R[1], R[1], h);
|
|
||||||
vec3_norm(R[2], R[2]);
|
vec3_norm(R[2], R[2]);
|
||||||
|
|
||||||
s = vec3_mul_inner(R[1], R[2]);
|
s = vec3_mul_inner(R[1], R[2]);
|
||||||
@ -316,13 +330,17 @@ static inline void mat4x4_orthonormalize(mat4x4 R, mat4x4 M)
|
|||||||
vec3_sub(R[1], R[1], h);
|
vec3_sub(R[1], R[1], h);
|
||||||
vec3_norm(R[1], R[1]);
|
vec3_norm(R[1], R[1]);
|
||||||
|
|
||||||
|
s = vec3_mul_inner(R[0], R[2]);
|
||||||
|
vec3_scale(h, R[2], s);
|
||||||
|
vec3_sub(R[0], R[0], h);
|
||||||
|
|
||||||
s = vec3_mul_inner(R[0], R[1]);
|
s = vec3_mul_inner(R[0], R[1]);
|
||||||
vec3_scale(h, R[1], s);
|
vec3_scale(h, R[1], s);
|
||||||
vec3_sub(R[0], R[0], h);
|
vec3_sub(R[0], R[0], h);
|
||||||
vec3_norm(R[0], R[0]);
|
vec3_norm(R[0], R[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t, float n, float f)
|
LINMATH_H_FUNC void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t, float n, float f)
|
||||||
{
|
{
|
||||||
M[0][0] = 2.f*n/(r-l);
|
M[0][0] = 2.f*n/(r-l);
|
||||||
M[0][1] = M[0][2] = M[0][3] = 0.f;
|
M[0][1] = M[0][2] = M[0][3] = 0.f;
|
||||||
@ -338,7 +356,7 @@ static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t,
|
|||||||
M[3][2] = -2.f*(f*n)/(f-n);
|
M[3][2] = -2.f*(f*n)/(f-n);
|
||||||
M[3][0] = M[3][1] = M[3][3] = 0.f;
|
M[3][0] = M[3][1] = M[3][3] = 0.f;
|
||||||
}
|
}
|
||||||
static inline void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, float n, float f)
|
LINMATH_H_FUNC void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, float n, float f)
|
||||||
{
|
{
|
||||||
M[0][0] = 2.f/(r-l);
|
M[0][0] = 2.f/(r-l);
|
||||||
M[0][1] = M[0][2] = M[0][3] = 0.f;
|
M[0][1] = M[0][2] = M[0][3] = 0.f;
|
||||||
@ -354,11 +372,11 @@ static inline void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, fl
|
|||||||
M[3][2] = -(f+n)/(f-n);
|
M[3][2] = -(f+n)/(f-n);
|
||||||
M[3][3] = 1.f;
|
M[3][3] = 1.f;
|
||||||
}
|
}
|
||||||
static inline void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float n, float f)
|
LINMATH_H_FUNC void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float n, float f)
|
||||||
{
|
{
|
||||||
/* NOTE: Degrees are an unhandy unit to work with.
|
/* NOTE: Degrees are an unhandy unit to work with.
|
||||||
* linmath.h uses radians for everything! */
|
* linmath.h uses radians for everything! */
|
||||||
float const a = 1.f / (float) tan(y_fov / 2.f);
|
float const a = 1.f / tanf(y_fov / 2.f);
|
||||||
|
|
||||||
m[0][0] = a / aspect;
|
m[0][0] = a / aspect;
|
||||||
m[0][1] = 0.f;
|
m[0][1] = 0.f;
|
||||||
@ -380,7 +398,7 @@ static inline void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float
|
|||||||
m[3][2] = -((2.f * f * n) / (f - n));
|
m[3][2] = -((2.f * f * n) / (f - n));
|
||||||
m[3][3] = 0.f;
|
m[3][3] = 0.f;
|
||||||
}
|
}
|
||||||
static inline void mat4x4_look_at(mat4x4 m, vec3 eye, vec3 center, vec3 up)
|
LINMATH_H_FUNC void mat4x4_look_at(mat4x4 m, vec3 eye, vec3 center, vec3 up)
|
||||||
{
|
{
|
||||||
/* Adapted from Android's OpenGL Matrix.java. */
|
/* Adapted from Android's OpenGL Matrix.java. */
|
||||||
/* See the OpenGL GLUT documentation for gluLookAt for a description */
|
/* See the OpenGL GLUT documentation for gluLookAt for a description */
|
||||||
@ -389,15 +407,14 @@ static inline void mat4x4_look_at(mat4x4 m, vec3 eye, vec3 center, vec3 up)
|
|||||||
/* TODO: The negation of of can be spared by swapping the order of
|
/* TODO: The negation of of can be spared by swapping the order of
|
||||||
* operands in the following cross products in the right way. */
|
* operands in the following cross products in the right way. */
|
||||||
vec3 f;
|
vec3 f;
|
||||||
vec3 s;
|
|
||||||
vec3 t;
|
|
||||||
|
|
||||||
vec3_sub(f, center, eye);
|
vec3_sub(f, center, eye);
|
||||||
vec3_norm(f, f);
|
vec3_norm(f, f);
|
||||||
|
|
||||||
|
vec3 s;
|
||||||
vec3_mul_cross(s, f, up);
|
vec3_mul_cross(s, f, up);
|
||||||
vec3_norm(s, s);
|
vec3_norm(s, s);
|
||||||
|
|
||||||
|
vec3 t;
|
||||||
vec3_mul_cross(t, s, f);
|
vec3_mul_cross(t, s, f);
|
||||||
|
|
||||||
m[0][0] = s[0];
|
m[0][0] = s[0];
|
||||||
@ -424,24 +441,24 @@ static inline void mat4x4_look_at(mat4x4 m, vec3 eye, vec3 center, vec3 up)
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef float quat[4];
|
typedef float quat[4];
|
||||||
static inline void quat_identity(quat q)
|
LINMATH_H_FUNC void quat_identity(quat q)
|
||||||
{
|
{
|
||||||
q[0] = q[1] = q[2] = 0.f;
|
q[0] = q[1] = q[2] = 0.f;
|
||||||
q[3] = 1.f;
|
q[3] = 1.f;
|
||||||
}
|
}
|
||||||
static inline void quat_add(quat r, quat a, quat b)
|
LINMATH_H_FUNC void quat_add(quat r, quat a, quat b)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<4; ++i)
|
for(i=0; i<4; ++i)
|
||||||
r[i] = a[i] + b[i];
|
r[i] = a[i] + b[i];
|
||||||
}
|
}
|
||||||
static inline void quat_sub(quat r, quat a, quat b)
|
LINMATH_H_FUNC void quat_sub(quat r, quat a, quat b)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<4; ++i)
|
for(i=0; i<4; ++i)
|
||||||
r[i] = a[i] - b[i];
|
r[i] = a[i] - b[i];
|
||||||
}
|
}
|
||||||
static inline void quat_mul(quat r, quat p, quat q)
|
LINMATH_H_FUNC void quat_mul(quat r, quat p, quat q)
|
||||||
{
|
{
|
||||||
vec3 w;
|
vec3 w;
|
||||||
vec3_mul_cross(r, p, q);
|
vec3_mul_cross(r, p, q);
|
||||||
@ -451,13 +468,13 @@ static inline void quat_mul(quat r, quat p, quat q)
|
|||||||
vec3_add(r, r, w);
|
vec3_add(r, r, w);
|
||||||
r[3] = p[3]*q[3] - vec3_mul_inner(p, q);
|
r[3] = p[3]*q[3] - vec3_mul_inner(p, q);
|
||||||
}
|
}
|
||||||
static inline void quat_scale(quat r, quat v, float s)
|
LINMATH_H_FUNC void quat_scale(quat r, quat v, float s)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<4; ++i)
|
for(i=0; i<4; ++i)
|
||||||
r[i] = v[i] * s;
|
r[i] = v[i] * s;
|
||||||
}
|
}
|
||||||
static inline float quat_inner_product(quat a, quat b)
|
LINMATH_H_FUNC float quat_inner_product(quat a, quat b)
|
||||||
{
|
{
|
||||||
float p = 0.f;
|
float p = 0.f;
|
||||||
int i;
|
int i;
|
||||||
@ -465,42 +482,43 @@ static inline float quat_inner_product(quat a, quat b)
|
|||||||
p += b[i]*a[i];
|
p += b[i]*a[i];
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
static inline void quat_conj(quat r, quat q)
|
LINMATH_H_FUNC void quat_conj(quat r, quat q)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<3; ++i)
|
for(i=0; i<3; ++i)
|
||||||
r[i] = -q[i];
|
r[i] = -q[i];
|
||||||
r[3] = q[3];
|
r[3] = q[3];
|
||||||
}
|
}
|
||||||
static inline void quat_rotate(quat r, float angle, vec3 axis) {
|
LINMATH_H_FUNC void quat_rotate(quat r, float angle, vec3 axis) {
|
||||||
int i;
|
|
||||||
vec3 v;
|
vec3 v;
|
||||||
vec3_scale(v, axis, sinf(angle / 2));
|
vec3_scale(v, axis, sinf(angle / 2));
|
||||||
|
int i;
|
||||||
for(i=0; i<3; ++i)
|
for(i=0; i<3; ++i)
|
||||||
r[i] = v[i];
|
r[i] = v[i];
|
||||||
r[3] = cosf(angle / 2);
|
r[3] = cosf(angle / 2);
|
||||||
}
|
}
|
||||||
#define quat_norm vec4_norm
|
#define quat_norm vec4_norm
|
||||||
static inline void quat_mul_vec3(vec3 r, quat q, vec3 v)
|
LINMATH_H_FUNC void quat_mul_vec3(vec3 r, quat q, vec3 v)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Method by Fabian 'ryg' Giessen (of Farbrausch)
|
* Method by Fabian 'ryg' Giessen (of Farbrausch)
|
||||||
t = 2 * cross(q.xyz, v)
|
t = 2 * cross(q.xyz, v)
|
||||||
v' = v + q.w * t + cross(q.xyz, t)
|
v' = v + q.w * t + cross(q.xyz, t)
|
||||||
*/
|
*/
|
||||||
vec3 t = {q[0], q[1], q[2]};
|
vec3 t;
|
||||||
|
vec3 q_xyz = {q[0], q[1], q[2]};
|
||||||
vec3 u = {q[0], q[1], q[2]};
|
vec3 u = {q[0], q[1], q[2]};
|
||||||
|
|
||||||
vec3_mul_cross(t, t, v);
|
vec3_mul_cross(t, q_xyz, v);
|
||||||
vec3_scale(t, t, 2);
|
vec3_scale(t, t, 2);
|
||||||
|
|
||||||
vec3_mul_cross(u, u, t);
|
vec3_mul_cross(u, q_xyz, t);
|
||||||
vec3_scale(t, t, q[3]);
|
vec3_scale(t, t, q[3]);
|
||||||
|
|
||||||
vec3_add(r, v, t);
|
vec3_add(r, v, t);
|
||||||
vec3_add(r, r, u);
|
vec3_add(r, r, u);
|
||||||
}
|
}
|
||||||
static inline void mat4x4_from_quat(mat4x4 M, quat q)
|
LINMATH_H_FUNC void mat4x4_from_quat(mat4x4 M, quat q)
|
||||||
{
|
{
|
||||||
float a = q[3];
|
float a = q[3];
|
||||||
float b = q[0];
|
float b = q[0];
|
||||||
@ -530,7 +548,7 @@ static inline void mat4x4_from_quat(mat4x4 M, quat q)
|
|||||||
M[3][3] = 1.f;
|
M[3][3] = 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mat4x4o_mul_quat(mat4x4 R, mat4x4 M, quat q)
|
LINMATH_H_FUNC void mat4x4o_mul_quat(mat4x4 R, mat4x4 M, quat q)
|
||||||
{
|
{
|
||||||
/* XXX: The way this is written only works for othogonal matrices. */
|
/* XXX: The way this is written only works for othogonal matrices. */
|
||||||
/* TODO: Take care of non-orthogonal case. */
|
/* TODO: Take care of non-orthogonal case. */
|
||||||
@ -541,7 +559,7 @@ static inline void mat4x4o_mul_quat(mat4x4 R, mat4x4 M, quat q)
|
|||||||
R[3][0] = R[3][1] = R[3][2] = 0.f;
|
R[3][0] = R[3][1] = R[3][2] = 0.f;
|
||||||
R[3][3] = 1.f;
|
R[3][3] = 1.f;
|
||||||
}
|
}
|
||||||
static inline void quat_from_mat4x4(quat q, mat4x4 M)
|
LINMATH_H_FUNC void quat_from_mat4x4(quat q, mat4x4 M)
|
||||||
{
|
{
|
||||||
float r=0.f;
|
float r=0.f;
|
||||||
int i;
|
int i;
|
||||||
@ -557,7 +575,7 @@ static inline void quat_from_mat4x4(quat q, mat4x4 M)
|
|||||||
p = &perm[i];
|
p = &perm[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
r = (float) sqrt(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]] );
|
r = sqrtf(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]] );
|
||||||
|
|
||||||
if(r < 1e-6) {
|
if(r < 1e-6) {
|
||||||
q[0] = 1.f;
|
q[0] = 1.f;
|
||||||
@ -571,4 +589,33 @@ static inline void quat_from_mat4x4(quat q, mat4x4 M)
|
|||||||
q[3] = (M[p[2]][p[1]] - M[p[1]][p[2]])/(2.f*r);
|
q[3] = (M[p[2]][p[1]] - M[p[1]][p[2]])/(2.f*r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LINMATH_H_FUNC void mat4x4_arcball(mat4x4 R, mat4x4 M, vec2 _a, vec2 _b, float s)
|
||||||
|
{
|
||||||
|
vec2 a; memcpy(a, _a, sizeof(a));
|
||||||
|
vec2 b; memcpy(b, _b, sizeof(b));
|
||||||
|
|
||||||
|
float z_a = 0.;
|
||||||
|
float z_b = 0.;
|
||||||
|
|
||||||
|
if(vec2_len(a) < 1.f) {
|
||||||
|
z_a = sqrtf(1.f - vec2_mul_inner(a, a));
|
||||||
|
} else {
|
||||||
|
vec2_norm(a, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(vec2_len(b) < 1.f) {
|
||||||
|
z_b = sqrtf(1.f - vec2_mul_inner(b, b));
|
||||||
|
} else {
|
||||||
|
vec2_norm(b, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 a_ = {a[0], a[1], z_a};
|
||||||
|
vec3 b_ = {b[0], b[1], z_b};
|
||||||
|
|
||||||
|
vec3 c_;
|
||||||
|
vec3_mul_cross(c_, a_, b_);
|
||||||
|
|
||||||
|
float const angle = acosf(vec3_mul_inner(a_, b_)) * s;
|
||||||
|
mat4x4_rotate(R, M, c_[0], c_[1], c_[2], angle);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,3 +30,5 @@ add_custom_target(docs ALL "${DOXYGEN_EXECUTABLE}"
|
|||||||
WORKING_DIRECTORY "${GLFW_BINARY_DIR}/docs"
|
WORKING_DIRECTORY "${GLFW_BINARY_DIR}/docs"
|
||||||
COMMENT "Generating HTML documentation" VERBATIM)
|
COMMENT "Generating HTML documentation" VERBATIM)
|
||||||
|
|
||||||
|
set_target_properties(docs PROPERTIES FOLDER "GLFW3")
|
||||||
|
|
||||||
|
128
docs/build.dox
128
docs/build.dox
@ -78,6 +78,11 @@ compiler that the GLFW functions are defined in a DLL.
|
|||||||
The following macros control which OpenGL or OpenGL ES API header is included.
|
The following macros control which OpenGL or OpenGL ES API header is included.
|
||||||
Only one of these may be defined at a time.
|
Only one of these may be defined at a time.
|
||||||
|
|
||||||
|
@note GLFW does not provide any of the API headers mentioned below. They are
|
||||||
|
provided by your development environment or your OpenGL, OpenGL ES or Vulkan
|
||||||
|
SDK, and most of them can be downloaded from the
|
||||||
|
[Khronos Registry](https://www.khronos.org/registry/).
|
||||||
|
|
||||||
@anchor GLFW_INCLUDE_GLCOREARB
|
@anchor GLFW_INCLUDE_GLCOREARB
|
||||||
__GLFW_INCLUDE_GLCOREARB__ makes the GLFW header include the modern
|
__GLFW_INCLUDE_GLCOREARB__ makes the GLFW header include the modern
|
||||||
`GL/glcorearb.h` header (`OpenGL/gl3.h` on macOS) instead of the regular OpenGL
|
`GL/glcorearb.h` header (`OpenGL/gl3.h` on macOS) instead of the regular OpenGL
|
||||||
@ -129,10 +134,6 @@ header selected above. This should only be used with the standard OpenGL header
|
|||||||
and only for compatibility with legacy code. GLU has been deprecated and should
|
and only for compatibility with legacy code. GLU has been deprecated and should
|
||||||
not be used in new code.
|
not be used in new code.
|
||||||
|
|
||||||
@note GLFW does not provide any of the API headers mentioned above. They must
|
|
||||||
be provided by your development environment or your OpenGL, OpenGL ES or Vulkan
|
|
||||||
SDK.
|
|
||||||
|
|
||||||
@note None of these macros may be defined during the compilation of GLFW itself.
|
@note None of these macros may be defined during the compilation of GLFW itself.
|
||||||
If your build includes GLFW and you define any these in your build files, make
|
If your build includes GLFW and you define any these in your build files, make
|
||||||
sure they are not applied to the GLFW sources.
|
sure they are not applied to the GLFW sources.
|
||||||
@ -166,16 +167,11 @@ must also explicitly link with `gdi32`. Other toolchains including MinGW-w64
|
|||||||
include it in the set of default libraries along with other dependencies like
|
include it in the set of default libraries along with other dependencies like
|
||||||
`user32` and `kernel32`.
|
`user32` and `kernel32`.
|
||||||
|
|
||||||
If you are using GLU, you must also link with `glu32`.
|
|
||||||
|
|
||||||
The link library for the GLFW DLL is named `glfw3dll`. When compiling an
|
The link library for the GLFW DLL is named `glfw3dll`. When compiling an
|
||||||
application that uses the DLL version of GLFW, you need to define the @ref
|
application that uses the DLL version of GLFW, you need to define the @ref
|
||||||
GLFW_DLL macro _before_ any inclusion of the GLFW header. This can be done
|
GLFW_DLL macro _before_ any inclusion of the GLFW header. This can be done
|
||||||
either with a compiler switch or by defining it in your source code.
|
either with a compiler switch or by defining it in your source code.
|
||||||
|
|
||||||
An application using the GLFW DLL does not need to link against any of its
|
|
||||||
dependencies, but you still have to link against `glu32` if it uses GLU.
|
|
||||||
|
|
||||||
|
|
||||||
@subsection build_link_cmake_source With CMake and GLFW source
|
@subsection build_link_cmake_source With CMake and GLFW source
|
||||||
|
|
||||||
@ -187,51 +183,38 @@ With a few changes to your `CMakeLists.txt` you can have the GLFW source tree
|
|||||||
built along with your application.
|
built along with your application.
|
||||||
|
|
||||||
Add the root directory of the GLFW source tree to your project. This will add
|
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.
|
the `glfw` target to your project.
|
||||||
|
|
||||||
@code{.cmake}
|
@code{.cmake}
|
||||||
add_subdirectory(path/to/glfw)
|
add_subdirectory(path/to/glfw)
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Once GLFW has been added to the project, link against it with the `glfw` target.
|
Once GLFW has been added, link your application against the `glfw` target.
|
||||||
This adds all link-time dependencies of GLFW as it is currently configured,
|
This adds the GLFW library and its link-time dependencies as it is currently
|
||||||
the include directory for the GLFW header and, when applicable, the @ref
|
configured, the include directory for the GLFW header and, when applicable, the
|
||||||
GLFW_DLL macro.
|
@ref GLFW_DLL macro.
|
||||||
|
|
||||||
@code{.cmake}
|
@code{.cmake}
|
||||||
target_link_libraries(myapp glfw)
|
target_link_libraries(myapp glfw)
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Note that the dependencies do not include OpenGL or GLU, as GLFW loads any
|
Note that the `glfw` target does not depend on OpenGL, as GLFW loads any OpenGL,
|
||||||
OpenGL, OpenGL ES or Vulkan libraries it needs at runtime and does not use GLU.
|
OpenGL ES or Vulkan libraries it needs at runtime. If your application calls
|
||||||
If your application calls OpenGL directly, instead of using a modern
|
OpenGL directly, instead of using a modern
|
||||||
[extension loader library](@ref context_glext_auto) you can find it by requiring
|
[extension loader library](@ref context_glext_auto), use the OpenGL CMake
|
||||||
the OpenGL package.
|
package.
|
||||||
|
|
||||||
@code{.cmake}
|
@code{.cmake}
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
If OpenGL is found, the `OPENGL_FOUND` variable is true and the
|
If OpenGL is found, the `OpenGL::GL` target is added to your project, containing
|
||||||
`OPENGL_INCLUDE_DIR` and `OPENGL_gl_LIBRARY` cache variables can be used.
|
library and include directory paths. Link against this like any other library.
|
||||||
|
|
||||||
@code{.cmake}
|
@code{.cmake}
|
||||||
target_include_directories(myapp PUBLIC ${OPENGL_INCLUDE_DIR})
|
target_link_libraries(myapp OpenGL::GL)
|
||||||
target_link_libraries(myapp ${OPENGL_gl_LIBRARY})
|
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The OpenGL CMake package also looks for GLU. If GLU is found, the
|
|
||||||
`OPENGL_GLU_FOUND` variable is true and the `OPENGL_INCLUDE_DIR` and
|
|
||||||
`OPENGL_glu_LIBRARY` cache variables can be used.
|
|
||||||
|
|
||||||
@code{.cmake}
|
|
||||||
target_link_libraries(myapp ${OPENGL_glu_LIBRARY})
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
@note GLU has been deprecated and should not be used in new code, but some
|
|
||||||
legacy code requires it. See the [section on GLU](@ref moving_glu) in the
|
|
||||||
transition guide for suggested replacements.
|
|
||||||
|
|
||||||
|
|
||||||
@subsection build_link_cmake_package With CMake and installed GLFW binaries
|
@subsection build_link_cmake_package With CMake and installed GLFW binaries
|
||||||
|
|
||||||
@ -247,44 +230,30 @@ find_package(glfw3 3.4 REQUIRED)
|
|||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Once GLFW has been added to the project, link against it with the `glfw` target.
|
Once GLFW has been added to the project, link against it with the `glfw` target.
|
||||||
This adds all link-time dependencies of GLFW as it is currently configured,
|
This adds the GLFW library and its link-time dependencies, the include directory
|
||||||
the include directory for the GLFW header and, when applicable, the @ref
|
for the GLFW header and, when applicable, the @ref GLFW_DLL macro.
|
||||||
GLFW_DLL macro.
|
|
||||||
|
|
||||||
@code{.cmake}
|
@code{.cmake}
|
||||||
target_link_libraries(myapp glfw)
|
target_link_libraries(myapp glfw)
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Note that the dependencies do not include OpenGL or GLU, as GLFW loads any
|
Note that the `glfw` target does not depend on OpenGL, as GLFW loads any OpenGL,
|
||||||
OpenGL, OpenGL ES or Vulkan libraries it needs at runtime and does not use GLU.
|
OpenGL ES or Vulkan libraries it needs at runtime. If your application calls
|
||||||
If your application calls OpenGL directly, instead of using a modern
|
OpenGL directly, instead of using a modern
|
||||||
[extension loader library](@ref context_glext_auto) you can find it by requiring
|
[extension loader library](@ref context_glext_auto), use the OpenGL CMake
|
||||||
the OpenGL package.
|
package.
|
||||||
|
|
||||||
@code{.cmake}
|
@code{.cmake}
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
If OpenGL is found, the `OPENGL_FOUND` variable is true and the
|
If OpenGL is found, the `OpenGL::GL` target is added to your project, containing
|
||||||
`OPENGL_INCLUDE_DIR` and `OPENGL_gl_LIBRARY` cache variables can be used.
|
library and include directory paths. Link against this like any other library.
|
||||||
|
|
||||||
@code{.cmake}
|
@code{.cmake}
|
||||||
target_include_directories(myapp PUBLIC ${OPENGL_INCLUDE_DIR})
|
target_link_libraries(myapp OpenGL::GL)
|
||||||
target_link_libraries(myapp ${OPENGL_gl_LIBRARY})
|
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The OpenGL CMake package also looks for GLU. If GLU is found, the
|
|
||||||
`OPENGL_GLU_FOUND` variable is true and the `OPENGL_INCLUDE_DIR` and
|
|
||||||
`OPENGL_glu_LIBRARY` cache variables can be used.
|
|
||||||
|
|
||||||
@code{.cmake}
|
|
||||||
target_link_libraries(myapp ${OPENGL_glu_LIBRARY})
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
@note GLU has been deprecated and should not be used in new code, but some
|
|
||||||
legacy code requires it. See the [section on GLU](@ref moving_glu) in the
|
|
||||||
transition guide for suggested replacements.
|
|
||||||
|
|
||||||
|
|
||||||
@subsection build_link_pkgconfig With makefiles and pkg-config on Unix
|
@subsection build_link_pkgconfig With makefiles and pkg-config on Unix
|
||||||
|
|
||||||
@ -299,42 +268,31 @@ A typical compile and link command-line when using the static version of the
|
|||||||
GLFW library may look like this:
|
GLFW library may look like this:
|
||||||
|
|
||||||
@code{.sh}
|
@code{.sh}
|
||||||
cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --static --libs glfw3`
|
cc $(pkg-config --cflags glfw3) -o myprog myprog.c $(pkg-config --static --libs glfw3)
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
If you are using the shared version of the GLFW library, omit the `--static`
|
If you are using the shared version of the GLFW library, omit the `--static`
|
||||||
flag.
|
flag.
|
||||||
|
|
||||||
@code{.sh}
|
@code{.sh}
|
||||||
cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --libs glfw3`
|
cc $(pkg-config --cflags glfw3) -o myprog myprog.c $(pkg-config --libs glfw3)
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
You can also use the `glfw3.pc` file without installing it first, by using the
|
You can also use the `glfw3.pc` file without installing it first, by using the
|
||||||
`PKG_CONFIG_PATH` environment variable.
|
`PKG_CONFIG_PATH` environment variable.
|
||||||
|
|
||||||
@code{.sh}
|
@code{.sh}
|
||||||
env PKG_CONFIG_PATH=path/to/glfw/src cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --libs glfw3`
|
env PKG_CONFIG_PATH=path/to/glfw/src cc $(pkg-config --cflags glfw3) -o myprog myprog.c $(pkg-config --libs glfw3)
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The dependencies do not include OpenGL or GLU, as GLFW loads any OpenGL, OpenGL
|
The dependencies do not include OpenGL, as GLFW loads any OpenGL, OpenGL ES or
|
||||||
ES or Vulkan libraries it needs at runtime and does not use GLU. On macOS, GLU
|
Vulkan libraries it needs at runtime. If your application calls OpenGL
|
||||||
is built into the OpenGL framework, so if you need GLU you don't need to do
|
directly, instead of using a modern
|
||||||
anything extra. If you need GLU and are using Linux or BSD, you should add the
|
[extension loader library](@ref context_glext_auto), you should add the `gl`
|
||||||
`glu` pkg-config package.
|
pkg-config package.
|
||||||
|
|
||||||
@code{.sh}
|
@code{.sh}
|
||||||
cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --libs glfw3 glu`
|
cc $(pkg-config --cflags glfw3 gl) -o myprog myprog.c $(pkg-config --libs glfw3 gl)
|
||||||
@endcode
|
|
||||||
|
|
||||||
@note GLU has been deprecated and should not be used in new code, but some
|
|
||||||
legacy code requires it. See the [section on GLU](@ref moving_glu) in the
|
|
||||||
transition guide for suggested replacements.
|
|
||||||
|
|
||||||
If you are using the static version of the GLFW library, make sure you don't
|
|
||||||
link statically against GLU.
|
|
||||||
|
|
||||||
@code{.sh}
|
|
||||||
cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --static --libs glfw3` `pkg-config --libs glu`
|
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
|
|
||||||
@ -344,8 +302,8 @@ If you are using the dynamic library version of GLFW, add it to the project
|
|||||||
dependencies.
|
dependencies.
|
||||||
|
|
||||||
If you are using the static library version of GLFW, add it and the Cocoa,
|
If you are using the static library version of GLFW, add it and the Cocoa,
|
||||||
OpenGL, IOKit and CoreVideo frameworks to the project as dependencies. They can
|
OpenGL and IOKit frameworks to the project as dependencies. They can all be
|
||||||
all be found in `/System/Library/Frameworks`.
|
found in `/System/Library/Frameworks`.
|
||||||
|
|
||||||
|
|
||||||
@subsection build_link_osx With command-line on macOS
|
@subsection build_link_osx With command-line on macOS
|
||||||
@ -359,7 +317,7 @@ the `-l` and `-framework` switches.
|
|||||||
If you are using the dynamic GLFW library, which is named `libglfw.3.dylib`, do:
|
If you are using the dynamic GLFW library, which is named `libglfw.3.dylib`, do:
|
||||||
|
|
||||||
@code{.sh}
|
@code{.sh}
|
||||||
cc -o myprog myprog.c -lglfw -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo
|
cc -o myprog myprog.c -lglfw -framework Cocoa -framework OpenGL -framework IOKit
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
If you are using the static library, named `libglfw3.a`, substitute `-lglfw3`
|
If you are using the static library, named `libglfw3.a`, substitute `-lglfw3`
|
||||||
@ -368,9 +326,7 @@ for `-lglfw`.
|
|||||||
Note that you do not add the `.framework` extension to a framework when linking
|
Note that you do not add the `.framework` extension to a framework when linking
|
||||||
against it from the command-line.
|
against it from the command-line.
|
||||||
|
|
||||||
The OpenGL framework contains both the OpenGL and GLU APIs, so there is nothing
|
@note Your machine may have `libGL.*.dylib` style OpenGL library, but that is
|
||||||
special to do when using GLU. Also note that even though your machine may have
|
for the X Window System and will not work with the macOS native version of GLFW.
|
||||||
`libGL`-style OpenGL libraries, they are for use with the X Window System and
|
|
||||||
will _not_ work with the macOS native version of GLFW.
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -111,7 +111,7 @@ has been configured in the compositor.
|
|||||||
GLFW uses the [xdg-shell
|
GLFW uses the [xdg-shell
|
||||||
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml)
|
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml)
|
||||||
to provide better window management. This protocol is part of
|
to provide better window management. This protocol is part of
|
||||||
wayland-protocols 1.12, and mandatory at build time.
|
wayland-protocols 1.12, and is mandatory for GLFW to display a window.
|
||||||
|
|
||||||
GLFW uses the [relative pointer
|
GLFW uses the [relative pointer
|
||||||
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/relative-pointer/relative-pointer-unstable-v1.xml)
|
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/relative-pointer/relative-pointer-unstable-v1.xml)
|
||||||
@ -268,10 +268,10 @@ surfaces on Microsoft Windows. If any of these extensions are not available,
|
|||||||
@ref glfwGetRequiredInstanceExtensions will return an empty list and window
|
@ref glfwGetRequiredInstanceExtensions will return an empty list and window
|
||||||
surface creation will fail.
|
surface creation will fail.
|
||||||
|
|
||||||
GLFW uses the `VK_KHR_surface` and `VK_MVK_macos_surface` extensions to create
|
GLFW uses the `VK_KHR_surface` and either the `VK_MVK_macos_surface` or
|
||||||
surfaces on macOS. If any of these extensions are not available, @ref
|
`VK_EXT_metal_surface` extensions to create surfaces on macOS. If any of these
|
||||||
glfwGetRequiredInstanceExtensions will return an empty list and window surface
|
extensions are not available, @ref glfwGetRequiredInstanceExtensions will
|
||||||
creation will fail.
|
return an empty list and window surface creation will fail.
|
||||||
|
|
||||||
GLFW uses the `VK_KHR_surface` and either the `VK_KHR_xlib_surface` or
|
GLFW uses the `VK_KHR_surface` and either the `VK_KHR_xlib_surface` or
|
||||||
`VK_KHR_xcb_surface` extensions to create surfaces on X11. If `VK_KHR_surface`
|
`VK_KHR_xcb_surface` extensions to create surfaces on X11. If `VK_KHR_surface`
|
||||||
|
@ -84,10 +84,6 @@ objects are recommended for rendering with such contexts.
|
|||||||
You should still [process events](@ref events) as long as you have at least one
|
You should still [process events](@ref events) as long as you have at least one
|
||||||
window, even if none of them are visible.
|
window, even if none of them are visible.
|
||||||
|
|
||||||
@macos The first time a window is created the menu bar is created. This is not
|
|
||||||
desirable for example when writing a command-line only application. Menu bar
|
|
||||||
creation can be disabled with the @ref GLFW_COCOA_MENUBAR init hint.
|
|
||||||
|
|
||||||
|
|
||||||
@subsection context_less Windows without contexts
|
@subsection context_less Windows without contexts
|
||||||
|
|
||||||
|
@ -62,6 +62,11 @@ before the application exits. Modern systems are very good at freeing resources
|
|||||||
allocated by programs that exit, but GLFW sometimes has to change global system
|
allocated by programs that exit, but GLFW sometimes has to change global system
|
||||||
settings and these might not be restored without termination.
|
settings and these might not be restored without termination.
|
||||||
|
|
||||||
|
@macos When the library is initialized the main menu and dock icon are created.
|
||||||
|
These are not desirable for a command-line only program. The creation of the
|
||||||
|
main menu and dock icon can be disabled with the @ref GLFW_COCOA_MENUBAR init
|
||||||
|
hint.
|
||||||
|
|
||||||
|
|
||||||
@subsection init_hints Initialization hints
|
@subsection init_hints Initialization hints
|
||||||
|
|
||||||
@ -97,9 +102,9 @@ the application to the `Contents/Resources` subdirectory of the application's
|
|||||||
bundle, if present. Set this with @ref glfwInitHint.
|
bundle, if present. Set this with @ref glfwInitHint.
|
||||||
|
|
||||||
@anchor GLFW_COCOA_MENUBAR_hint
|
@anchor GLFW_COCOA_MENUBAR_hint
|
||||||
__GLFW_COCOA_MENUBAR__ specifies whether to create a basic menu bar, either from
|
__GLFW_COCOA_MENUBAR__ specifies whether to create the menu bar and dock icon
|
||||||
a nib or manually, when the first window is created, which is when AppKit is
|
when GLFW is initialized. This applies whether the menu bar is created from
|
||||||
initialized. Set this with @ref glfwInitHint.
|
a nib or manually by GLFW. Set this with @ref glfwInitHint.
|
||||||
|
|
||||||
|
|
||||||
@subsubsection init_hints_values Supported and default values
|
@subsubsection init_hints_values Supported and default values
|
||||||
|
@ -52,6 +52,19 @@ add_subdirectory(path/to/glfw)
|
|||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
|
|
||||||
|
@subsubsection initmenu_34 macOS main menu now created at initialization
|
||||||
|
|
||||||
|
GLFW now creates the main menu and completes the initialization of NSApplication
|
||||||
|
during initialization. Programs that do not want a main menu can disable it
|
||||||
|
with the [GLFW_COCOA_MENUBAR](@ref GLFW_COCOA_MENUBAR_hint) init hint.
|
||||||
|
|
||||||
|
|
||||||
|
@subsubsection corevideo_34 CoreVideo dependency has been removed
|
||||||
|
|
||||||
|
GLFW no longer depends on the CoreVideo framework on macOS and it no longer
|
||||||
|
needs to be specified during compilation or linking.
|
||||||
|
|
||||||
|
|
||||||
@subsection deprecations_34 Deprecations in version 3.4
|
@subsection deprecations_34 Deprecations in version 3.4
|
||||||
|
|
||||||
@subsection removals_34 Removals in 3.4
|
@subsection removals_34 Removals in 3.4
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
link_libraries(glfw)
|
link_libraries(glfw)
|
||||||
|
|
||||||
include_directories(${glfw_INCLUDE_DIRS} "${GLFW_SOURCE_DIR}/deps")
|
include_directories("${GLFW_SOURCE_DIR}/deps")
|
||||||
|
|
||||||
if (MATH_LIBRARY)
|
if (MATH_LIBRARY)
|
||||||
link_libraries("${MATH_LIBRARY}")
|
link_libraries("${MATH_LIBRARY}")
|
||||||
@ -11,27 +11,10 @@ if (MSVC)
|
|||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (GLFW_USE_OSMESA)
|
|
||||||
add_definitions(-DUSE_NATIVE_OSMESA)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(ICON glfw.rc)
|
set(ICON glfw.rc)
|
||||||
elseif (APPLE)
|
elseif (APPLE)
|
||||||
set(ICON glfw.icns)
|
set(ICON glfw.icns)
|
||||||
set_source_files_properties(glfw.icns PROPERTIES
|
|
||||||
MACOSX_PACKAGE_LOCATION "Resources")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (${CMAKE_VERSION} VERSION_EQUAL "3.1.0" OR
|
|
||||||
${CMAKE_VERSION} VERSION_GREATER "3.1.0")
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
|
||||||
else()
|
|
||||||
# Remove this fallback when removing support for CMake version less than 3.1
|
|
||||||
add_compile_options("$<$<C_COMPILER_ID:AppleClang>:-std=c99>"
|
|
||||||
"$<$<C_COMPILER_ID:Clang>:-std=c99>"
|
|
||||||
"$<$<C_COMPILER_ID:GNU>:-std=c99>")
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(GLAD_GL "${GLFW_SOURCE_DIR}/deps/glad/gl.h"
|
set(GLAD_GL "${GLFW_SOURCE_DIR}/deps/glad/gl.h"
|
||||||
@ -51,20 +34,26 @@ add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD_GL})
|
|||||||
add_executable(triangle-opengl WIN32 MACOSX_BUNDLE triangle-opengl.c ${ICON} ${GLAD_GL})
|
add_executable(triangle-opengl WIN32 MACOSX_BUNDLE triangle-opengl.c ${ICON} ${GLAD_GL})
|
||||||
add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD_GL})
|
add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD_GL})
|
||||||
|
|
||||||
target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}")
|
target_link_libraries(particles Threads::Threads)
|
||||||
if (RT_LIBRARY)
|
if (RT_LIBRARY)
|
||||||
target_link_libraries(particles "${RT_LIBRARY}")
|
target_link_libraries(particles "${RT_LIBRARY}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(WINDOWS_BINARIES boing gears heightmap particles sharing splitview triangle-opengl wave)
|
set(GUI_ONLY_BINARIES boing gears heightmap particles sharing splitview
|
||||||
|
triangle-opengl wave)
|
||||||
set(CONSOLE_BINARIES offscreen)
|
set(CONSOLE_BINARIES offscreen)
|
||||||
|
|
||||||
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
set_target_properties(${GUI_ONLY_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
||||||
|
C_STANDARD 99
|
||||||
FOLDER "GLFW3/Examples")
|
FOLDER "GLFW3/Examples")
|
||||||
|
|
||||||
|
if (GLFW_USE_OSMESA)
|
||||||
|
target_compile_definitions(offscreen PRIVATE USE_NATIVE_OSMESA)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
# Tell MSVC to use main instead of WinMain for Windows subsystem executables
|
# Tell MSVC to use main instead of WinMain for Windows subsystem executables
|
||||||
set_target_properties(${WINDOWS_BINARIES} PROPERTIES
|
set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
|
||||||
LINK_FLAGS "/ENTRY:mainCRTStartup")
|
LINK_FLAGS "/ENTRY:mainCRTStartup")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -78,11 +67,12 @@ if (APPLE)
|
|||||||
set_target_properties(splitview PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "SplitView")
|
set_target_properties(splitview PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "SplitView")
|
||||||
set_target_properties(wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
|
set_target_properties(wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
|
||||||
|
|
||||||
set_target_properties(${WINDOWS_BINARIES} PROPERTIES
|
set_source_files_properties(glfw.icns PROPERTIES
|
||||||
RESOURCE glfw.icns
|
MACOSX_PACKAGE_LOCATION "Resources")
|
||||||
|
set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
|
||||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
|
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
|
||||||
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION}
|
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION}
|
||||||
MACOSX_BUNDLE_ICON_FILE glfw.icns
|
MACOSX_BUNDLE_ICON_FILE glfw.icns
|
||||||
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/MacOSXBundleInfo.plist.in")
|
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/Info.plist.in")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -148,6 +148,7 @@ int main(void)
|
|||||||
glUseProgram(program);
|
glUseProgram(program);
|
||||||
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
|
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
glFinish();
|
||||||
|
|
||||||
#if USE_NATIVE_OSMESA
|
#if USE_NATIVE_OSMESA
|
||||||
glfwGetOSMesaColorBuffer(window, &width, &height, NULL, (void**) &buffer);
|
glfwGetOSMesaColorBuffer(window, &width, &height, NULL, (void**) &buffer);
|
||||||
|
@ -1831,6 +1831,18 @@ typedef struct GLFWgamepadstate
|
|||||||
* bundle, if present. This can be disabled with the @ref
|
* bundle, if present. This can be disabled with the @ref
|
||||||
* GLFW_COCOA_CHDIR_RESOURCES init hint.
|
* GLFW_COCOA_CHDIR_RESOURCES init hint.
|
||||||
*
|
*
|
||||||
|
* @remark @macos This function will create the main menu and dock icon for the
|
||||||
|
* application. If GLFW finds a `MainMenu.nib` it is loaded and assumed to
|
||||||
|
* contain a menu bar. Otherwise a minimal menu bar is created manually with
|
||||||
|
* common commands like Hide, Quit and About. The About entry opens a minimal
|
||||||
|
* about dialog with information from the application's bundle. The menu bar
|
||||||
|
* and dock icon can be disabled entirely with the @ref GLFW_COCOA_MENUBAR init
|
||||||
|
* hint.
|
||||||
|
*
|
||||||
|
* @remark @x11 This function will set the `LC_CTYPE` category of the
|
||||||
|
* application locale according to the current environment if that category is
|
||||||
|
* still "C". This is because the "C" locale breaks Unicode text input.
|
||||||
|
*
|
||||||
* @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 intro_init
|
* @sa @ref intro_init
|
||||||
@ -2670,13 +2682,6 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
|
|||||||
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
|
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
|
||||||
* in the Mac Developer Library.
|
* in the Mac Developer Library.
|
||||||
*
|
*
|
||||||
* @remark @macos The first time a window is created the menu bar is created.
|
|
||||||
* If GLFW finds a `MainMenu.nib` it is loaded and assumed to contain a menu
|
|
||||||
* bar. Otherwise a minimal menu bar is created manually with common commands
|
|
||||||
* like Hide, Quit and About. The About entry opens a minimal about dialog
|
|
||||||
* with information from the application's bundle. Menu bar creation can be
|
|
||||||
* disabled entirely with the @ref GLFW_COCOA_MENUBAR init hint.
|
|
||||||
*
|
|
||||||
* @remark @macos On OS X 10.10 and later the window frame will not be rendered
|
* @remark @macos On OS X 10.10 and later the window frame will not be rendered
|
||||||
* at full resolution on Retina displays unless the
|
* at full resolution on Retina displays unless the
|
||||||
* [GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint)
|
* [GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint)
|
||||||
@ -2685,7 +2690,7 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
|
|||||||
* [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html)
|
* [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html)
|
||||||
* in the Mac Developer Library. The GLFW test and example programs use
|
* in the Mac Developer Library. The GLFW test and example programs use
|
||||||
* a custom `Info.plist` template for this, which can be found as
|
* a custom `Info.plist` template for this, which can be found as
|
||||||
* `CMake/MacOSXBundleInfo.plist.in` in the source tree.
|
* `CMake/Info.plist.in` in the source tree.
|
||||||
*
|
*
|
||||||
* @remark @macos When activating frame autosaving with
|
* @remark @macos When activating frame autosaving with
|
||||||
* [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified
|
* [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified
|
||||||
@ -5776,8 +5781,9 @@ GLFWAPI int glfwVulkanSupported(void);
|
|||||||
* returned array, as it is an error to specify an extension more than once in
|
* returned array, as it is an error to specify an extension more than once in
|
||||||
* the `VkInstanceCreateInfo` struct.
|
* the `VkInstanceCreateInfo` struct.
|
||||||
*
|
*
|
||||||
* @remark @macos This function currently only supports the
|
* @remark @macos This function currently supports either the
|
||||||
* `VK_MVK_macos_surface` extension from MoltenVK.
|
* `VK_MVK_macos_surface` extension from MoltenVK or `VK_EXT_metal_surface`
|
||||||
|
* extension.
|
||||||
*
|
*
|
||||||
* @pointer_lifetime The returned array is allocated and freed by GLFW. You
|
* @pointer_lifetime The returned array is allocated and freed by GLFW. You
|
||||||
* should not free it yourself. It is guaranteed to be valid only until the
|
* should not free it yourself. It is guaranteed to be valid only until the
|
||||||
|
@ -1,118 +1,96 @@
|
|||||||
|
|
||||||
set(common_HEADERS internal.h mappings.h
|
add_library(glfw "${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
|
||||||
"${GLFW_BINARY_DIR}/src/glfw_config.h"
|
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h"
|
||||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
|
internal.h mappings.h context.c init.c input.c monitor.c
|
||||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h")
|
vulkan.c window.c)
|
||||||
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
|
target_sources(glfw PRIVATE cocoa_platform.h cocoa_joystick.h posix_thread.h
|
||||||
posix_thread.h nsgl_context.h egl_context.h osmesa_context.h)
|
nsgl_context.h egl_context.h osmesa_context.h
|
||||||
set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m
|
cocoa_init.m cocoa_joystick.m cocoa_monitor.m
|
||||||
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_thread.c
|
cocoa_window.m cocoa_time.c posix_thread.c
|
||||||
nsgl_context.m egl_context.c osmesa_context.c)
|
nsgl_context.m egl_context.c osmesa_context.c)
|
||||||
elseif (_GLFW_WIN32)
|
elseif (_GLFW_WIN32)
|
||||||
set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h
|
target_sources(glfw PRIVATE win32_platform.h win32_joystick.h wgl_context.h
|
||||||
wgl_context.h egl_context.h osmesa_context.h)
|
egl_context.h osmesa_context.h win32_init.c
|
||||||
set(glfw_SOURCES ${common_SOURCES} win32_init.c win32_joystick.c
|
win32_joystick.c win32_monitor.c win32_time.c
|
||||||
win32_monitor.c win32_time.c win32_thread.c win32_window.c
|
win32_thread.c win32_window.c wgl_context.c
|
||||||
wgl_context.c egl_context.c osmesa_context.c)
|
egl_context.c osmesa_context.c)
|
||||||
elseif (_GLFW_X11)
|
elseif (_GLFW_X11)
|
||||||
set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h posix_time.h
|
target_sources(glfw PRIVATE x11_platform.h xkb_unicode.h posix_time.h
|
||||||
posix_thread.h glx_context.h egl_context.h osmesa_context.h)
|
posix_thread.h glx_context.h egl_context.h
|
||||||
set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c
|
osmesa_context.h x11_init.c x11_monitor.c
|
||||||
xkb_unicode.c posix_time.c posix_thread.c glx_context.c
|
x11_window.c xkb_unicode.c posix_time.c
|
||||||
egl_context.c osmesa_context.c)
|
posix_thread.c glx_context.c egl_context.c
|
||||||
|
osmesa_context.c)
|
||||||
elseif (_GLFW_WAYLAND)
|
elseif (_GLFW_WAYLAND)
|
||||||
set(glfw_HEADERS ${common_HEADERS} wl_platform.h
|
target_sources(glfw PRIVATE wl_platform.h posix_time.h posix_thread.h
|
||||||
posix_time.h posix_thread.h xkb_unicode.h egl_context.h
|
xkb_unicode.h egl_context.h osmesa_context.h
|
||||||
osmesa_context.h)
|
wl_init.c wl_monitor.c wl_window.c posix_time.c
|
||||||
set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c
|
posix_thread.c xkb_unicode.c egl_context.c
|
||||||
posix_time.c posix_thread.c xkb_unicode.c
|
osmesa_context.c)
|
||||||
egl_context.c osmesa_context.c)
|
|
||||||
|
|
||||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
|
||||||
PROTOCOL
|
|
||||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/xdg-shell/xdg-shell.xml"
|
|
||||||
BASENAME xdg-shell)
|
|
||||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
|
||||||
PROTOCOL
|
|
||||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
|
||||||
BASENAME xdg-decoration)
|
|
||||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
|
||||||
PROTOCOL
|
|
||||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/viewporter/viewporter.xml"
|
|
||||||
BASENAME viewporter)
|
|
||||||
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)
|
|
||||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
|
||||||
PROTOCOL
|
|
||||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml"
|
|
||||||
BASENAME idle-inhibit-unstable-v1)
|
|
||||||
elseif (_GLFW_OSMESA)
|
elseif (_GLFW_OSMESA)
|
||||||
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
|
target_sources(glfw PRIVATE null_platform.h null_joystick.h posix_time.h
|
||||||
posix_time.h posix_thread.h osmesa_context.h)
|
posix_thread.h osmesa_context.h null_init.c
|
||||||
set(glfw_SOURCES ${common_SOURCES} null_init.c null_monitor.c null_window.c
|
null_monitor.c null_window.c null_joystick.c
|
||||||
null_joystick.c posix_time.c posix_thread.c osmesa_context.c)
|
posix_time.c posix_thread.c osmesa_context.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (_GLFW_X11 OR _GLFW_WAYLAND)
|
if (_GLFW_X11 OR _GLFW_WAYLAND)
|
||||||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
||||||
set(glfw_HEADERS ${glfw_HEADERS} linux_joystick.h)
|
target_sources(glfw PRIVATE linux_joystick.h linux_joystick.c)
|
||||||
set(glfw_SOURCES ${glfw_SOURCES} linux_joystick.c)
|
|
||||||
else()
|
else()
|
||||||
set(glfw_HEADERS ${glfw_HEADERS} null_joystick.h)
|
target_sources(glfw PRIVATE null_joystick.h null_joystick.c)
|
||||||
set(glfw_SOURCES ${glfw_SOURCES} null_joystick.c)
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (APPLE)
|
if (_GLFW_WAYLAND)
|
||||||
# For some reason, CMake doesn't know about .m
|
ecm_add_wayland_client_protocol(GLFW_WAYLAND_PROTOCOL_SOURCES
|
||||||
set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C)
|
PROTOCOL
|
||||||
|
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/xdg-shell/xdg-shell.xml"
|
||||||
|
BASENAME xdg-shell)
|
||||||
|
ecm_add_wayland_client_protocol(GLFW_WAYLAND_PROTOCOL_SOURCES
|
||||||
|
PROTOCOL
|
||||||
|
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
||||||
|
BASENAME xdg-decoration)
|
||||||
|
ecm_add_wayland_client_protocol(GLFW_WAYLAND_PROTOCOL_SOURCES
|
||||||
|
PROTOCOL
|
||||||
|
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/viewporter/viewporter.xml"
|
||||||
|
BASENAME viewporter)
|
||||||
|
ecm_add_wayland_client_protocol(GLFW_WAYLAND_PROTOCOL_SOURCES
|
||||||
|
PROTOCOL
|
||||||
|
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml"
|
||||||
|
BASENAME relative-pointer-unstable-v1)
|
||||||
|
ecm_add_wayland_client_protocol(GLFW_WAYLAND_PROTOCOL_SOURCES
|
||||||
|
PROTOCOL
|
||||||
|
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
|
||||||
|
BASENAME pointer-constraints-unstable-v1)
|
||||||
|
ecm_add_wayland_client_protocol(GLFW_WAYLAND_PROTOCOL_SOURCES
|
||||||
|
PROTOCOL
|
||||||
|
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml"
|
||||||
|
BASENAME idle-inhibit-unstable-v1)
|
||||||
|
target_sources(glfw PRIVATE ${GLFW_WAYLAND_PROTOCOL_SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Make GCC and Clang warn about declarations that VS 2010 and 2012 won't accept
|
if (WIN32 AND BUILD_SHARED_LIBS)
|
||||||
# for all source files that VS will build
|
configure_file(glfw.rc.in glfw.rc @ONLY)
|
||||||
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
|
target_sources(glfw PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/glfw.rc")
|
||||||
"${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
|
|
||||||
"${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
set(windows_SOURCES ${glfw_SOURCES})
|
|
||||||
else()
|
|
||||||
set(windows_SOURCES ${common_SOURCES})
|
|
||||||
endif()
|
|
||||||
set_source_files_properties(${windows_SOURCES} PROPERTIES
|
|
||||||
COMPILE_FLAGS -Wdeclaration-after-statement)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(glfw ${glfw_SOURCES} ${glfw_HEADERS})
|
configure_file(glfw_config.h.in glfw_config.h @ONLY)
|
||||||
|
target_compile_definitions(glfw PRIVATE _GLFW_USE_CONFIG_H)
|
||||||
|
target_sources(glfw PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/glfw_config.h")
|
||||||
|
|
||||||
set_target_properties(glfw PROPERTIES
|
set_target_properties(glfw PROPERTIES
|
||||||
OUTPUT_NAME ${GLFW_LIB_NAME}
|
OUTPUT_NAME ${GLFW_LIB_NAME}
|
||||||
VERSION ${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}
|
VERSION ${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}
|
||||||
SOVERSION ${GLFW_VERSION_MAJOR}
|
SOVERSION ${GLFW_VERSION_MAJOR}
|
||||||
POSITION_INDEPENDENT_CODE ON
|
POSITION_INDEPENDENT_CODE ON
|
||||||
|
C_STANDARD 99
|
||||||
|
C_EXTENSIONS OFF
|
||||||
|
DEFINE_SYMBOL _GLFW_BUILD_DLL
|
||||||
FOLDER "GLFW3")
|
FOLDER "GLFW3")
|
||||||
|
|
||||||
if (${CMAKE_VERSION} VERSION_EQUAL "3.1.0" OR
|
|
||||||
${CMAKE_VERSION} VERSION_GREATER "3.1.0")
|
|
||||||
|
|
||||||
set_target_properties(glfw PROPERTIES C_STANDARD 99)
|
|
||||||
else()
|
|
||||||
# Remove this fallback when removing support for CMake version less than 3.1
|
|
||||||
target_compile_options(glfw PRIVATE
|
|
||||||
"$<$<C_COMPILER_ID:AppleClang>:-std=c99>"
|
|
||||||
"$<$<C_COMPILER_ID:Clang>:-std=c99>"
|
|
||||||
"$<$<C_COMPILER_ID:GNU>:-std=c99>")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_compile_definitions(glfw PRIVATE _GLFW_USE_CONFIG_H)
|
|
||||||
target_include_directories(glfw PUBLIC
|
target_include_directories(glfw PUBLIC
|
||||||
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
|
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
|
||||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
|
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||||
@ -120,26 +98,50 @@ target_include_directories(glfw PRIVATE
|
|||||||
"${GLFW_SOURCE_DIR}/src"
|
"${GLFW_SOURCE_DIR}/src"
|
||||||
"${GLFW_BINARY_DIR}/src"
|
"${GLFW_BINARY_DIR}/src"
|
||||||
${glfw_INCLUDE_DIRS})
|
${glfw_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(glfw PRIVATE Threads::Threads ${glfw_LIBRARIES})
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
# For some reason CMake didn't know about .m until version 3.16
|
||||||
|
set_source_files_properties(cocoa_init.m cocoa_joystick.m cocoa_monitor.m
|
||||||
|
cocoa_window.m nsgl_context.m PROPERTIES
|
||||||
|
LANGUAGE C)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
|
||||||
|
"${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
|
||||||
|
"${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
|
||||||
|
|
||||||
|
# Make GCC and Clang warn about declarations that VS 2010 and 2012 won't
|
||||||
|
# accept for all source files that VS will build
|
||||||
|
set_source_files_properties(context.c init.c input.c monitor.c vulkan.c
|
||||||
|
window.c win32_init.c win32_joystick.c
|
||||||
|
win32_monitor.c win32_time.c win32_thread.c
|
||||||
|
win32_window.c wgl_context.c egl_context.c
|
||||||
|
osmesa_context.c PROPERTIES
|
||||||
|
COMPILE_FLAGS -Wdeclaration-after-statement)
|
||||||
|
|
||||||
|
# Enable a reasonable set of warnings (no, -Wextra is not reasonable)
|
||||||
|
target_compile_options(glfw PRIVATE "-Wall")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
target_compile_definitions(glfw PRIVATE _UNICODE)
|
||||||
|
endif()
|
||||||
|
|
||||||
# HACK: When building on MinGW, WINVER and UNICODE need to be defined before
|
# HACK: When building on MinGW, WINVER and UNICODE need to be defined before
|
||||||
# the inclusion of stddef.h (by glfw3.h), which is itself included before
|
# the inclusion of stddef.h (by glfw3.h), which is itself included before
|
||||||
# win32_platform.h. We define them here until a saner solution can be found
|
# win32_platform.h. We define them here until a saner solution can be found
|
||||||
# NOTE: MinGW-w64 and Visual C++ do /not/ need this hack.
|
# NOTE: MinGW-w64 and Visual C++ do /not/ need this hack.
|
||||||
target_compile_definitions(glfw PRIVATE
|
if (MINGW)
|
||||||
"$<$<BOOL:${MINGW}>:UNICODE;WINVER=0x0501>")
|
target_compile_definitions(glfw PRIVATE UNICODE WINVER=0x0501)
|
||||||
|
endif()
|
||||||
# Enable a reasonable set of warnings (no, -Wextra is not reasonable)
|
|
||||||
target_compile_options(glfw PRIVATE
|
|
||||||
"$<$<C_COMPILER_ID:AppleClang>:-Wall>"
|
|
||||||
"$<$<C_COMPILER_ID:Clang>:-Wall>"
|
|
||||||
"$<$<C_COMPILER_ID:GNU>:-Wall>")
|
|
||||||
|
|
||||||
if (BUILD_SHARED_LIBS)
|
if (BUILD_SHARED_LIBS)
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
if (MINGW)
|
if (MINGW)
|
||||||
# Remove the dependency on the shared version of libgcc
|
# Remove the dependency on the shared version of libgcc
|
||||||
# NOTE: MinGW-w64 has the correct default but MinGW needs this
|
# NOTE: MinGW-w64 has the correct default but MinGW needs this
|
||||||
target_link_options(glfw PRIVATE "-static-libgcc")
|
target_link_libraries(glfw PRIVATE "-static-libgcc")
|
||||||
|
|
||||||
# Remove the lib prefix on the DLL (but not the import library)
|
# Remove the lib prefix on the DLL (but not the import library)
|
||||||
set_target_properties(glfw PROPERTIES PREFIX "")
|
set_target_properties(glfw PROPERTIES PREFIX "")
|
||||||
@ -151,11 +153,8 @@ if (BUILD_SHARED_LIBS)
|
|||||||
set_target_properties(glfw PROPERTIES IMPORT_SUFFIX "dll.lib")
|
set_target_properties(glfw PROPERTIES IMPORT_SUFFIX "dll.lib")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_compile_definitions(glfw INTERFACE GLFW_DLL)
|
target_compile_definitions(glfw INTERFACE GLFW_DLL)
|
||||||
elseif (APPLE)
|
elseif (APPLE)
|
||||||
# Add -fno-common to work around a bug in Apple's GCC
|
|
||||||
target_compile_options(glfw PRIVATE "-fno-common")
|
|
||||||
|
|
||||||
set_target_properties(glfw PROPERTIES
|
set_target_properties(glfw PROPERTIES
|
||||||
INSTALL_NAME_DIR "${CMAKE_INSTALL_LIBDIR}")
|
INSTALL_NAME_DIR "${CMAKE_INSTALL_LIBDIR}")
|
||||||
endif()
|
endif()
|
||||||
@ -164,10 +163,6 @@ if (BUILD_SHARED_LIBS)
|
|||||||
# Hide symbols not explicitly tagged for export from the shared library
|
# Hide symbols not explicitly tagged for export from the shared library
|
||||||
target_compile_options(glfw PRIVATE "-fvisibility=hidden")
|
target_compile_options(glfw PRIVATE "-fvisibility=hidden")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(glfw PRIVATE ${glfw_LIBRARIES})
|
|
||||||
else()
|
|
||||||
target_link_libraries(glfw INTERFACE ${glfw_LIBRARIES})
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
|
@ -431,9 +431,8 @@ static GLFWbool initializeTIS(void)
|
|||||||
// In case we are unbundled, make us a proper UI application
|
// In case we are unbundled, make us a proper UI application
|
||||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||||
|
|
||||||
// Menu bar setup must go between sharedApplication above and
|
// Menu bar setup must go between sharedApplication and finishLaunching
|
||||||
// finishLaunching below, in order to properly emulate the behavior
|
// in order to properly emulate the behavior of NSApplicationMain
|
||||||
// of NSApplicationMain
|
|
||||||
|
|
||||||
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
|
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
|
||||||
{
|
{
|
||||||
@ -448,9 +447,8 @@ static GLFWbool initializeTIS(void)
|
|||||||
|
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification *)notification
|
- (void)applicationDidFinishLaunching:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
[NSApp stop:nil];
|
|
||||||
|
|
||||||
_glfwPlatformPostEmptyEvent();
|
_glfwPlatformPostEmptyEvent();
|
||||||
|
[NSApp stop:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationDidHide:(NSNotification *)notification
|
- (void)applicationDidHide:(NSNotification *)notification
|
||||||
@ -464,6 +462,32 @@ static GLFWbool initializeTIS(void)
|
|||||||
@end // GLFWApplicationDelegate
|
@end // GLFWApplicationDelegate
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void* _glfwLoadLocalVulkanLoaderNS(void)
|
||||||
|
{
|
||||||
|
CFBundleRef bundle = CFBundleGetMainBundle();
|
||||||
|
if (!bundle)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
CFURLRef url =
|
||||||
|
CFBundleCopyAuxiliaryExecutableURL(bundle, CFSTR("libvulkan.1.dylib"));
|
||||||
|
if (!url)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char path[PATH_MAX];
|
||||||
|
void* handle = NULL;
|
||||||
|
|
||||||
|
if (CFURLGetFileSystemRepresentation(url, true, (UInt8*) path, sizeof(path) - 1))
|
||||||
|
handle = _glfw_dlopen(path);
|
||||||
|
|
||||||
|
CFRelease(url);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -478,9 +502,6 @@ int _glfwPlatformInit(void)
|
|||||||
toTarget:_glfw.ns.helper
|
toTarget:_glfw.ns.helper
|
||||||
withObject:nil];
|
withObject:nil];
|
||||||
|
|
||||||
if (NSApp)
|
|
||||||
_glfw.ns.finishedLaunching = GLFW_TRUE;
|
|
||||||
|
|
||||||
[NSApplication sharedApplication];
|
[NSApplication sharedApplication];
|
||||||
|
|
||||||
_glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
|
_glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
|
||||||
@ -533,6 +554,10 @@ int _glfwPlatformInit(void)
|
|||||||
_glfwInitJoysticksNS();
|
_glfwInitJoysticksNS();
|
||||||
|
|
||||||
_glfwPollMonitorsNS();
|
_glfwPollMonitorsNS();
|
||||||
|
|
||||||
|
if (![[NSRunningApplication currentApplication] isFinishedLaunching])
|
||||||
|
[NSApp run];
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
|
|
||||||
} // autoreleasepool
|
} // autoreleasepool
|
||||||
|
@ -331,7 +331,7 @@ void _glfwInitJoysticksNS(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(usages) / sizeof(long); i++)
|
for (size_t i = 0; i < sizeof(usages) / sizeof(long); i++)
|
||||||
{
|
{
|
||||||
const long page = kHIDPage_GenericDesktop;
|
const long page = kHIDPage_GenericDesktop;
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ static GLFWbool modeIsGood(CGDisplayModeRef mode)
|
|||||||
// Convert Core Graphics display mode to GLFW video mode
|
// Convert Core Graphics display mode to GLFW video mode
|
||||||
//
|
//
|
||||||
static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
||||||
CVDisplayLinkRef link)
|
double fallbackRefreshRate)
|
||||||
{
|
{
|
||||||
GLFWvidmode result;
|
GLFWvidmode result;
|
||||||
result.width = (int) CGDisplayModeGetWidth(mode);
|
result.width = (int) CGDisplayModeGetWidth(mode);
|
||||||
@ -152,11 +152,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
|||||||
result.refreshRate = (int) round(CGDisplayModeGetRefreshRate(mode));
|
result.refreshRate = (int) round(CGDisplayModeGetRefreshRate(mode));
|
||||||
|
|
||||||
if (result.refreshRate == 0)
|
if (result.refreshRate == 0)
|
||||||
{
|
result.refreshRate = (int) round(fallbackRefreshRate);
|
||||||
const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
|
|
||||||
if (!(time.flags & kCVTimeIsIndefinite))
|
|
||||||
result.refreshRate = (int) (time.timeScale / (double) time.timeValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||||
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
||||||
@ -238,6 +234,68 @@ static GLFWbool refreshMonitorScreen(_GLFWmonitor* monitor)
|
|||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the display refresh rate queried from the I/O registry
|
||||||
|
//
|
||||||
|
static double getFallbackRefreshRate(CGDirectDisplayID displayID)
|
||||||
|
{
|
||||||
|
double refreshRate = 60.0;
|
||||||
|
|
||||||
|
io_iterator_t it;
|
||||||
|
io_service_t service;
|
||||||
|
|
||||||
|
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
|
||||||
|
IOServiceMatching("IOFramebuffer"),
|
||||||
|
&it) != 0)
|
||||||
|
{
|
||||||
|
return refreshRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((service = IOIteratorNext(it)) != 0)
|
||||||
|
{
|
||||||
|
const CFNumberRef indexRef =
|
||||||
|
IORegistryEntryCreateCFProperty(service,
|
||||||
|
CFSTR("IOFramebufferOpenGLIndex"),
|
||||||
|
kCFAllocatorDefault,
|
||||||
|
kNilOptions);
|
||||||
|
if (!indexRef)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint32_t index = 0;
|
||||||
|
CFNumberGetValue(indexRef, kCFNumberIntType, &index);
|
||||||
|
CFRelease(indexRef);
|
||||||
|
|
||||||
|
if (CGOpenGLDisplayMaskToDisplayID(1 << index) != displayID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const CFNumberRef clockRef =
|
||||||
|
IORegistryEntryCreateCFProperty(service,
|
||||||
|
CFSTR("IOFBCurrentPixelClock"),
|
||||||
|
kCFAllocatorDefault,
|
||||||
|
kNilOptions);
|
||||||
|
const CFNumberRef countRef =
|
||||||
|
IORegistryEntryCreateCFProperty(service,
|
||||||
|
CFSTR("IOFBCurrentPixelCount"),
|
||||||
|
kCFAllocatorDefault,
|
||||||
|
kNilOptions);
|
||||||
|
if (!clockRef || !countRef)
|
||||||
|
break;
|
||||||
|
|
||||||
|
uint32_t clock = 0, count = 0;
|
||||||
|
CFNumberGetValue(clockRef, kCFNumberIntType, &clock);
|
||||||
|
CFNumberGetValue(countRef, kCFNumberIntType, &count);
|
||||||
|
CFRelease(clockRef);
|
||||||
|
CFRelease(countRef);
|
||||||
|
|
||||||
|
if (clock > 0 && count > 0)
|
||||||
|
refreshRate = clock / (double) count;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOObjectRelease(it);
|
||||||
|
return refreshRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
@ -294,6 +352,11 @@ void _glfwPollMonitorsNS(void)
|
|||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
|
|
||||||
|
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displays[i]);
|
||||||
|
if (CGDisplayModeGetRefreshRate(mode) == 0.0)
|
||||||
|
monitor->ns.fallbackRefreshRate = getFallbackRefreshRate(displays[i]);
|
||||||
|
CGDisplayModeRelease(mode);
|
||||||
|
|
||||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,9 +381,6 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
|||||||
if (_glfwCompareVideoModes(¤t, best) == 0)
|
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CVDisplayLinkRef link;
|
|
||||||
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
|
||||||
|
|
||||||
CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
||||||
const CFIndex count = CFArrayGetCount(modes);
|
const CFIndex count = CFArrayGetCount(modes);
|
||||||
CGDisplayModeRef native = NULL;
|
CGDisplayModeRef native = NULL;
|
||||||
@ -331,7 +391,8 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
|||||||
if (!modeIsGood(dm))
|
if (!modeIsGood(dm))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
|
const GLFWvidmode mode =
|
||||||
|
vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
|
||||||
if (_glfwCompareVideoModes(best, &mode) == 0)
|
if (_glfwCompareVideoModes(best, &mode) == 0)
|
||||||
{
|
{
|
||||||
native = dm;
|
native = dm;
|
||||||
@ -350,7 +411,6 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CFRelease(modes);
|
CFRelease(modes);
|
||||||
CVDisplayLinkRelease(link);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the previously saved (original) video mode
|
// Restore the previously saved (original) video mode
|
||||||
@ -440,9 +500,6 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
|||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
CVDisplayLinkRef link;
|
|
||||||
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
|
||||||
|
|
||||||
CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
||||||
const CFIndex found = CFArrayGetCount(modes);
|
const CFIndex found = CFArrayGetCount(modes);
|
||||||
GLFWvidmode* result = calloc(found, sizeof(GLFWvidmode));
|
GLFWvidmode* result = calloc(found, sizeof(GLFWvidmode));
|
||||||
@ -453,7 +510,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
|||||||
if (!modeIsGood(dm))
|
if (!modeIsGood(dm))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
|
const GLFWvidmode mode =
|
||||||
|
vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
|
||||||
CFIndex j;
|
CFIndex j;
|
||||||
|
|
||||||
for (j = 0; j < *count; j++)
|
for (j = 0; j < *count; j++)
|
||||||
@ -471,7 +529,6 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CFRelease(modes);
|
CFRelease(modes);
|
||||||
CVDisplayLinkRelease(link);
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
} // autoreleasepool
|
} // autoreleasepool
|
||||||
@ -481,15 +538,10 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
|
|||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
|
||||||
CVDisplayLinkRef link;
|
|
||||||
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
|
||||||
|
|
||||||
CGDisplayModeRef native = CGDisplayCopyDisplayMode(monitor->ns.displayID);
|
CGDisplayModeRef native = CGDisplayCopyDisplayMode(monitor->ns.displayID);
|
||||||
*mode = vidmodeFromCGDisplayMode(native, link);
|
*mode = vidmodeFromCGDisplayMode(native, monitor->ns.fallbackRefreshRate);
|
||||||
CGDisplayModeRelease(native);
|
CGDisplayModeRelease(native);
|
||||||
|
|
||||||
CVDisplayLinkRelease(link);
|
|
||||||
|
|
||||||
} // autoreleasepool
|
} // autoreleasepool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,8 +28,6 @@
|
|||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
#include <Carbon/Carbon.h>
|
#include <Carbon/Carbon.h>
|
||||||
#include <CoreVideo/CVBase.h>
|
|
||||||
#include <CoreVideo/CVDisplayLink.h>
|
|
||||||
|
|
||||||
// NOTE: All of NSGL was deprecated in the 10.14 SDK
|
// NOTE: All of NSGL was deprecated in the 10.14 SDK
|
||||||
// This disables the pointless warnings for every symbol we use
|
// This disables the pointless warnings for every symbol we use
|
||||||
@ -63,6 +61,7 @@ typedef void* id;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
||||||
|
typedef VkFlags VkMetalSurfaceCreateFlagsEXT;
|
||||||
|
|
||||||
typedef struct VkMacOSSurfaceCreateInfoMVK
|
typedef struct VkMacOSSurfaceCreateInfoMVK
|
||||||
{
|
{
|
||||||
@ -72,7 +71,16 @@ typedef struct VkMacOSSurfaceCreateInfoMVK
|
|||||||
const void* pView;
|
const void* pView;
|
||||||
} VkMacOSSurfaceCreateInfoMVK;
|
} VkMacOSSurfaceCreateInfoMVK;
|
||||||
|
|
||||||
|
typedef struct VkMetalSurfaceCreateInfoEXT
|
||||||
|
{
|
||||||
|
VkStructureType sType;
|
||||||
|
const void* pNext;
|
||||||
|
VkMetalSurfaceCreateFlagsEXT flags;
|
||||||
|
const void* pLayer;
|
||||||
|
} VkMetalSurfaceCreateInfoEXT;
|
||||||
|
|
||||||
typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||||
|
typedef VkResult (APIENTRY *PFN_vkCreateMetalSurfaceEXT)(VkInstance,const VkMetalSurfaceCreateInfoEXT*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||||
|
|
||||||
#include "posix_thread.h"
|
#include "posix_thread.h"
|
||||||
#include "cocoa_joystick.h"
|
#include "cocoa_joystick.h"
|
||||||
@ -133,7 +141,6 @@ typedef struct _GLFWlibraryNS
|
|||||||
{
|
{
|
||||||
CGEventSourceRef eventSource;
|
CGEventSourceRef eventSource;
|
||||||
id delegate;
|
id delegate;
|
||||||
GLFWbool finishedLaunching;
|
|
||||||
GLFWbool cursorHidden;
|
GLFWbool cursorHidden;
|
||||||
TISInputSourceRef inputSource;
|
TISInputSourceRef inputSource;
|
||||||
IOHIDManagerRef hidManager;
|
IOHIDManagerRef hidManager;
|
||||||
@ -170,6 +177,7 @@ typedef struct _GLFWmonitorNS
|
|||||||
CGDisplayModeRef previousMode;
|
CGDisplayModeRef previousMode;
|
||||||
uint32_t unitNumber;
|
uint32_t unitNumber;
|
||||||
id screen;
|
id screen;
|
||||||
|
double fallbackRefreshRate;
|
||||||
|
|
||||||
} _GLFWmonitorNS;
|
} _GLFWmonitorNS;
|
||||||
|
|
||||||
@ -198,3 +206,5 @@ void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
|
|||||||
|
|
||||||
float _glfwTransformYNS(float y);
|
float _glfwTransformYNS(float y);
|
||||||
|
|
||||||
|
void* _glfwLoadLocalVulkanLoaderNS(void);
|
||||||
|
|
||||||
|
@ -322,12 +322,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
_glfwInputWindowFocus(window, GLFW_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)windowDidChangeScreen:(NSNotification *)notification
|
|
||||||
{
|
|
||||||
if (window->context.source == GLFW_NATIVE_CONTEXT_API)
|
|
||||||
_glfwUpdateDisplayLinkDisplayNSGL(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
@ -890,12 +884,6 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
|
||||||
if (!_glfw.ns.finishedLaunching)
|
|
||||||
{
|
|
||||||
[NSApp run];
|
|
||||||
_glfw.ns.finishedLaunching = GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!createNativeWindow(window, wndconfig, fbconfig))
|
if (!createNativeWindow(window, wndconfig, fbconfig))
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
@ -967,13 +955,14 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||||||
} // autoreleasepool
|
} // autoreleasepool
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char *title)
|
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[window->ns.object setTitle:@(title)];
|
NSString* string = @(title);
|
||||||
|
[window->ns.object setTitle:string];
|
||||||
// HACK: Set the miniwindow title explicitly as setTitle: doesn't update it
|
// HACK: Set the miniwindow title explicitly as setTitle: doesn't update it
|
||||||
// if the window lacks NSWindowStyleMaskTitled
|
// if the window lacks NSWindowStyleMaskTitled
|
||||||
[window->ns.object setMiniwindowTitle:@(title)];
|
[window->ns.object setMiniwindowTitle:string];
|
||||||
} // autoreleasepool
|
} // autoreleasepool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1512,6 +1501,13 @@ const char* _glfwPlatformGetScancodeName(int scancode)
|
|||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
|
||||||
|
if (scancode < 0 || scancode > 0xff ||
|
||||||
|
_glfw.ns.keycodes[scancode] == GLFW_KEY_UNKNOWN)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const int key = _glfw.ns.keycodes[scancode];
|
const int key = _glfw.ns.keycodes[scancode];
|
||||||
|
|
||||||
UInt32 deadKeyState = 0;
|
UInt32 deadKeyState = 0;
|
||||||
@ -1607,13 +1603,13 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
|||||||
|
|
||||||
// HACK: Try to use a private message
|
// HACK: Try to use a private message
|
||||||
if (shape == GLFW_RESIZE_EW_CURSOR)
|
if (shape == GLFW_RESIZE_EW_CURSOR)
|
||||||
cursorSelector = @selector(_windowResizeEastWestCursor);
|
cursorSelector = NSSelectorFromString(@"_windowResizeEastWestCursor");
|
||||||
else if (shape == GLFW_RESIZE_NS_CURSOR)
|
else if (shape == GLFW_RESIZE_NS_CURSOR)
|
||||||
cursorSelector = @selector(_windowResizeNorthSouthCursor);
|
cursorSelector = NSSelectorFromString(@"_windowResizeNorthSouthCursor");
|
||||||
else if (shape == GLFW_RESIZE_NWSE_CURSOR)
|
else if (shape == GLFW_RESIZE_NWSE_CURSOR)
|
||||||
cursorSelector = @selector(_windowResizeNorthWestSouthEastCursor);
|
cursorSelector = NSSelectorFromString(@"_windowResizeNorthWestSouthEastCursor");
|
||||||
else if (shape == GLFW_RESIZE_NESW_CURSOR)
|
else if (shape == GLFW_RESIZE_NESW_CURSOR)
|
||||||
cursorSelector = @selector(_windowResizeNorthEastSouthWestCursor);
|
cursorSelector = NSSelectorFromString(@"_windowResizeNorthEastSouthWestCursor");
|
||||||
|
|
||||||
if (cursorSelector && [NSCursor respondsToSelector:cursorSelector])
|
if (cursorSelector && [NSCursor respondsToSelector:cursorSelector])
|
||||||
{
|
{
|
||||||
@ -1711,11 +1707,16 @@ const char* _glfwPlatformGetClipboardString(void)
|
|||||||
|
|
||||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||||
{
|
{
|
||||||
if (!_glfw.vk.KHR_surface || !_glfw.vk.MVK_macos_surface)
|
if (_glfw.vk.KHR_surface && _glfw.vk.EXT_metal_surface)
|
||||||
return;
|
{
|
||||||
|
extensions[0] = "VK_KHR_surface";
|
||||||
extensions[0] = "VK_KHR_surface";
|
extensions[1] = "VK_EXT_metal_surface";
|
||||||
extensions[1] = "VK_MVK_macos_surface";
|
}
|
||||||
|
else if (_glfw.vk.KHR_surface && _glfw.vk.MVK_macos_surface)
|
||||||
|
{
|
||||||
|
extensions[0] = "VK_KHR_surface";
|
||||||
|
extensions[1] = "VK_MVK_macos_surface";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||||
@ -1733,19 +1734,6 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
|||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
|
||||||
VkResult err;
|
|
||||||
VkMacOSSurfaceCreateInfoMVK sci;
|
|
||||||
PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK;
|
|
||||||
|
|
||||||
vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK)
|
|
||||||
vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK");
|
|
||||||
if (!vkCreateMacOSSurfaceMVK)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"Cocoa: Vulkan instance missing VK_MVK_macos_surface extension");
|
|
||||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// HACK: Dynamically load Core Animation to avoid adding an extra
|
// HACK: Dynamically load Core Animation to avoid adding an extra
|
||||||
// dependency for the majority who don't use MoltenVK
|
// dependency for the majority who don't use MoltenVK
|
||||||
NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"];
|
NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"];
|
||||||
@ -1771,11 +1759,49 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
|||||||
[window->ns.view setLayer:window->ns.layer];
|
[window->ns.view setLayer:window->ns.layer];
|
||||||
[window->ns.view setWantsLayer:YES];
|
[window->ns.view setWantsLayer:YES];
|
||||||
|
|
||||||
memset(&sci, 0, sizeof(sci));
|
VkResult err;
|
||||||
sci.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
|
|
||||||
sci.pView = window->ns.view;
|
if (_glfw.vk.EXT_metal_surface)
|
||||||
|
{
|
||||||
|
VkMetalSurfaceCreateInfoEXT sci;
|
||||||
|
|
||||||
|
PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT;
|
||||||
|
vkCreateMetalSurfaceEXT = (PFN_vkCreateMetalSurfaceEXT)
|
||||||
|
vkGetInstanceProcAddr(instance, "vkCreateMetalSurfaceEXT");
|
||||||
|
if (!vkCreateMetalSurfaceEXT)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"Cocoa: Vulkan instance missing VK_EXT_metal_surface extension");
|
||||||
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&sci, 0, sizeof(sci));
|
||||||
|
sci.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
|
||||||
|
sci.pLayer = window->ns.layer;
|
||||||
|
|
||||||
|
err = vkCreateMetalSurfaceEXT(instance, &sci, allocator, surface);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VkMacOSSurfaceCreateInfoMVK sci;
|
||||||
|
|
||||||
|
PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK;
|
||||||
|
vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK)
|
||||||
|
vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK");
|
||||||
|
if (!vkCreateMacOSSurfaceMVK)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"Cocoa: Vulkan instance missing VK_MVK_macos_surface extension");
|
||||||
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&sci, 0, sizeof(sci));
|
||||||
|
sci.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
|
||||||
|
sci.pView = window->ns.view;
|
||||||
|
|
||||||
|
err = vkCreateMacOSSurfaceMVK(instance, &sci, allocator, surface);
|
||||||
|
}
|
||||||
|
|
||||||
err = vkCreateMacOSSurfaceMVK(instance, &sci, allocator, surface);
|
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
@ -123,23 +123,24 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
#if defined(_GLFW_X11)
|
#if defined(_GLFW_X11)
|
||||||
XVisualInfo vi = {0};
|
|
||||||
|
|
||||||
// Only consider EGLConfigs with associated Visuals
|
|
||||||
vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
|
|
||||||
if (!vi.visualid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (desired->transparent)
|
|
||||||
{
|
{
|
||||||
int count;
|
XVisualInfo vi = {0};
|
||||||
XVisualInfo* vis = XGetVisualInfo(_glfw.x11.display,
|
|
||||||
VisualIDMask, &vi,
|
// Only consider EGLConfigs with associated Visuals
|
||||||
&count);
|
vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
|
||||||
if (vis)
|
if (!vi.visualid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (desired->transparent)
|
||||||
{
|
{
|
||||||
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
|
int count;
|
||||||
XFree(vis);
|
XVisualInfo* vis =
|
||||||
|
XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count);
|
||||||
|
if (vis)
|
||||||
|
{
|
||||||
|
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
|
||||||
|
XFree(vis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // _GLFW_X11
|
#endif // _GLFW_X11
|
||||||
|
30
src/glfw.rc.in
Normal file
30
src/glfw.rc.in
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
#include <winver.h>
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION @GLFW_VERSION_MAJOR@,@GLFW_VERSION_MINOR@,@GLFW_VERSION_PATCH@,0
|
||||||
|
PRODUCTVERSION @GLFW_VERSION_MAJOR@,@GLFW_VERSION_MINOR@,@GLFW_VERSION_PATCH@,0
|
||||||
|
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||||
|
FILEFLAGS 0
|
||||||
|
FILEOS VOS_NT_WINDOWS32
|
||||||
|
FILETYPE VFT_DLL
|
||||||
|
FILESUBTYPE 0
|
||||||
|
{
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
{
|
||||||
|
BLOCK "040904B0"
|
||||||
|
{
|
||||||
|
VALUE "CompanyName", "GLFW"
|
||||||
|
VALUE "FileDescription", "GLFW @GLFW_VERSION@ DLL"
|
||||||
|
VALUE "FileVersion", "@GLFW_VERSION@"
|
||||||
|
VALUE "OriginalFilename", "glfw3.dll"
|
||||||
|
VALUE "ProductName", "GLFW"
|
||||||
|
VALUE "ProductVersion", "@GLFW_VERSION@"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
{
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
include("${CMAKE_CURRENT_LIST_DIR}/glfw3Targets.cmake")
|
|
@ -45,8 +45,6 @@
|
|||||||
// Define this to 1 if building GLFW for OSMesa
|
// Define this to 1 if building GLFW for OSMesa
|
||||||
#cmakedefine _GLFW_OSMESA
|
#cmakedefine _GLFW_OSMESA
|
||||||
|
|
||||||
// Define this to 1 if building as a shared library / dynamic library / DLL
|
|
||||||
#cmakedefine _GLFW_BUILD_DLL
|
|
||||||
// Define this to 1 to use Vulkan loader linked statically into application
|
// Define this to 1 to use Vulkan loader linked statically into application
|
||||||
#cmakedefine _GLFW_VULKAN_STATIC
|
#cmakedefine _GLFW_VULKAN_STATIC
|
||||||
|
|
||||||
|
@ -128,6 +128,7 @@ typedef enum VkStructureType
|
|||||||
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
||||||
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
||||||
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
|
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
|
||||||
|
VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000,
|
||||||
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
||||||
} VkStructureType;
|
} VkStructureType;
|
||||||
|
|
||||||
@ -559,6 +560,7 @@ struct _GLFWlibrary
|
|||||||
GLFWbool KHR_win32_surface;
|
GLFWbool KHR_win32_surface;
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
GLFWbool MVK_macos_surface;
|
GLFWbool MVK_macos_surface;
|
||||||
|
GLFWbool EXT_metal_surface;
|
||||||
#elif defined(_GLFW_X11)
|
#elif defined(_GLFW_X11)
|
||||||
GLFWbool KHR_xlib_surface;
|
GLFWbool KHR_xlib_surface;
|
||||||
GLFWbool KHR_xcb_surface;
|
GLFWbool KHR_xcb_surface;
|
||||||
|
@ -44,10 +44,6 @@ typedef struct _GLFWcontextNSGL
|
|||||||
{
|
{
|
||||||
id pixelFormat;
|
id pixelFormat;
|
||||||
id object;
|
id object;
|
||||||
CVDisplayLinkRef displayLink;
|
|
||||||
atomic_int swapInterval;
|
|
||||||
int swapIntervalsPassed;
|
|
||||||
id swapIntervalCond;
|
|
||||||
|
|
||||||
} _GLFWcontextNSGL;
|
} _GLFWcontextNSGL;
|
||||||
|
|
||||||
@ -67,5 +63,4 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
void _glfwDestroyContextNSGL(_GLFWwindow* window);
|
void _glfwDestroyContextNSGL(_GLFWwindow* window);
|
||||||
void _glfwUpdateDisplayLinkDisplayNSGL(_GLFWwindow* window);
|
|
||||||
|
|
||||||
|
@ -28,29 +28,8 @@
|
|||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
// Display link callback for manual swap interval implementation
|
#include <unistd.h>
|
||||||
// This is based on a similar workaround added to SDL2
|
#include <math.h>
|
||||||
//
|
|
||||||
static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink,
|
|
||||||
const CVTimeStamp* now,
|
|
||||||
const CVTimeStamp* outputTime,
|
|
||||||
CVOptionFlags flagsIn,
|
|
||||||
CVOptionFlags* flagsOut,
|
|
||||||
void* userInfo)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = (_GLFWwindow *) userInfo;
|
|
||||||
|
|
||||||
const int interval = atomic_load(&window->context.nsgl.swapInterval);
|
|
||||||
if (interval > 0)
|
|
||||||
{
|
|
||||||
[window->context.nsgl.swapIntervalCond lock];
|
|
||||||
window->context.nsgl.swapIntervalsPassed++;
|
|
||||||
[window->context.nsgl.swapIntervalCond signal];
|
|
||||||
[window->context.nsgl.swapIntervalCond unlock];
|
|
||||||
}
|
|
||||||
|
|
||||||
return kCVReturnSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void makeContextCurrentNSGL(_GLFWwindow* window)
|
static void makeContextCurrentNSGL(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
@ -70,19 +49,28 @@ static void swapBuffersNSGL(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
|
||||||
const int interval = atomic_load(&window->context.nsgl.swapInterval);
|
// HACK: Simulate vsync with usleep as NSGL swap interval does not apply to
|
||||||
if (interval > 0)
|
// windows with a non-visible occlusion state
|
||||||
|
if (!([window->ns.object occlusionState] & NSWindowOcclusionStateVisible))
|
||||||
{
|
{
|
||||||
[window->context.nsgl.swapIntervalCond lock];
|
int interval = 0;
|
||||||
do
|
[window->context.nsgl.object getValues:&interval
|
||||||
|
forParameter:NSOpenGLContextParameterSwapInterval];
|
||||||
|
|
||||||
|
if (interval > 0)
|
||||||
{
|
{
|
||||||
[window->context.nsgl.swapIntervalCond wait];
|
const double framerate = 60.0;
|
||||||
} while (window->context.nsgl.swapIntervalsPassed % interval != 0);
|
const uint64_t frequency = _glfwPlatformGetTimerFrequency();
|
||||||
window->context.nsgl.swapIntervalsPassed = 0;
|
const uint64_t value = _glfwPlatformGetTimerValue();
|
||||||
[window->context.nsgl.swapIntervalCond unlock];
|
|
||||||
|
const double elapsed = value / (double) frequency;
|
||||||
|
const double period = 1.0 / framerate;
|
||||||
|
const double delay = period - fmod(elapsed, period);
|
||||||
|
|
||||||
|
usleep(floorl(delay * 1e6));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ARP appears to be unnecessary, but this is future-proof
|
|
||||||
[window->context.nsgl.object flushBuffer];
|
[window->context.nsgl.object flushBuffer];
|
||||||
|
|
||||||
} // autoreleasepool
|
} // autoreleasepool
|
||||||
@ -91,11 +79,14 @@ static void swapBuffersNSGL(_GLFWwindow* window)
|
|||||||
static void swapIntervalNSGL(int interval)
|
static void swapIntervalNSGL(int interval)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
|
||||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
atomic_store(&window->context.nsgl.swapInterval, interval);
|
if (window)
|
||||||
[window->context.nsgl.swapIntervalCond lock];
|
{
|
||||||
window->context.nsgl.swapIntervalsPassed = 0;
|
[window->context.nsgl.object setValues:&interval
|
||||||
[window->context.nsgl.swapIntervalCond unlock];
|
forParameter:NSOpenGLContextParameterSwapInterval];
|
||||||
|
}
|
||||||
|
|
||||||
} // autoreleasepool
|
} // autoreleasepool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,17 +114,6 @@ static void destroyContextNSGL(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
|
||||||
if (window->context.nsgl.displayLink)
|
|
||||||
{
|
|
||||||
if (CVDisplayLinkIsRunning(window->context.nsgl.displayLink))
|
|
||||||
CVDisplayLinkStop(window->context.nsgl.displayLink);
|
|
||||||
|
|
||||||
CVDisplayLinkRelease(window->context.nsgl.displayLink);
|
|
||||||
}
|
|
||||||
|
|
||||||
[window->context.nsgl.swapIntervalCond release];
|
|
||||||
window->context.nsgl.swapIntervalCond = nil;
|
|
||||||
|
|
||||||
[window->context.nsgl.pixelFormat release];
|
[window->context.nsgl.pixelFormat release];
|
||||||
window->context.nsgl.pixelFormat = nil;
|
window->context.nsgl.pixelFormat = nil;
|
||||||
|
|
||||||
@ -354,17 +334,10 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
forParameter:NSOpenGLContextParameterSurfaceOpacity];
|
forParameter:NSOpenGLContextParameterSurfaceOpacity];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->ns.retina)
|
[window->ns.view setWantsBestResolutionOpenGLSurface:window->ns.retina];
|
||||||
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
|
||||||
|
|
||||||
GLint interval = 0;
|
|
||||||
[window->context.nsgl.object setValues:&interval
|
|
||||||
forParameter:NSOpenGLContextParameterSwapInterval];
|
|
||||||
|
|
||||||
[window->context.nsgl.object setView:window->ns.view];
|
[window->context.nsgl.object setView:window->ns.view];
|
||||||
|
|
||||||
window->context.nsgl.swapIntervalCond = [NSCondition new];
|
|
||||||
|
|
||||||
window->context.makeCurrent = makeContextCurrentNSGL;
|
window->context.makeCurrent = makeContextCurrentNSGL;
|
||||||
window->context.swapBuffers = swapBuffersNSGL;
|
window->context.swapBuffers = swapBuffersNSGL;
|
||||||
window->context.swapInterval = swapIntervalNSGL;
|
window->context.swapInterval = swapIntervalNSGL;
|
||||||
@ -372,26 +345,9 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
window->context.getProcAddress = getProcAddressNSGL;
|
window->context.getProcAddress = getProcAddressNSGL;
|
||||||
window->context.destroy = destroyContextNSGL;
|
window->context.destroy = destroyContextNSGL;
|
||||||
|
|
||||||
CVDisplayLinkCreateWithActiveCGDisplays(&window->context.nsgl.displayLink);
|
|
||||||
CVDisplayLinkSetOutputCallback(window->context.nsgl.displayLink,
|
|
||||||
&displayLinkCallback,
|
|
||||||
window);
|
|
||||||
CVDisplayLinkStart(window->context.nsgl.displayLink);
|
|
||||||
|
|
||||||
_glfwUpdateDisplayLinkDisplayNSGL(window);
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwUpdateDisplayLinkDisplayNSGL(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
CGDirectDisplayID displayID =
|
|
||||||
[[[window->ns.object screen] deviceDescription][@"NSScreenNumber"] unsignedIntValue];
|
|
||||||
if (!displayID)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CVDisplayLinkSetCurrentCGDisplay(window->context.nsgl.displayLink, displayID);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW native API //////
|
////// GLFW native API //////
|
||||||
|
@ -27,8 +27,11 @@
|
|||||||
// It is fine to use C99 in this file because it will not be built with VS
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
|
#define _POSIX_C_SOURCE 199309L
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
@ -41,7 +44,7 @@
|
|||||||
//
|
//
|
||||||
void _glfwInitTimerPOSIX(void)
|
void _glfwInitTimerPOSIX(void)
|
||||||
{
|
{
|
||||||
#if defined(CLOCK_MONOTONIC)
|
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
||||||
@ -64,7 +67,7 @@ void _glfwInitTimerPOSIX(void)
|
|||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerValue(void)
|
uint64_t _glfwPlatformGetTimerValue(void)
|
||||||
{
|
{
|
||||||
#if defined(CLOCK_MONOTONIC)
|
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
||||||
if (_glfw.timer.posix.monotonic)
|
if (_glfw.timer.posix.monotonic)
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
@ -57,6 +57,8 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||||||
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
|
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
|
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
|
||||||
|
if (!_glfw.vk.handle)
|
||||||
|
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
|
||||||
#else
|
#else
|
||||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
||||||
#endif
|
#endif
|
||||||
@ -130,6 +132,8 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
|
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
|
||||||
_glfw.vk.MVK_macos_surface = GLFW_TRUE;
|
_glfw.vk.MVK_macos_surface = GLFW_TRUE;
|
||||||
|
else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0)
|
||||||
|
_glfw.vk.EXT_metal_surface = GLFW_TRUE;
|
||||||
#elif defined(_GLFW_X11)
|
#elif defined(_GLFW_X11)
|
||||||
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
||||||
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
|
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
|
||||||
|
@ -104,10 +104,6 @@ typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
|
|||||||
#define wglMakeCurrent _glfw.wgl.MakeCurrent
|
#define wglMakeCurrent _glfw.wgl.MakeCurrent
|
||||||
#define wglShareLists _glfw.wgl.ShareLists
|
#define wglShareLists _glfw.wgl.ShareLists
|
||||||
|
|
||||||
#define _GLFW_RECREATION_NOT_NEEDED 0
|
|
||||||
#define _GLFW_RECREATION_REQUIRED 1
|
|
||||||
#define _GLFW_RECREATION_IMPOSSIBLE 2
|
|
||||||
|
|
||||||
#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
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
|
|
||||||
// Callback for EnumDisplayMonitors in createMonitor
|
// Callback for EnumDisplayMonitors in createMonitor
|
||||||
|
@ -36,8 +36,6 @@
|
|||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
|
||||||
#define _GLFW_KEY_INVALID -2
|
|
||||||
|
|
||||||
// Returns the window style for the specified window
|
// Returns the window style for the specified window
|
||||||
//
|
//
|
||||||
static DWORD getWindowStyle(const _GLFWwindow* window)
|
static DWORD getWindowStyle(const _GLFWwindow* window)
|
||||||
@ -448,77 +446,6 @@ static int getKeyMods(void)
|
|||||||
return mods;
|
return mods;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieves and translates modifier keys
|
|
||||||
//
|
|
||||||
static int getAsyncKeyMods(void)
|
|
||||||
{
|
|
||||||
int mods = 0;
|
|
||||||
|
|
||||||
if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
|
|
||||||
mods |= GLFW_MOD_SHIFT;
|
|
||||||
if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
|
|
||||||
mods |= GLFW_MOD_CONTROL;
|
|
||||||
if (GetAsyncKeyState(VK_MENU) & 0x8000)
|
|
||||||
mods |= GLFW_MOD_ALT;
|
|
||||||
if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) & 0x8000)
|
|
||||||
mods |= GLFW_MOD_SUPER;
|
|
||||||
if (GetAsyncKeyState(VK_CAPITAL) & 1)
|
|
||||||
mods |= GLFW_MOD_CAPS_LOCK;
|
|
||||||
if (GetAsyncKeyState(VK_NUMLOCK) & 1)
|
|
||||||
mods |= GLFW_MOD_NUM_LOCK;
|
|
||||||
|
|
||||||
return mods;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Translates a Windows key to the corresponding GLFW key
|
|
||||||
//
|
|
||||||
static int translateKey(WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
// The Ctrl keys require special handling
|
|
||||||
if (wParam == VK_CONTROL)
|
|
||||||
{
|
|
||||||
MSG next;
|
|
||||||
DWORD time;
|
|
||||||
|
|
||||||
// Right side keys have the extended key bit set
|
|
||||||
if (HIWORD(lParam) & KF_EXTENDED)
|
|
||||||
return GLFW_KEY_RIGHT_CONTROL;
|
|
||||||
|
|
||||||
// HACK: Alt Gr sends Left Ctrl and then Right Alt in close sequence
|
|
||||||
// We only want the Right Alt message, so if the next message is
|
|
||||||
// Right Alt we ignore this (synthetic) Left Ctrl message
|
|
||||||
time = GetMessageTime();
|
|
||||||
|
|
||||||
if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))
|
|
||||||
{
|
|
||||||
if (next.message == WM_KEYDOWN ||
|
|
||||||
next.message == WM_SYSKEYDOWN ||
|
|
||||||
next.message == WM_KEYUP ||
|
|
||||||
next.message == WM_SYSKEYUP)
|
|
||||||
{
|
|
||||||
if (next.wParam == VK_MENU &&
|
|
||||||
(HIWORD(next.lParam) & KF_EXTENDED) &&
|
|
||||||
next.time == time)
|
|
||||||
{
|
|
||||||
// Next message is Right Alt down so discard this
|
|
||||||
return _GLFW_KEY_INVALID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_KEY_LEFT_CONTROL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wParam == VK_PROCESSKEY)
|
|
||||||
{
|
|
||||||
// IME notifies that keys have been filtered by setting the virtual
|
|
||||||
// key-code to VK_PROCESSKEY
|
|
||||||
return _GLFW_KEY_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _glfw.win32.keycodes[HIWORD(lParam) & 0x1FF];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fitToMonitor(_GLFWwindow* window)
|
static void fitToMonitor(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
MONITORINFO mi = { sizeof(mi) };
|
MONITORINFO mi = { sizeof(mi) };
|
||||||
@ -748,13 +675,64 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
case WM_KEYUP:
|
case WM_KEYUP:
|
||||||
case WM_SYSKEYUP:
|
case WM_SYSKEYUP:
|
||||||
{
|
{
|
||||||
const int key = translateKey(wParam, lParam);
|
int key, scancode;
|
||||||
const int scancode = (HIWORD(lParam) & 0x1ff);
|
|
||||||
const int action = (HIWORD(lParam) & KF_UP) ? GLFW_RELEASE : GLFW_PRESS;
|
const int action = (HIWORD(lParam) & KF_UP) ? GLFW_RELEASE : GLFW_PRESS;
|
||||||
const int mods = getKeyMods();
|
const int mods = getKeyMods();
|
||||||
|
|
||||||
if (key == _GLFW_KEY_INVALID)
|
scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff));
|
||||||
|
if (!scancode)
|
||||||
|
{
|
||||||
|
// NOTE: Some synthetic key messages have a scancode of zero
|
||||||
|
// HACK: Map the virtual key back to a usable scancode
|
||||||
|
scancode = MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC);
|
||||||
|
}
|
||||||
|
|
||||||
|
key = _glfw.win32.keycodes[scancode];
|
||||||
|
|
||||||
|
// The Ctrl keys require special handling
|
||||||
|
if (wParam == VK_CONTROL)
|
||||||
|
{
|
||||||
|
if (HIWORD(lParam) & KF_EXTENDED)
|
||||||
|
{
|
||||||
|
// Right side keys have the extended key bit set
|
||||||
|
key = GLFW_KEY_RIGHT_CONTROL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: Alt Gr sends Left Ctrl followed by Right Alt
|
||||||
|
// HACK: We only want one event for Alt Gr, so if we detect
|
||||||
|
// this sequence we discard this Left Ctrl message now
|
||||||
|
// and later report Right Alt normally
|
||||||
|
MSG next;
|
||||||
|
const DWORD time = GetMessageTime();
|
||||||
|
|
||||||
|
if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))
|
||||||
|
{
|
||||||
|
if (next.message == WM_KEYDOWN ||
|
||||||
|
next.message == WM_SYSKEYDOWN ||
|
||||||
|
next.message == WM_KEYUP ||
|
||||||
|
next.message == WM_SYSKEYUP)
|
||||||
|
{
|
||||||
|
if (next.wParam == VK_MENU &&
|
||||||
|
(HIWORD(next.lParam) & KF_EXTENDED) &&
|
||||||
|
next.time == time)
|
||||||
|
{
|
||||||
|
// Next message is Right Alt down so discard this
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a regular Left Ctrl message
|
||||||
|
key = GLFW_KEY_LEFT_CONTROL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (wParam == VK_PROCESSKEY)
|
||||||
|
{
|
||||||
|
// IME notifies that keys have been filtered by setting the
|
||||||
|
// virtual key-code to VK_PROCESSKEY
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (action == GLFW_RELEASE && wParam == VK_SHIFT)
|
if (action == GLFW_RELEASE && wParam == VK_SHIFT)
|
||||||
{
|
{
|
||||||
@ -1934,30 +1912,40 @@ void _glfwPlatformPollEvents(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HACK: Release modifier keys that the system did not emit KEYUP for
|
||||||
|
// NOTE: Shift keys on Windows tend to "stick" when both are pressed as
|
||||||
|
// no key up message is generated by the first key release
|
||||||
|
// NOTE: Windows key is not reported as released by the Win+V hotkey
|
||||||
|
// Other Win hotkeys are handled implicitly by _glfwInputWindowFocus
|
||||||
|
// because they change the input focus
|
||||||
|
// NOTE: The other half of this is in the WM_*KEY* handler in windowProc
|
||||||
handle = GetActiveWindow();
|
handle = GetActiveWindow();
|
||||||
if (handle)
|
if (handle)
|
||||||
{
|
{
|
||||||
// NOTE: Shift keys on Windows tend to "stick" when both are pressed as
|
|
||||||
// no key up message is generated by the first key release
|
|
||||||
// The other half of this is in the handling of WM_KEYUP
|
|
||||||
// HACK: Query actual key state and synthesize release events as needed
|
|
||||||
window = GetPropW(handle, L"GLFW");
|
window = GetPropW(handle, L"GLFW");
|
||||||
if (window)
|
if (window)
|
||||||
{
|
{
|
||||||
const GLFWbool lshift = (GetAsyncKeyState(VK_LSHIFT) & 0x8000) != 0;
|
int i;
|
||||||
const GLFWbool rshift = (GetAsyncKeyState(VK_RSHIFT) & 0x8000) != 0;
|
const int keys[4][2] =
|
||||||
|
{
|
||||||
|
{ VK_LSHIFT, GLFW_KEY_LEFT_SHIFT },
|
||||||
|
{ VK_RSHIFT, GLFW_KEY_RIGHT_SHIFT },
|
||||||
|
{ VK_LWIN, GLFW_KEY_LEFT_SUPER },
|
||||||
|
{ VK_RWIN, GLFW_KEY_RIGHT_SUPER }
|
||||||
|
};
|
||||||
|
|
||||||
if (!lshift && window->keys[GLFW_KEY_LEFT_SHIFT] == GLFW_PRESS)
|
for (i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
const int mods = getAsyncKeyMods();
|
const int vk = keys[i][0];
|
||||||
const int scancode = _glfw.win32.scancodes[GLFW_KEY_LEFT_SHIFT];
|
const int key = keys[i][1];
|
||||||
_glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, GLFW_RELEASE, mods);
|
const int scancode = _glfw.win32.scancodes[key];
|
||||||
}
|
|
||||||
else if (!rshift && window->keys[GLFW_KEY_RIGHT_SHIFT] == GLFW_PRESS)
|
if ((GetKeyState(vk) & 0x8000))
|
||||||
{
|
continue;
|
||||||
const int mods = getAsyncKeyMods();
|
if (window->keys[key] != GLFW_PRESS)
|
||||||
const int scancode = _glfw.win32.scancodes[GLFW_KEY_RIGHT_SHIFT];
|
continue;
|
||||||
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, GLFW_RELEASE, mods);
|
|
||||||
|
_glfwInputKey(window, key, scancode, GLFW_RELEASE, getKeyMods());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2039,6 +2027,13 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
|||||||
|
|
||||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||||
{
|
{
|
||||||
|
if (scancode < 0 || scancode > (KF_EXTENDED | 0xff) ||
|
||||||
|
_glfw.win32.keycodes[scancode] == GLFW_KEY_UNKNOWN)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return _glfw.win32.keynames[_glfw.win32.keycodes[scancode]];
|
return _glfw.win32.keynames[_glfw.win32.keycodes[scancode]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
// It is fine to use C99 in this file because it will not be built with VS
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
|
#define _POSIX_C_SOURCE 199309L
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -38,6 +40,7 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/timerfd.h>
|
#include <sys/timerfd.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
|
||||||
@ -125,6 +128,7 @@ static void pointerHandleLeave(void* data,
|
|||||||
_glfw.wl.serial = serial;
|
_glfw.wl.serial = serial;
|
||||||
_glfw.wl.pointerFocus = NULL;
|
_glfw.wl.pointerFocus = NULL;
|
||||||
_glfwInputCursorEnter(window, GLFW_FALSE);
|
_glfwInputCursorEnter(window, GLFW_FALSE);
|
||||||
|
_glfw.wl.cursorPreviousName = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setCursor(_GLFWwindow* window, const char* name)
|
static void setCursor(_GLFWwindow* window, const char* name)
|
||||||
@ -196,6 +200,7 @@ static void pointerHandleMotion(void* data,
|
|||||||
window->wl.cursorPosX = x;
|
window->wl.cursorPosX = x;
|
||||||
window->wl.cursorPosY = y;
|
window->wl.cursorPosY = y;
|
||||||
_glfwInputCursorPos(window, x, y);
|
_glfwInputCursorPos(window, x, y);
|
||||||
|
_glfw.wl.cursorPreviousName = NULL;
|
||||||
return;
|
return;
|
||||||
case topDecoration:
|
case topDecoration:
|
||||||
if (y < _GLFW_DECORATION_WIDTH)
|
if (y < _GLFW_DECORATION_WIDTH)
|
||||||
|
576
src/x11_init.c
576
src/x11_init.c
@ -29,33 +29,23 @@
|
|||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#include <X11/Xresource.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
// Translate an X11 key code to a GLFW key code.
|
// Translate the X11 KeySyms for a key to a GLFW key code
|
||||||
|
// NOTE: This is only used as a fallback, in case the XKB method fails
|
||||||
|
// It is layout-dependent and will fail partially on most non-US layouts
|
||||||
//
|
//
|
||||||
static int translateKeyCode(int scancode)
|
static int translateKeySyms(const KeySym* keysyms, int width)
|
||||||
{
|
{
|
||||||
int keySym;
|
if (width > 1)
|
||||||
|
|
||||||
// Valid key code range is [8,255], according to the Xlib manual
|
|
||||||
if (scancode < 8 || scancode > 255)
|
|
||||||
return GLFW_KEY_UNKNOWN;
|
|
||||||
|
|
||||||
if (_glfw.x11.xkb.available)
|
|
||||||
{
|
{
|
||||||
// Try secondary keysym, for numeric keypad keys
|
switch (keysyms[1])
|
||||||
// Note: This way we always force "NumLock = ON", which is intentional
|
|
||||||
// since the returned key code should correspond to a physical
|
|
||||||
// location.
|
|
||||||
keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 1);
|
|
||||||
switch (keySym)
|
|
||||||
{
|
{
|
||||||
case XK_KP_0: return GLFW_KEY_KP_0;
|
case XK_KP_0: return GLFW_KEY_KP_0;
|
||||||
case XK_KP_1: return GLFW_KEY_KP_1;
|
case XK_KP_1: return GLFW_KEY_KP_1;
|
||||||
@ -73,22 +63,9 @@ static int translateKeyCode(int scancode)
|
|||||||
case XK_KP_Enter: return GLFW_KEY_KP_ENTER;
|
case XK_KP_Enter: return GLFW_KEY_KP_ENTER;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now try primary keysym for function keys (non-printable keys)
|
|
||||||
// These should not depend on the current keyboard layout
|
|
||||||
keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int dummy;
|
|
||||||
KeySym* keySyms;
|
|
||||||
|
|
||||||
keySyms = XGetKeyboardMapping(_glfw.x11.display, scancode, 1, &dummy);
|
|
||||||
keySym = keySyms[0];
|
|
||||||
XFree(keySyms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (keySym)
|
switch (keysyms[0])
|
||||||
{
|
{
|
||||||
case XK_Escape: return GLFW_KEY_ESCAPE;
|
case XK_Escape: return GLFW_KEY_ESCAPE;
|
||||||
case XK_Tab: return GLFW_KEY_TAB;
|
case XK_Tab: return GLFW_KEY_TAB;
|
||||||
@ -232,7 +209,7 @@ static int translateKeyCode(int scancode)
|
|||||||
//
|
//
|
||||||
static void createKeyTables(void)
|
static void createKeyTables(void)
|
||||||
{
|
{
|
||||||
int scancode, key;
|
int scancode, scancodeMin, scancodeMax;
|
||||||
|
|
||||||
memset(_glfw.x11.keycodes, -1, sizeof(_glfw.x11.keycodes));
|
memset(_glfw.x11.keycodes, -1, sizeof(_glfw.x11.keycodes));
|
||||||
memset(_glfw.x11.scancodes, -1, sizeof(_glfw.x11.scancodes));
|
memset(_glfw.x11.scancodes, -1, sizeof(_glfw.x11.scancodes));
|
||||||
@ -242,89 +219,217 @@ static void createKeyTables(void)
|
|||||||
// Use XKB to determine physical key locations independently of the
|
// Use XKB to determine physical key locations independently of the
|
||||||
// current keyboard layout
|
// current keyboard layout
|
||||||
|
|
||||||
char name[XkbKeyNameLength + 1];
|
|
||||||
XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);
|
XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);
|
||||||
XkbGetNames(_glfw.x11.display, XkbKeyNamesMask, desc);
|
XkbGetNames(_glfw.x11.display, XkbKeyNamesMask | XkbKeyAliasesMask, desc);
|
||||||
|
|
||||||
|
scancodeMin = desc->min_key_code;
|
||||||
|
scancodeMax = desc->max_key_code;
|
||||||
|
|
||||||
|
const struct
|
||||||
|
{
|
||||||
|
int key;
|
||||||
|
char* name;
|
||||||
|
} keymap[] =
|
||||||
|
{
|
||||||
|
{ GLFW_KEY_GRAVE_ACCENT, "TLDE" },
|
||||||
|
{ GLFW_KEY_1, "AE01" },
|
||||||
|
{ GLFW_KEY_2, "AE02" },
|
||||||
|
{ GLFW_KEY_3, "AE03" },
|
||||||
|
{ GLFW_KEY_4, "AE04" },
|
||||||
|
{ GLFW_KEY_5, "AE05" },
|
||||||
|
{ GLFW_KEY_6, "AE06" },
|
||||||
|
{ GLFW_KEY_7, "AE07" },
|
||||||
|
{ GLFW_KEY_8, "AE08" },
|
||||||
|
{ GLFW_KEY_9, "AE09" },
|
||||||
|
{ GLFW_KEY_0, "AE10" },
|
||||||
|
{ GLFW_KEY_MINUS, "AE11" },
|
||||||
|
{ GLFW_KEY_EQUAL, "AE12" },
|
||||||
|
{ GLFW_KEY_Q, "AD01" },
|
||||||
|
{ GLFW_KEY_W, "AD02" },
|
||||||
|
{ GLFW_KEY_E, "AD03" },
|
||||||
|
{ GLFW_KEY_R, "AD04" },
|
||||||
|
{ GLFW_KEY_T, "AD05" },
|
||||||
|
{ GLFW_KEY_Y, "AD06" },
|
||||||
|
{ GLFW_KEY_U, "AD07" },
|
||||||
|
{ GLFW_KEY_I, "AD08" },
|
||||||
|
{ GLFW_KEY_O, "AD09" },
|
||||||
|
{ GLFW_KEY_P, "AD10" },
|
||||||
|
{ GLFW_KEY_LEFT_BRACKET, "AD11" },
|
||||||
|
{ GLFW_KEY_RIGHT_BRACKET, "AD12" },
|
||||||
|
{ GLFW_KEY_A, "AC01" },
|
||||||
|
{ GLFW_KEY_S, "AC02" },
|
||||||
|
{ GLFW_KEY_D, "AC03" },
|
||||||
|
{ GLFW_KEY_F, "AC04" },
|
||||||
|
{ GLFW_KEY_G, "AC05" },
|
||||||
|
{ GLFW_KEY_H, "AC06" },
|
||||||
|
{ GLFW_KEY_J, "AC07" },
|
||||||
|
{ GLFW_KEY_K, "AC08" },
|
||||||
|
{ GLFW_KEY_L, "AC09" },
|
||||||
|
{ GLFW_KEY_SEMICOLON, "AC10" },
|
||||||
|
{ GLFW_KEY_APOSTROPHE, "AC11" },
|
||||||
|
{ GLFW_KEY_Z, "AB01" },
|
||||||
|
{ GLFW_KEY_X, "AB02" },
|
||||||
|
{ GLFW_KEY_C, "AB03" },
|
||||||
|
{ GLFW_KEY_V, "AB04" },
|
||||||
|
{ GLFW_KEY_B, "AB05" },
|
||||||
|
{ GLFW_KEY_N, "AB06" },
|
||||||
|
{ GLFW_KEY_M, "AB07" },
|
||||||
|
{ GLFW_KEY_COMMA, "AB08" },
|
||||||
|
{ GLFW_KEY_PERIOD, "AB09" },
|
||||||
|
{ GLFW_KEY_SLASH, "AB10" },
|
||||||
|
{ GLFW_KEY_BACKSLASH, "BKSL" },
|
||||||
|
{ GLFW_KEY_WORLD_1, "LSGT" },
|
||||||
|
{ GLFW_KEY_SPACE, "SPCE" },
|
||||||
|
{ GLFW_KEY_ESCAPE, "ESC" },
|
||||||
|
{ GLFW_KEY_ENTER, "RTRN" },
|
||||||
|
{ GLFW_KEY_TAB, "TAB" },
|
||||||
|
{ GLFW_KEY_BACKSPACE, "BKSP" },
|
||||||
|
{ GLFW_KEY_INSERT, "INS" },
|
||||||
|
{ GLFW_KEY_DELETE, "DELE" },
|
||||||
|
{ GLFW_KEY_RIGHT, "RGHT" },
|
||||||
|
{ GLFW_KEY_LEFT, "LEFT" },
|
||||||
|
{ GLFW_KEY_DOWN, "DOWN" },
|
||||||
|
{ GLFW_KEY_UP, "UP" },
|
||||||
|
{ GLFW_KEY_PAGE_UP, "PGUP" },
|
||||||
|
{ GLFW_KEY_PAGE_DOWN, "PGDN" },
|
||||||
|
{ GLFW_KEY_HOME, "HOME" },
|
||||||
|
{ GLFW_KEY_END, "END" },
|
||||||
|
{ GLFW_KEY_CAPS_LOCK, "CAPS" },
|
||||||
|
{ GLFW_KEY_SCROLL_LOCK, "SCLK" },
|
||||||
|
{ GLFW_KEY_NUM_LOCK, "NMLK" },
|
||||||
|
{ GLFW_KEY_PRINT_SCREEN, "PRSC" },
|
||||||
|
{ GLFW_KEY_PAUSE, "PAUS" },
|
||||||
|
{ GLFW_KEY_F1, "FK01" },
|
||||||
|
{ GLFW_KEY_F2, "FK02" },
|
||||||
|
{ GLFW_KEY_F3, "FK03" },
|
||||||
|
{ GLFW_KEY_F4, "FK04" },
|
||||||
|
{ GLFW_KEY_F5, "FK05" },
|
||||||
|
{ GLFW_KEY_F6, "FK06" },
|
||||||
|
{ GLFW_KEY_F7, "FK07" },
|
||||||
|
{ GLFW_KEY_F8, "FK08" },
|
||||||
|
{ GLFW_KEY_F9, "FK09" },
|
||||||
|
{ GLFW_KEY_F10, "FK10" },
|
||||||
|
{ GLFW_KEY_F11, "FK11" },
|
||||||
|
{ GLFW_KEY_F12, "FK12" },
|
||||||
|
{ GLFW_KEY_F13, "FK13" },
|
||||||
|
{ GLFW_KEY_F14, "FK14" },
|
||||||
|
{ GLFW_KEY_F15, "FK15" },
|
||||||
|
{ GLFW_KEY_F16, "FK16" },
|
||||||
|
{ GLFW_KEY_F17, "FK17" },
|
||||||
|
{ GLFW_KEY_F18, "FK18" },
|
||||||
|
{ GLFW_KEY_F19, "FK19" },
|
||||||
|
{ GLFW_KEY_F20, "FK20" },
|
||||||
|
{ GLFW_KEY_F21, "FK21" },
|
||||||
|
{ GLFW_KEY_F22, "FK22" },
|
||||||
|
{ GLFW_KEY_F23, "FK23" },
|
||||||
|
{ GLFW_KEY_F24, "FK24" },
|
||||||
|
{ GLFW_KEY_F25, "FK25" },
|
||||||
|
{ GLFW_KEY_KP_0, "KP0" },
|
||||||
|
{ GLFW_KEY_KP_1, "KP1" },
|
||||||
|
{ GLFW_KEY_KP_2, "KP2" },
|
||||||
|
{ GLFW_KEY_KP_3, "KP3" },
|
||||||
|
{ GLFW_KEY_KP_4, "KP4" },
|
||||||
|
{ GLFW_KEY_KP_5, "KP5" },
|
||||||
|
{ GLFW_KEY_KP_6, "KP6" },
|
||||||
|
{ GLFW_KEY_KP_7, "KP7" },
|
||||||
|
{ GLFW_KEY_KP_8, "KP8" },
|
||||||
|
{ GLFW_KEY_KP_9, "KP9" },
|
||||||
|
{ GLFW_KEY_KP_DECIMAL, "KPDL" },
|
||||||
|
{ GLFW_KEY_KP_DIVIDE, "KPDV" },
|
||||||
|
{ GLFW_KEY_KP_MULTIPLY, "KPMU" },
|
||||||
|
{ GLFW_KEY_KP_SUBTRACT, "KPSU" },
|
||||||
|
{ GLFW_KEY_KP_ADD, "KPAD" },
|
||||||
|
{ GLFW_KEY_KP_ENTER, "KPEN" },
|
||||||
|
{ GLFW_KEY_KP_EQUAL, "KPEQ" },
|
||||||
|
{ GLFW_KEY_LEFT_SHIFT, "LFSH" },
|
||||||
|
{ GLFW_KEY_LEFT_CONTROL, "LCTL" },
|
||||||
|
{ GLFW_KEY_LEFT_ALT, "LALT" },
|
||||||
|
{ GLFW_KEY_LEFT_SUPER, "LWIN" },
|
||||||
|
{ GLFW_KEY_RIGHT_SHIFT, "RTSH" },
|
||||||
|
{ GLFW_KEY_RIGHT_CONTROL, "RCTL" },
|
||||||
|
{ GLFW_KEY_RIGHT_ALT, "RALT" },
|
||||||
|
{ GLFW_KEY_RIGHT_ALT, "LVL3" },
|
||||||
|
{ GLFW_KEY_RIGHT_ALT, "MDSW" },
|
||||||
|
{ GLFW_KEY_RIGHT_SUPER, "RWIN" },
|
||||||
|
{ GLFW_KEY_MENU, "MENU" }
|
||||||
|
};
|
||||||
|
|
||||||
// Find the X11 key code -> GLFW key code mapping
|
// Find the X11 key code -> GLFW key code mapping
|
||||||
for (scancode = desc->min_key_code; scancode <= desc->max_key_code; scancode++)
|
for (scancode = scancodeMin; scancode <= scancodeMax; scancode++)
|
||||||
{
|
{
|
||||||
memcpy(name, desc->names->keys[scancode].name, XkbKeyNameLength);
|
int key = GLFW_KEY_UNKNOWN;
|
||||||
name[XkbKeyNameLength] = '\0';
|
|
||||||
|
|
||||||
// Map the key name to a GLFW key code. Note: We only map printable
|
// Map the key name to a GLFW key code. Note: We use the US
|
||||||
// keys here, and we use the US keyboard layout. The rest of the
|
// keyboard layout. Because function keys aren't mapped correctly
|
||||||
// keys (function keys) are mapped using traditional KeySym
|
// when using traditional KeySym translations, they are mapped
|
||||||
// translations.
|
// here instead.
|
||||||
if (strcmp(name, "TLDE") == 0) key = GLFW_KEY_GRAVE_ACCENT;
|
for (int i = 0; i < sizeof(keymap) / sizeof(keymap[0]); i++)
|
||||||
else if (strcmp(name, "AE01") == 0) key = GLFW_KEY_1;
|
{
|
||||||
else if (strcmp(name, "AE02") == 0) key = GLFW_KEY_2;
|
if (strncmp(desc->names->keys[scancode].name,
|
||||||
else if (strcmp(name, "AE03") == 0) key = GLFW_KEY_3;
|
keymap[i].name,
|
||||||
else if (strcmp(name, "AE04") == 0) key = GLFW_KEY_4;
|
XkbKeyNameLength) == 0)
|
||||||
else if (strcmp(name, "AE05") == 0) key = GLFW_KEY_5;
|
{
|
||||||
else if (strcmp(name, "AE06") == 0) key = GLFW_KEY_6;
|
key = keymap[i].key;
|
||||||
else if (strcmp(name, "AE07") == 0) key = GLFW_KEY_7;
|
break;
|
||||||
else if (strcmp(name, "AE08") == 0) key = GLFW_KEY_8;
|
}
|
||||||
else if (strcmp(name, "AE09") == 0) key = GLFW_KEY_9;
|
}
|
||||||
else if (strcmp(name, "AE10") == 0) key = GLFW_KEY_0;
|
|
||||||
else if (strcmp(name, "AE11") == 0) key = GLFW_KEY_MINUS;
|
|
||||||
else if (strcmp(name, "AE12") == 0) key = GLFW_KEY_EQUAL;
|
|
||||||
else if (strcmp(name, "AD01") == 0) key = GLFW_KEY_Q;
|
|
||||||
else if (strcmp(name, "AD02") == 0) key = GLFW_KEY_W;
|
|
||||||
else if (strcmp(name, "AD03") == 0) key = GLFW_KEY_E;
|
|
||||||
else if (strcmp(name, "AD04") == 0) key = GLFW_KEY_R;
|
|
||||||
else if (strcmp(name, "AD05") == 0) key = GLFW_KEY_T;
|
|
||||||
else if (strcmp(name, "AD06") == 0) key = GLFW_KEY_Y;
|
|
||||||
else if (strcmp(name, "AD07") == 0) key = GLFW_KEY_U;
|
|
||||||
else if (strcmp(name, "AD08") == 0) key = GLFW_KEY_I;
|
|
||||||
else if (strcmp(name, "AD09") == 0) key = GLFW_KEY_O;
|
|
||||||
else if (strcmp(name, "AD10") == 0) key = GLFW_KEY_P;
|
|
||||||
else if (strcmp(name, "AD11") == 0) key = GLFW_KEY_LEFT_BRACKET;
|
|
||||||
else if (strcmp(name, "AD12") == 0) key = GLFW_KEY_RIGHT_BRACKET;
|
|
||||||
else if (strcmp(name, "AC01") == 0) key = GLFW_KEY_A;
|
|
||||||
else if (strcmp(name, "AC02") == 0) key = GLFW_KEY_S;
|
|
||||||
else if (strcmp(name, "AC03") == 0) key = GLFW_KEY_D;
|
|
||||||
else if (strcmp(name, "AC04") == 0) key = GLFW_KEY_F;
|
|
||||||
else if (strcmp(name, "AC05") == 0) key = GLFW_KEY_G;
|
|
||||||
else if (strcmp(name, "AC06") == 0) key = GLFW_KEY_H;
|
|
||||||
else if (strcmp(name, "AC07") == 0) key = GLFW_KEY_J;
|
|
||||||
else if (strcmp(name, "AC08") == 0) key = GLFW_KEY_K;
|
|
||||||
else if (strcmp(name, "AC09") == 0) key = GLFW_KEY_L;
|
|
||||||
else if (strcmp(name, "AC10") == 0) key = GLFW_KEY_SEMICOLON;
|
|
||||||
else if (strcmp(name, "AC11") == 0) key = GLFW_KEY_APOSTROPHE;
|
|
||||||
else if (strcmp(name, "AB01") == 0) key = GLFW_KEY_Z;
|
|
||||||
else if (strcmp(name, "AB02") == 0) key = GLFW_KEY_X;
|
|
||||||
else if (strcmp(name, "AB03") == 0) key = GLFW_KEY_C;
|
|
||||||
else if (strcmp(name, "AB04") == 0) key = GLFW_KEY_V;
|
|
||||||
else if (strcmp(name, "AB05") == 0) key = GLFW_KEY_B;
|
|
||||||
else if (strcmp(name, "AB06") == 0) key = GLFW_KEY_N;
|
|
||||||
else if (strcmp(name, "AB07") == 0) key = GLFW_KEY_M;
|
|
||||||
else if (strcmp(name, "AB08") == 0) key = GLFW_KEY_COMMA;
|
|
||||||
else if (strcmp(name, "AB09") == 0) key = GLFW_KEY_PERIOD;
|
|
||||||
else if (strcmp(name, "AB10") == 0) key = GLFW_KEY_SLASH;
|
|
||||||
else if (strcmp(name, "BKSL") == 0) key = GLFW_KEY_BACKSLASH;
|
|
||||||
else if (strcmp(name, "LSGT") == 0) key = GLFW_KEY_WORLD_1;
|
|
||||||
else key = GLFW_KEY_UNKNOWN;
|
|
||||||
|
|
||||||
if ((scancode >= 0) && (scancode < 256))
|
// Fall back to key aliases in case the key name did not match
|
||||||
_glfw.x11.keycodes[scancode] = key;
|
for (int i = 0; i < desc->names->num_key_aliases; i++)
|
||||||
|
{
|
||||||
|
if (key != GLFW_KEY_UNKNOWN)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (strncmp(desc->names->key_aliases[i].real,
|
||||||
|
desc->names->keys[scancode].name,
|
||||||
|
XkbKeyNameLength) != 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < sizeof(keymap) / sizeof(keymap[0]); j++)
|
||||||
|
{
|
||||||
|
if (strncmp(desc->names->key_aliases[i].alias,
|
||||||
|
keymap[j].name,
|
||||||
|
XkbKeyNameLength) == 0)
|
||||||
|
{
|
||||||
|
key = keymap[j].key;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.x11.keycodes[scancode] = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
XkbFreeNames(desc, XkbKeyNamesMask, True);
|
XkbFreeNames(desc, XkbKeyNamesMask, True);
|
||||||
XkbFreeKeyboard(desc, 0, True);
|
XkbFreeKeyboard(desc, 0, True);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
XDisplayKeycodes(_glfw.x11.display, &scancodeMin, &scancodeMax);
|
||||||
|
|
||||||
for (scancode = 0; scancode < 256; scancode++)
|
int width;
|
||||||
|
KeySym* keysyms = XGetKeyboardMapping(_glfw.x11.display,
|
||||||
|
scancodeMin,
|
||||||
|
scancodeMax - scancodeMin + 1,
|
||||||
|
&width);
|
||||||
|
|
||||||
|
for (scancode = scancodeMin; scancode <= scancodeMax; scancode++)
|
||||||
{
|
{
|
||||||
// Translate the un-translated key codes using traditional X11 KeySym
|
// Translate the un-translated key codes using traditional X11 KeySym
|
||||||
// lookups
|
// lookups
|
||||||
if (_glfw.x11.keycodes[scancode] < 0)
|
if (_glfw.x11.keycodes[scancode] < 0)
|
||||||
_glfw.x11.keycodes[scancode] = translateKeyCode(scancode);
|
{
|
||||||
|
const size_t base = (scancode - scancodeMin) * width;
|
||||||
|
_glfw.x11.keycodes[scancode] = translateKeySyms(&keysyms[base], width);
|
||||||
|
}
|
||||||
|
|
||||||
// Store the reverse translation for faster key name lookup
|
// Store the reverse translation for faster key name lookup
|
||||||
if (_glfw.x11.keycodes[scancode] > 0)
|
if (_glfw.x11.keycodes[scancode] > 0)
|
||||||
_glfw.x11.scancodes[_glfw.x11.keycodes[scancode]] = scancode;
|
_glfw.x11.scancodes[_glfw.x11.keycodes[scancode]] = scancode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XFree(keysyms);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether the IM has a usable style
|
// Check whether the IM has a usable style
|
||||||
@ -350,6 +455,40 @@ static GLFWbool hasUsableInputMethodStyle(void)
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void inputMethodDestroyCallback(XIM im, XPointer clientData, XPointer callData)
|
||||||
|
{
|
||||||
|
_glfw.x11.im = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void inputMethodInstantiateCallback(Display* display,
|
||||||
|
XPointer clientData,
|
||||||
|
XPointer callData)
|
||||||
|
{
|
||||||
|
if (_glfw.x11.im)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_glfw.x11.im = XOpenIM(_glfw.x11.display, 0, NULL, NULL);
|
||||||
|
if (_glfw.x11.im)
|
||||||
|
{
|
||||||
|
if (!hasUsableInputMethodStyle())
|
||||||
|
{
|
||||||
|
XCloseIM(_glfw.x11.im);
|
||||||
|
_glfw.x11.im = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.x11.im)
|
||||||
|
{
|
||||||
|
XIMCallback callback;
|
||||||
|
callback.callback = (XIMProc) inputMethodDestroyCallback;
|
||||||
|
callback.client_data = NULL;
|
||||||
|
XSetIMValues(_glfw.x11.im, XNDestroyCallback, &callback, NULL);
|
||||||
|
|
||||||
|
for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next)
|
||||||
|
_glfwCreateInputContextX11(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether the specified atom is supported
|
// Check whether the specified atom is supported
|
||||||
//
|
//
|
||||||
static Atom getSupportedAtom(Atom* supportedAtoms,
|
static Atom getSupportedAtom(Atom* supportedAtoms,
|
||||||
@ -857,6 +996,9 @@ static Window createHelperWindow(void)
|
|||||||
//
|
//
|
||||||
static int errorHandler(Display *display, XErrorEvent* event)
|
static int errorHandler(Display *display, XErrorEvent* event)
|
||||||
{
|
{
|
||||||
|
if (_glfw.x11.display != display)
|
||||||
|
return 0;
|
||||||
|
|
||||||
_glfw.x11.errorCode = event->error_code;
|
_glfw.x11.errorCode = event->error_code;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -937,15 +1079,224 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
|
|||||||
|
|
||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
#if !defined(X_HAVE_UTF8_STRING)
|
// HACK: If the application has left the locale as "C" then both wide
|
||||||
// HACK: If the current locale is "C" and the Xlib UTF-8 functions are
|
// character text input and explicit UTF-8 input via XIM will break
|
||||||
// unavailable, apply the environment's locale in the hope that it's
|
// This sets the CTYPE part of the current locale from the environment
|
||||||
// both available and not "C"
|
// in the hope that it is set to something more sane than "C"
|
||||||
// This is done because the "C" locale breaks wide character input,
|
|
||||||
// which is what we fall back on when UTF-8 support is missing
|
|
||||||
if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
|
if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
|
||||||
setlocale(LC_CTYPE, "");
|
setlocale(LC_CTYPE, "");
|
||||||
|
|
||||||
|
#if defined(__CYGWIN__)
|
||||||
|
_glfw.x11.xlib.handle = _glfw_dlopen("libX11-6.so");
|
||||||
|
#else
|
||||||
|
_glfw.x11.xlib.handle = _glfw_dlopen("libX11.so.6");
|
||||||
#endif
|
#endif
|
||||||
|
if (!_glfw.x11.xlib.handle)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to load Xlib");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.x11.xlib.AllocClassHint = (PFN_XAllocClassHint)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XAllocClassHint");
|
||||||
|
_glfw.x11.xlib.AllocSizeHints = (PFN_XAllocSizeHints)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XAllocSizeHints");
|
||||||
|
_glfw.x11.xlib.AllocWMHints = (PFN_XAllocWMHints)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XAllocWMHints");
|
||||||
|
_glfw.x11.xlib.ChangeProperty = (PFN_XChangeProperty)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XChangeProperty");
|
||||||
|
_glfw.x11.xlib.ChangeWindowAttributes = (PFN_XChangeWindowAttributes)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XChangeWindowAttributes");
|
||||||
|
_glfw.x11.xlib.CheckIfEvent = (PFN_XCheckIfEvent)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XCheckIfEvent");
|
||||||
|
_glfw.x11.xlib.CheckTypedWindowEvent = (PFN_XCheckTypedWindowEvent)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XCheckTypedWindowEvent");
|
||||||
|
_glfw.x11.xlib.CloseDisplay = (PFN_XCloseDisplay)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XCloseDisplay");
|
||||||
|
_glfw.x11.xlib.CloseIM = (PFN_XCloseIM)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XCloseIM");
|
||||||
|
_glfw.x11.xlib.ConvertSelection = (PFN_XConvertSelection)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XConvertSelection");
|
||||||
|
_glfw.x11.xlib.CreateColormap = (PFN_XCreateColormap)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XCreateColormap");
|
||||||
|
_glfw.x11.xlib.CreateFontCursor = (PFN_XCreateFontCursor)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XCreateFontCursor");
|
||||||
|
_glfw.x11.xlib.CreateIC = (PFN_XCreateIC)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XCreateIC");
|
||||||
|
_glfw.x11.xlib.CreateWindow = (PFN_XCreateWindow)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XCreateWindow");
|
||||||
|
_glfw.x11.xlib.DefineCursor = (PFN_XDefineCursor)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XDefineCursor");
|
||||||
|
_glfw.x11.xlib.DeleteContext = (PFN_XDeleteContext)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XDeleteContext");
|
||||||
|
_glfw.x11.xlib.DeleteProperty = (PFN_XDeleteProperty)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XDeleteProperty");
|
||||||
|
_glfw.x11.xlib.DestroyIC = (PFN_XDestroyIC)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyIC");
|
||||||
|
_glfw.x11.xlib.DestroyWindow = (PFN_XDestroyWindow)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyWindow");
|
||||||
|
_glfw.x11.xlib.DisplayKeycodes = (PFN_XDisplayKeycodes)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XDisplayKeycodes");
|
||||||
|
_glfw.x11.xlib.EventsQueued = (PFN_XEventsQueued)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XEventsQueued");
|
||||||
|
_glfw.x11.xlib.FilterEvent = (PFN_XFilterEvent)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XFilterEvent");
|
||||||
|
_glfw.x11.xlib.FindContext = (PFN_XFindContext)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XFindContext");
|
||||||
|
_glfw.x11.xlib.Flush = (PFN_XFlush)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XFlush");
|
||||||
|
_glfw.x11.xlib.Free = (PFN_XFree)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XFree");
|
||||||
|
_glfw.x11.xlib.FreeColormap = (PFN_XFreeColormap)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XFreeColormap");
|
||||||
|
_glfw.x11.xlib.FreeCursor = (PFN_XFreeCursor)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XFreeCursor");
|
||||||
|
_glfw.x11.xlib.FreeEventData = (PFN_XFreeEventData)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XFreeEventData");
|
||||||
|
_glfw.x11.xlib.GetErrorText = (PFN_XGetErrorText)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetErrorText");
|
||||||
|
_glfw.x11.xlib.GetEventData = (PFN_XGetEventData)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetEventData");
|
||||||
|
_glfw.x11.xlib.GetICValues = (PFN_XGetICValues)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetICValues");
|
||||||
|
_glfw.x11.xlib.GetIMValues = (PFN_XGetIMValues)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetIMValues");
|
||||||
|
_glfw.x11.xlib.GetInputFocus = (PFN_XGetInputFocus)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetInputFocus");
|
||||||
|
_glfw.x11.xlib.GetKeyboardMapping = (PFN_XGetKeyboardMapping)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetKeyboardMapping");
|
||||||
|
_glfw.x11.xlib.GetScreenSaver = (PFN_XGetScreenSaver)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetScreenSaver");
|
||||||
|
_glfw.x11.xlib.GetSelectionOwner = (PFN_XGetSelectionOwner)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetSelectionOwner");
|
||||||
|
_glfw.x11.xlib.GetVisualInfo = (PFN_XGetVisualInfo)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetVisualInfo");
|
||||||
|
_glfw.x11.xlib.GetWMNormalHints = (PFN_XGetWMNormalHints)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetWMNormalHints");
|
||||||
|
_glfw.x11.xlib.GetWindowAttributes = (PFN_XGetWindowAttributes)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetWindowAttributes");
|
||||||
|
_glfw.x11.xlib.GetWindowProperty = (PFN_XGetWindowProperty)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XGetWindowProperty");
|
||||||
|
_glfw.x11.xlib.GrabPointer = (PFN_XGrabPointer)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XGrabPointer");
|
||||||
|
_glfw.x11.xlib.IconifyWindow = (PFN_XIconifyWindow)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XIconifyWindow");
|
||||||
|
_glfw.x11.xlib.InitThreads = (PFN_XInitThreads)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XInitThreads");
|
||||||
|
_glfw.x11.xlib.InternAtom = (PFN_XInternAtom)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XInternAtom");
|
||||||
|
_glfw.x11.xlib.LookupString = (PFN_XLookupString)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XLookupString");
|
||||||
|
_glfw.x11.xlib.MapRaised = (PFN_XMapRaised)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XMapRaised");
|
||||||
|
_glfw.x11.xlib.MapWindow = (PFN_XMapWindow)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XMapWindow");
|
||||||
|
_glfw.x11.xlib.MoveResizeWindow = (PFN_XMoveResizeWindow)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XMoveResizeWindow");
|
||||||
|
_glfw.x11.xlib.MoveWindow = (PFN_XMoveWindow)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XMoveWindow");
|
||||||
|
_glfw.x11.xlib.NextEvent = (PFN_XNextEvent)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XNextEvent");
|
||||||
|
_glfw.x11.xlib.OpenDisplay = (PFN_XOpenDisplay)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XOpenDisplay");
|
||||||
|
_glfw.x11.xlib.OpenIM = (PFN_XOpenIM)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XOpenIM");
|
||||||
|
_glfw.x11.xlib.PeekEvent = (PFN_XPeekEvent)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XPeekEvent");
|
||||||
|
_glfw.x11.xlib.Pending = (PFN_XPending)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XPending");
|
||||||
|
_glfw.x11.xlib.QueryExtension = (PFN_XQueryExtension)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XQueryExtension");
|
||||||
|
_glfw.x11.xlib.QueryPointer = (PFN_XQueryPointer)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XQueryPointer");
|
||||||
|
_glfw.x11.xlib.RaiseWindow = (PFN_XRaiseWindow)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XRaiseWindow");
|
||||||
|
_glfw.x11.xlib.RegisterIMInstantiateCallback = (PFN_XRegisterIMInstantiateCallback)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XRegisterIMInstantiateCallback");
|
||||||
|
_glfw.x11.xlib.ResizeWindow = (PFN_XResizeWindow)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XResizeWindow");
|
||||||
|
_glfw.x11.xlib.ResourceManagerString = (PFN_XResourceManagerString)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XResourceManagerString");
|
||||||
|
_glfw.x11.xlib.SaveContext = (PFN_XSaveContext)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSaveContext");
|
||||||
|
_glfw.x11.xlib.SelectInput = (PFN_XSelectInput)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSelectInput");
|
||||||
|
_glfw.x11.xlib.SendEvent = (PFN_XSendEvent)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSendEvent");
|
||||||
|
_glfw.x11.xlib.SetClassHint = (PFN_XSetClassHint)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetClassHint");
|
||||||
|
_glfw.x11.xlib.SetErrorHandler = (PFN_XSetErrorHandler)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetErrorHandler");
|
||||||
|
_glfw.x11.xlib.SetICFocus = (PFN_XSetICFocus)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetICFocus");
|
||||||
|
_glfw.x11.xlib.SetIMValues = (PFN_XSetIMValues)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetIMValues");
|
||||||
|
_glfw.x11.xlib.SetInputFocus = (PFN_XSetInputFocus)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetInputFocus");
|
||||||
|
_glfw.x11.xlib.SetLocaleModifiers = (PFN_XSetLocaleModifiers)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetLocaleModifiers");
|
||||||
|
_glfw.x11.xlib.SetScreenSaver = (PFN_XSetScreenSaver)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetScreenSaver");
|
||||||
|
_glfw.x11.xlib.SetSelectionOwner = (PFN_XSetSelectionOwner)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetSelectionOwner");
|
||||||
|
_glfw.x11.xlib.SetWMHints = (PFN_XSetWMHints)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetWMHints");
|
||||||
|
_glfw.x11.xlib.SetWMNormalHints = (PFN_XSetWMNormalHints)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetWMNormalHints");
|
||||||
|
_glfw.x11.xlib.SetWMProtocols = (PFN_XSetWMProtocols)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSetWMProtocols");
|
||||||
|
_glfw.x11.xlib.SupportsLocale = (PFN_XSupportsLocale)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSupportsLocale");
|
||||||
|
_glfw.x11.xlib.Sync = (PFN_XSync)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XSync");
|
||||||
|
_glfw.x11.xlib.TranslateCoordinates = (PFN_XTranslateCoordinates)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XTranslateCoordinates");
|
||||||
|
_glfw.x11.xlib.UndefineCursor = (PFN_XUndefineCursor)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XUndefineCursor");
|
||||||
|
_glfw.x11.xlib.UngrabPointer = (PFN_XUngrabPointer)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XUngrabPointer");
|
||||||
|
_glfw.x11.xlib.UnmapWindow = (PFN_XUnmapWindow)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XUnmapWindow");
|
||||||
|
_glfw.x11.xlib.UnsetICFocus = (PFN_XUnsetICFocus)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XUnsetICFocus");
|
||||||
|
_glfw.x11.xlib.VisualIDFromVisual = (PFN_XVisualIDFromVisual)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XVisualIDFromVisual");
|
||||||
|
_glfw.x11.xlib.WarpPointer = (PFN_XWarpPointer)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XWarpPointer");
|
||||||
|
_glfw.x11.xkb.FreeKeyboard = (PFN_XkbFreeKeyboard)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbFreeKeyboard");
|
||||||
|
_glfw.x11.xkb.FreeNames = (PFN_XkbFreeNames)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbFreeNames");
|
||||||
|
_glfw.x11.xkb.GetMap = (PFN_XkbGetMap)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbGetMap");
|
||||||
|
_glfw.x11.xkb.GetNames = (PFN_XkbGetNames)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbGetNames");
|
||||||
|
_glfw.x11.xkb.GetState = (PFN_XkbGetState)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbGetState");
|
||||||
|
_glfw.x11.xkb.KeycodeToKeysym = (PFN_XkbKeycodeToKeysym)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbKeycodeToKeysym");
|
||||||
|
_glfw.x11.xkb.QueryExtension = (PFN_XkbQueryExtension)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbQueryExtension");
|
||||||
|
_glfw.x11.xkb.SelectEventDetails = (PFN_XkbSelectEventDetails)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbSelectEventDetails");
|
||||||
|
_glfw.x11.xkb.SetDetectableAutoRepeat = (PFN_XkbSetDetectableAutoRepeat)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XkbSetDetectableAutoRepeat");
|
||||||
|
_glfw.x11.xrm.DestroyDatabase = (PFN_XrmDestroyDatabase)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XrmDestroyDatabase");
|
||||||
|
_glfw.x11.xrm.GetResource = (PFN_XrmGetResource)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XrmGetResource");
|
||||||
|
_glfw.x11.xrm.GetStringDatabase = (PFN_XrmGetStringDatabase)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XrmGetStringDatabase");
|
||||||
|
_glfw.x11.xrm.Initialize = (PFN_XrmInitialize)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XrmInitialize");
|
||||||
|
_glfw.x11.xrm.UniqueQuark = (PFN_XrmUniqueQuark)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XrmUniqueQuark");
|
||||||
|
_glfw.x11.xlib.UnregisterIMInstantiateCallback = (PFN_XUnregisterIMInstantiateCallback)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "XUnregisterIMInstantiateCallback");
|
||||||
|
_glfw.x11.xlib.utf8LookupString = (PFN_Xutf8LookupString)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "Xutf8LookupString");
|
||||||
|
_glfw.x11.xlib.utf8SetWMProperties = (PFN_Xutf8SetWMProperties)
|
||||||
|
_glfw_dlsym(_glfw.x11.xlib.handle, "Xutf8SetWMProperties");
|
||||||
|
|
||||||
XInitThreads();
|
XInitThreads();
|
||||||
XrmInitialize();
|
XrmInitialize();
|
||||||
@ -984,15 +1335,11 @@ int _glfwPlatformInit(void)
|
|||||||
{
|
{
|
||||||
XSetLocaleModifiers("");
|
XSetLocaleModifiers("");
|
||||||
|
|
||||||
_glfw.x11.im = XOpenIM(_glfw.x11.display, 0, NULL, NULL);
|
// If an IM is already present our callback will be called right away
|
||||||
if (_glfw.x11.im)
|
XRegisterIMInstantiateCallback(_glfw.x11.display,
|
||||||
{
|
NULL, NULL, NULL,
|
||||||
if (!hasUsableInputMethodStyle())
|
inputMethodInstantiateCallback,
|
||||||
{
|
NULL);
|
||||||
XCloseIM(_glfw.x11.im);
|
|
||||||
_glfw.x11.im = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
@ -1029,6 +1376,11 @@ void _glfwPlatformTerminate(void)
|
|||||||
free(_glfw.x11.primarySelectionString);
|
free(_glfw.x11.primarySelectionString);
|
||||||
free(_glfw.x11.clipboardString);
|
free(_glfw.x11.clipboardString);
|
||||||
|
|
||||||
|
XUnregisterIMInstantiateCallback(_glfw.x11.display,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
inputMethodInstantiateCallback,
|
||||||
|
NULL);
|
||||||
|
|
||||||
if (_glfw.x11.im)
|
if (_glfw.x11.im)
|
||||||
{
|
{
|
||||||
XCloseIM(_glfw.x11.im);
|
XCloseIM(_glfw.x11.im);
|
||||||
@ -1091,6 +1443,12 @@ void _glfwPlatformTerminate(void)
|
|||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
_glfwTerminateJoysticksLinux();
|
_glfwTerminateJoysticksLinux();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (_glfw.x11.xlib.handle)
|
||||||
|
{
|
||||||
|
_glfw_dlclose(_glfw.x11.xlib.handle);
|
||||||
|
_glfw.x11.xlib.handle = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
|
@ -322,12 +322,16 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|||||||
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
if (xpos)
|
if (ci)
|
||||||
*xpos = ci->x;
|
{
|
||||||
if (ypos)
|
if (xpos)
|
||||||
*ypos = ci->y;
|
*xpos = ci->x;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = ci->y;
|
||||||
|
|
||||||
|
XRRFreeCrtcInfo(ci);
|
||||||
|
}
|
||||||
|
|
||||||
XRRFreeCrtcInfo(ci);
|
|
||||||
XRRFreeScreenResources(sr);
|
XRRFreeScreenResources(sr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -493,9 +497,15 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
|||||||
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
*mode = vidmodeFromModeInfo(getModeInfo(sr, ci->mode), ci);
|
if (ci)
|
||||||
|
{
|
||||||
|
const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
|
||||||
|
if (mi) // mi can be NULL if the monitor has been disconnected
|
||||||
|
*mode = vidmodeFromModeInfo(mi, ci);
|
||||||
|
|
||||||
|
XRRFreeCrtcInfo(ci);
|
||||||
|
}
|
||||||
|
|
||||||
XRRFreeCrtcInfo(ci);
|
|
||||||
XRRFreeScreenResources(sr);
|
XRRFreeScreenResources(sr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/Xresource.h>
|
||||||
#include <X11/Xcursor/Xcursor.h>
|
#include <X11/Xcursor/Xcursor.h>
|
||||||
|
|
||||||
// The XRandR extension provides mode setting and gamma control
|
// The XRandR extension provides mode setting and gamma control
|
||||||
@ -47,6 +48,207 @@
|
|||||||
// The XInput extension provides raw mouse motion input
|
// The XInput extension provides raw mouse motion input
|
||||||
#include <X11/extensions/XInput2.h>
|
#include <X11/extensions/XInput2.h>
|
||||||
|
|
||||||
|
typedef XClassHint* (* PFN_XAllocClassHint)(void);
|
||||||
|
typedef XSizeHints* (* PFN_XAllocSizeHints)(void);
|
||||||
|
typedef XWMHints* (* PFN_XAllocWMHints)(void);
|
||||||
|
typedef int (* PFN_XChangeProperty)(Display*,Window,Atom,Atom,int,int,const unsigned char*,int);
|
||||||
|
typedef int (* PFN_XChangeWindowAttributes)(Display*,Window,unsigned long,XSetWindowAttributes*);
|
||||||
|
typedef Bool (* PFN_XCheckIfEvent)(Display*,XEvent*,Bool(*)(Display*,XEvent*,XPointer),XPointer);
|
||||||
|
typedef Bool (* PFN_XCheckTypedWindowEvent)(Display*,Window,int,XEvent*);
|
||||||
|
typedef int (* PFN_XCloseDisplay)(Display*);
|
||||||
|
typedef Status (* PFN_XCloseIM)(XIM);
|
||||||
|
typedef int (* PFN_XConvertSelection)(Display*,Atom,Atom,Atom,Window,Time);
|
||||||
|
typedef Colormap (* PFN_XCreateColormap)(Display*,Window,Visual*,int);
|
||||||
|
typedef Cursor (* PFN_XCreateFontCursor)(Display*,unsigned int);
|
||||||
|
typedef XIC (* PFN_XCreateIC)(XIM,...);
|
||||||
|
typedef Window (* PFN_XCreateWindow)(Display*,Window,int,int,unsigned int,unsigned int,unsigned int,int,unsigned int,Visual*,unsigned long,XSetWindowAttributes*);
|
||||||
|
typedef int (* PFN_XDefineCursor)(Display*,Window,Cursor);
|
||||||
|
typedef int (* PFN_XDeleteContext)(Display*,XID,XContext);
|
||||||
|
typedef int (* PFN_XDeleteProperty)(Display*,Window,Atom);
|
||||||
|
typedef void (* PFN_XDestroyIC)(XIC);
|
||||||
|
typedef int (* PFN_XDestroyWindow)(Display*,Window);
|
||||||
|
typedef int (* PFN_XDisplayKeycodes)(Display*,int*,int*);
|
||||||
|
typedef int (* PFN_XEventsQueued)(Display*,int);
|
||||||
|
typedef Bool (* PFN_XFilterEvent)(XEvent*,Window);
|
||||||
|
typedef int (* PFN_XFindContext)(Display*,XID,XContext,XPointer*);
|
||||||
|
typedef int (* PFN_XFlush)(Display*);
|
||||||
|
typedef int (* PFN_XFree)(void*);
|
||||||
|
typedef int (* PFN_XFreeColormap)(Display*,Colormap);
|
||||||
|
typedef int (* PFN_XFreeCursor)(Display*,Cursor);
|
||||||
|
typedef void (* PFN_XFreeEventData)(Display*,XGenericEventCookie*);
|
||||||
|
typedef int (* PFN_XGetErrorText)(Display*,int,char*,int);
|
||||||
|
typedef Bool (* PFN_XGetEventData)(Display*,XGenericEventCookie*);
|
||||||
|
typedef char* (* PFN_XGetICValues)(XIC,...);
|
||||||
|
typedef char* (* PFN_XGetIMValues)(XIM,...);
|
||||||
|
typedef int (* PFN_XGetInputFocus)(Display*,Window*,int*);
|
||||||
|
typedef KeySym* (* PFN_XGetKeyboardMapping)(Display*,KeyCode,int,int*);
|
||||||
|
typedef int (* PFN_XGetScreenSaver)(Display*,int*,int*,int*,int*);
|
||||||
|
typedef Window (* PFN_XGetSelectionOwner)(Display*,Atom);
|
||||||
|
typedef XVisualInfo* (* PFN_XGetVisualInfo)(Display*,long,XVisualInfo*,int*);
|
||||||
|
typedef Status (* PFN_XGetWMNormalHints)(Display*,Window,XSizeHints*,long*);
|
||||||
|
typedef Status (* PFN_XGetWindowAttributes)(Display*,Window,XWindowAttributes*);
|
||||||
|
typedef int (* PFN_XGetWindowProperty)(Display*,Window,Atom,long,long,Bool,Atom,Atom*,int*,unsigned long*,unsigned long*,unsigned char**);
|
||||||
|
typedef int (* PFN_XGrabPointer)(Display*,Window,Bool,unsigned int,int,int,Window,Cursor,Time);
|
||||||
|
typedef Status (* PFN_XIconifyWindow)(Display*,Window,int);
|
||||||
|
typedef Status (* PFN_XInitThreads)(void);
|
||||||
|
typedef Atom (* PFN_XInternAtom)(Display*,const char*,Bool);
|
||||||
|
typedef int (* PFN_XLookupString)(XKeyEvent*,char*,int,KeySym*,XComposeStatus*);
|
||||||
|
typedef int (* PFN_XMapRaised)(Display*,Window);
|
||||||
|
typedef int (* PFN_XMapWindow)(Display*,Window);
|
||||||
|
typedef int (* PFN_XMoveResizeWindow)(Display*,Window,int,int,unsigned int,unsigned int);
|
||||||
|
typedef int (* PFN_XMoveWindow)(Display*,Window,int,int);
|
||||||
|
typedef int (* PFN_XNextEvent)(Display*,XEvent*);
|
||||||
|
typedef Display* (* PFN_XOpenDisplay)(const char*);
|
||||||
|
typedef XIM (* PFN_XOpenIM)(Display*,XrmDatabase*,char*,char*);
|
||||||
|
typedef int (* PFN_XPeekEvent)(Display*,XEvent*);
|
||||||
|
typedef int (* PFN_XPending)(Display*);
|
||||||
|
typedef Bool (* PFN_XQueryExtension)(Display*,const char*,int*,int*,int*);
|
||||||
|
typedef Bool (* PFN_XQueryPointer)(Display*,Window,Window*,Window*,int*,int*,int*,int*,unsigned int*);
|
||||||
|
typedef int (* PFN_XRaiseWindow)(Display*,Window);
|
||||||
|
typedef Bool (* PFN_XRegisterIMInstantiateCallback)(Display*,void*,char*,char*,XIDProc,XPointer);
|
||||||
|
typedef int (* PFN_XResizeWindow)(Display*,Window,unsigned int,unsigned int);
|
||||||
|
typedef char* (* PFN_XResourceManagerString)(Display*);
|
||||||
|
typedef int (* PFN_XSaveContext)(Display*,XID,XContext,const char*);
|
||||||
|
typedef int (* PFN_XSelectInput)(Display*,Window,long);
|
||||||
|
typedef Status (* PFN_XSendEvent)(Display*,Window,Bool,long,XEvent*);
|
||||||
|
typedef int (* PFN_XSetClassHint)(Display*,Window,XClassHint*);
|
||||||
|
typedef XErrorHandler (* PFN_XSetErrorHandler)(XErrorHandler);
|
||||||
|
typedef void (* PFN_XSetICFocus)(XIC);
|
||||||
|
typedef char* (* PFN_XSetIMValues)(XIM,...);
|
||||||
|
typedef int (* PFN_XSetInputFocus)(Display*,Window,int,Time);
|
||||||
|
typedef char* (* PFN_XSetLocaleModifiers)(const char*);
|
||||||
|
typedef int (* PFN_XSetScreenSaver)(Display*,int,int,int,int);
|
||||||
|
typedef int (* PFN_XSetSelectionOwner)(Display*,Atom,Window,Time);
|
||||||
|
typedef int (* PFN_XSetWMHints)(Display*,Window,XWMHints*);
|
||||||
|
typedef void (* PFN_XSetWMNormalHints)(Display*,Window,XSizeHints*);
|
||||||
|
typedef Status (* PFN_XSetWMProtocols)(Display*,Window,Atom*,int);
|
||||||
|
typedef Bool (* PFN_XSupportsLocale)(void);
|
||||||
|
typedef int (* PFN_XSync)(Display*,Bool);
|
||||||
|
typedef Bool (* PFN_XTranslateCoordinates)(Display*,Window,Window,int,int,int*,int*,Window*);
|
||||||
|
typedef int (* PFN_XUndefineCursor)(Display*,Window);
|
||||||
|
typedef int (* PFN_XUngrabPointer)(Display*,Time);
|
||||||
|
typedef int (* PFN_XUnmapWindow)(Display*,Window);
|
||||||
|
typedef void (* PFN_XUnsetICFocus)(XIC);
|
||||||
|
typedef VisualID (* PFN_XVisualIDFromVisual)(Visual*);
|
||||||
|
typedef int (* PFN_XWarpPointer)(Display*,Window,Window,int,int,unsigned int,unsigned int,int,int);
|
||||||
|
typedef void (* PFN_XkbFreeKeyboard)(XkbDescPtr,unsigned int,Bool);
|
||||||
|
typedef void (* PFN_XkbFreeNames)(XkbDescPtr,unsigned int,Bool);
|
||||||
|
typedef XkbDescPtr (* PFN_XkbGetMap)(Display*,unsigned int,unsigned int);
|
||||||
|
typedef Status (* PFN_XkbGetNames)(Display*,unsigned int,XkbDescPtr);
|
||||||
|
typedef Status (* PFN_XkbGetState)(Display*,unsigned int,XkbStatePtr);
|
||||||
|
typedef KeySym (* PFN_XkbKeycodeToKeysym)(Display*,KeyCode,int,int);
|
||||||
|
typedef Bool (* PFN_XkbQueryExtension)(Display*,int*,int*,int*,int*,int*);
|
||||||
|
typedef Bool (* PFN_XkbSelectEventDetails)(Display*,unsigned int,unsigned int,unsigned long,unsigned long);
|
||||||
|
typedef Bool (* PFN_XkbSetDetectableAutoRepeat)(Display*,Bool,Bool*);
|
||||||
|
typedef void (* PFN_XrmDestroyDatabase)(XrmDatabase);
|
||||||
|
typedef Bool (* PFN_XrmGetResource)(XrmDatabase,const char*,const char*,char**,XrmValue*);
|
||||||
|
typedef XrmDatabase (* PFN_XrmGetStringDatabase)(const char*);
|
||||||
|
typedef void (* PFN_XrmInitialize)(void);
|
||||||
|
typedef XrmQuark (* PFN_XrmUniqueQuark)(void);
|
||||||
|
typedef Bool (* PFN_XUnregisterIMInstantiateCallback)(Display*,void*,char*,char*,XIDProc,XPointer);
|
||||||
|
typedef int (* PFN_Xutf8LookupString)(XIC,XKeyPressedEvent*,char*,int,KeySym*,Status*);
|
||||||
|
typedef void (* PFN_Xutf8SetWMProperties)(Display*,Window,const char*,const char*,char**,int,XSizeHints*,XWMHints*,XClassHint*);
|
||||||
|
#define XAllocClassHint _glfw.x11.xlib.AllocClassHint
|
||||||
|
#define XAllocSizeHints _glfw.x11.xlib.AllocSizeHints
|
||||||
|
#define XAllocWMHints _glfw.x11.xlib.AllocWMHints
|
||||||
|
#define XChangeProperty _glfw.x11.xlib.ChangeProperty
|
||||||
|
#define XChangeWindowAttributes _glfw.x11.xlib.ChangeWindowAttributes
|
||||||
|
#define XCheckIfEvent _glfw.x11.xlib.CheckIfEvent
|
||||||
|
#define XCheckTypedWindowEvent _glfw.x11.xlib.CheckTypedWindowEvent
|
||||||
|
#define XCloseDisplay _glfw.x11.xlib.CloseDisplay
|
||||||
|
#define XCloseIM _glfw.x11.xlib.CloseIM
|
||||||
|
#define XConvertSelection _glfw.x11.xlib.ConvertSelection
|
||||||
|
#define XCreateColormap _glfw.x11.xlib.CreateColormap
|
||||||
|
#define XCreateFontCursor _glfw.x11.xlib.CreateFontCursor
|
||||||
|
#define XCreateIC _glfw.x11.xlib.CreateIC
|
||||||
|
#define XCreateWindow _glfw.x11.xlib.CreateWindow
|
||||||
|
#define XDefineCursor _glfw.x11.xlib.DefineCursor
|
||||||
|
#define XDeleteContext _glfw.x11.xlib.DeleteContext
|
||||||
|
#define XDeleteProperty _glfw.x11.xlib.DeleteProperty
|
||||||
|
#define XDestroyIC _glfw.x11.xlib.DestroyIC
|
||||||
|
#define XDestroyWindow _glfw.x11.xlib.DestroyWindow
|
||||||
|
#define XDisplayKeycodes _glfw.x11.xlib.DisplayKeycodes
|
||||||
|
#define XEventsQueued _glfw.x11.xlib.EventsQueued
|
||||||
|
#define XFilterEvent _glfw.x11.xlib.FilterEvent
|
||||||
|
#define XFindContext _glfw.x11.xlib.FindContext
|
||||||
|
#define XFlush _glfw.x11.xlib.Flush
|
||||||
|
#define XFree _glfw.x11.xlib.Free
|
||||||
|
#define XFreeColormap _glfw.x11.xlib.FreeColormap
|
||||||
|
#define XFreeCursor _glfw.x11.xlib.FreeCursor
|
||||||
|
#define XFreeEventData _glfw.x11.xlib.FreeEventData
|
||||||
|
#define XGetErrorText _glfw.x11.xlib.GetErrorText
|
||||||
|
#define XGetEventData _glfw.x11.xlib.GetEventData
|
||||||
|
#define XGetICValues _glfw.x11.xlib.GetICValues
|
||||||
|
#define XGetIMValues _glfw.x11.xlib.GetIMValues
|
||||||
|
#define XGetInputFocus _glfw.x11.xlib.GetInputFocus
|
||||||
|
#define XGetKeyboardMapping _glfw.x11.xlib.GetKeyboardMapping
|
||||||
|
#define XGetScreenSaver _glfw.x11.xlib.GetScreenSaver
|
||||||
|
#define XGetSelectionOwner _glfw.x11.xlib.GetSelectionOwner
|
||||||
|
#define XGetVisualInfo _glfw.x11.xlib.GetVisualInfo
|
||||||
|
#define XGetWMNormalHints _glfw.x11.xlib.GetWMNormalHints
|
||||||
|
#define XGetWindowAttributes _glfw.x11.xlib.GetWindowAttributes
|
||||||
|
#define XGetWindowProperty _glfw.x11.xlib.GetWindowProperty
|
||||||
|
#define XGrabPointer _glfw.x11.xlib.GrabPointer
|
||||||
|
#define XIconifyWindow _glfw.x11.xlib.IconifyWindow
|
||||||
|
#define XInitThreads _glfw.x11.xlib.InitThreads
|
||||||
|
#define XInternAtom _glfw.x11.xlib.InternAtom
|
||||||
|
#define XLookupString _glfw.x11.xlib.LookupString
|
||||||
|
#define XMapRaised _glfw.x11.xlib.MapRaised
|
||||||
|
#define XMapWindow _glfw.x11.xlib.MapWindow
|
||||||
|
#define XMoveResizeWindow _glfw.x11.xlib.MoveResizeWindow
|
||||||
|
#define XMoveWindow _glfw.x11.xlib.MoveWindow
|
||||||
|
#define XNextEvent _glfw.x11.xlib.NextEvent
|
||||||
|
#define XOpenDisplay _glfw.x11.xlib.OpenDisplay
|
||||||
|
#define XOpenIM _glfw.x11.xlib.OpenIM
|
||||||
|
#define XPeekEvent _glfw.x11.xlib.PeekEvent
|
||||||
|
#define XPending _glfw.x11.xlib.Pending
|
||||||
|
#define XQueryExtension _glfw.x11.xlib.QueryExtension
|
||||||
|
#define XQueryPointer _glfw.x11.xlib.QueryPointer
|
||||||
|
#define XRaiseWindow _glfw.x11.xlib.RaiseWindow
|
||||||
|
#define XRegisterIMInstantiateCallback _glfw.x11.xlib.RegisterIMInstantiateCallback
|
||||||
|
#define XResizeWindow _glfw.x11.xlib.ResizeWindow
|
||||||
|
#define XResourceManagerString _glfw.x11.xlib.ResourceManagerString
|
||||||
|
#define XSaveContext _glfw.x11.xlib.SaveContext
|
||||||
|
#define XSelectInput _glfw.x11.xlib.SelectInput
|
||||||
|
#define XSendEvent _glfw.x11.xlib.SendEvent
|
||||||
|
#define XSetClassHint _glfw.x11.xlib.SetClassHint
|
||||||
|
#define XSetErrorHandler _glfw.x11.xlib.SetErrorHandler
|
||||||
|
#define XSetICFocus _glfw.x11.xlib.SetICFocus
|
||||||
|
#define XSetIMValues _glfw.x11.xlib.SetIMValues
|
||||||
|
#define XSetInputFocus _glfw.x11.xlib.SetInputFocus
|
||||||
|
#define XSetLocaleModifiers _glfw.x11.xlib.SetLocaleModifiers
|
||||||
|
#define XSetScreenSaver _glfw.x11.xlib.SetScreenSaver
|
||||||
|
#define XSetSelectionOwner _glfw.x11.xlib.SetSelectionOwner
|
||||||
|
#define XSetWMHints _glfw.x11.xlib.SetWMHints
|
||||||
|
#define XSetWMNormalHints _glfw.x11.xlib.SetWMNormalHints
|
||||||
|
#define XSetWMProtocols _glfw.x11.xlib.SetWMProtocols
|
||||||
|
#define XSupportsLocale _glfw.x11.xlib.SupportsLocale
|
||||||
|
#define XSync _glfw.x11.xlib.Sync
|
||||||
|
#define XTranslateCoordinates _glfw.x11.xlib.TranslateCoordinates
|
||||||
|
#define XUndefineCursor _glfw.x11.xlib.UndefineCursor
|
||||||
|
#define XUngrabPointer _glfw.x11.xlib.UngrabPointer
|
||||||
|
#define XUnmapWindow _glfw.x11.xlib.UnmapWindow
|
||||||
|
#define XUnsetICFocus _glfw.x11.xlib.UnsetICFocus
|
||||||
|
#define XVisualIDFromVisual _glfw.x11.xlib.VisualIDFromVisual
|
||||||
|
#define XWarpPointer _glfw.x11.xlib.WarpPointer
|
||||||
|
#define XkbFreeKeyboard _glfw.x11.xkb.FreeKeyboard
|
||||||
|
#define XkbFreeNames _glfw.x11.xkb.FreeNames
|
||||||
|
#define XkbGetMap _glfw.x11.xkb.GetMap
|
||||||
|
#define XkbGetNames _glfw.x11.xkb.GetNames
|
||||||
|
#define XkbGetState _glfw.x11.xkb.GetState
|
||||||
|
#define XkbKeycodeToKeysym _glfw.x11.xkb.KeycodeToKeysym
|
||||||
|
#define XkbQueryExtension _glfw.x11.xkb.QueryExtension
|
||||||
|
#define XkbSelectEventDetails _glfw.x11.xkb.SelectEventDetails
|
||||||
|
#define XkbSetDetectableAutoRepeat _glfw.x11.xkb.SetDetectableAutoRepeat
|
||||||
|
#define XrmDestroyDatabase _glfw.x11.xrm.DestroyDatabase
|
||||||
|
#define XrmGetResource _glfw.x11.xrm.GetResource
|
||||||
|
#define XrmGetStringDatabase _glfw.x11.xrm.GetStringDatabase
|
||||||
|
#define XrmInitialize _glfw.x11.xrm.Initialize
|
||||||
|
#define XrmUniqueQuark _glfw.x11.xrm.UniqueQuark
|
||||||
|
#define XUnregisterIMInstantiateCallback _glfw.x11.xlib.UnregisterIMInstantiateCallback
|
||||||
|
#define Xutf8LookupString _glfw.x11.xlib.utf8LookupString
|
||||||
|
#define Xutf8SetWMProperties _glfw.x11.xlib.utf8SetWMProperties
|
||||||
|
|
||||||
typedef XRRCrtcGamma* (* PFN_XRRAllocGamma)(int);
|
typedef XRRCrtcGamma* (* PFN_XRRAllocGamma)(int);
|
||||||
typedef void (* PFN_XRRFreeCrtcInfo)(XRRCrtcInfo*);
|
typedef void (* PFN_XRRFreeCrtcInfo)(XRRCrtcInfo*);
|
||||||
typedef void (* PFN_XRRFreeGamma)(XRRCrtcGamma*);
|
typedef void (* PFN_XRRFreeGamma)(XRRCrtcGamma*);
|
||||||
@ -186,6 +388,7 @@ typedef struct _GLFWwindowX11
|
|||||||
{
|
{
|
||||||
Colormap colormap;
|
Colormap colormap;
|
||||||
Window handle;
|
Window handle;
|
||||||
|
Window parent;
|
||||||
XIC ic;
|
XIC ic;
|
||||||
|
|
||||||
GLFWbool overrideRedirect;
|
GLFWbool overrideRedirect;
|
||||||
@ -300,6 +503,104 @@ typedef struct _GLFWlibraryX11
|
|||||||
Atom ATOM_PAIR;
|
Atom ATOM_PAIR;
|
||||||
Atom GLFW_SELECTION;
|
Atom GLFW_SELECTION;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
void* handle;
|
||||||
|
PFN_XAllocClassHint AllocClassHint;
|
||||||
|
PFN_XAllocSizeHints AllocSizeHints;
|
||||||
|
PFN_XAllocWMHints AllocWMHints;
|
||||||
|
PFN_XChangeProperty ChangeProperty;
|
||||||
|
PFN_XChangeWindowAttributes ChangeWindowAttributes;
|
||||||
|
PFN_XCheckIfEvent CheckIfEvent;
|
||||||
|
PFN_XCheckTypedWindowEvent CheckTypedWindowEvent;
|
||||||
|
PFN_XCloseDisplay CloseDisplay;
|
||||||
|
PFN_XCloseIM CloseIM;
|
||||||
|
PFN_XConvertSelection ConvertSelection;
|
||||||
|
PFN_XCreateColormap CreateColormap;
|
||||||
|
PFN_XCreateFontCursor CreateFontCursor;
|
||||||
|
PFN_XCreateIC CreateIC;
|
||||||
|
PFN_XCreateWindow CreateWindow;
|
||||||
|
PFN_XDefineCursor DefineCursor;
|
||||||
|
PFN_XDeleteContext DeleteContext;
|
||||||
|
PFN_XDeleteProperty DeleteProperty;
|
||||||
|
PFN_XDestroyIC DestroyIC;
|
||||||
|
PFN_XDestroyWindow DestroyWindow;
|
||||||
|
PFN_XDisplayKeycodes DisplayKeycodes;
|
||||||
|
PFN_XEventsQueued EventsQueued;
|
||||||
|
PFN_XFilterEvent FilterEvent;
|
||||||
|
PFN_XFindContext FindContext;
|
||||||
|
PFN_XFlush Flush;
|
||||||
|
PFN_XFree Free;
|
||||||
|
PFN_XFreeColormap FreeColormap;
|
||||||
|
PFN_XFreeCursor FreeCursor;
|
||||||
|
PFN_XFreeEventData FreeEventData;
|
||||||
|
PFN_XGetErrorText GetErrorText;
|
||||||
|
PFN_XGetEventData GetEventData;
|
||||||
|
PFN_XGetICValues GetICValues;
|
||||||
|
PFN_XGetIMValues GetIMValues;
|
||||||
|
PFN_XGetInputFocus GetInputFocus;
|
||||||
|
PFN_XGetKeyboardMapping GetKeyboardMapping;
|
||||||
|
PFN_XGetScreenSaver GetScreenSaver;
|
||||||
|
PFN_XGetSelectionOwner GetSelectionOwner;
|
||||||
|
PFN_XGetVisualInfo GetVisualInfo;
|
||||||
|
PFN_XGetWMNormalHints GetWMNormalHints;
|
||||||
|
PFN_XGetWindowAttributes GetWindowAttributes;
|
||||||
|
PFN_XGetWindowProperty GetWindowProperty;
|
||||||
|
PFN_XGrabPointer GrabPointer;
|
||||||
|
PFN_XIconifyWindow IconifyWindow;
|
||||||
|
PFN_XInitThreads InitThreads;
|
||||||
|
PFN_XInternAtom InternAtom;
|
||||||
|
PFN_XLookupString LookupString;
|
||||||
|
PFN_XMapRaised MapRaised;
|
||||||
|
PFN_XMapWindow MapWindow;
|
||||||
|
PFN_XMoveResizeWindow MoveResizeWindow;
|
||||||
|
PFN_XMoveWindow MoveWindow;
|
||||||
|
PFN_XNextEvent NextEvent;
|
||||||
|
PFN_XOpenDisplay OpenDisplay;
|
||||||
|
PFN_XOpenIM OpenIM;
|
||||||
|
PFN_XPeekEvent PeekEvent;
|
||||||
|
PFN_XPending Pending;
|
||||||
|
PFN_XQueryExtension QueryExtension;
|
||||||
|
PFN_XQueryPointer QueryPointer;
|
||||||
|
PFN_XRaiseWindow RaiseWindow;
|
||||||
|
PFN_XRegisterIMInstantiateCallback RegisterIMInstantiateCallback;
|
||||||
|
PFN_XResizeWindow ResizeWindow;
|
||||||
|
PFN_XResourceManagerString ResourceManagerString;
|
||||||
|
PFN_XSaveContext SaveContext;
|
||||||
|
PFN_XSelectInput SelectInput;
|
||||||
|
PFN_XSendEvent SendEvent;
|
||||||
|
PFN_XSetClassHint SetClassHint;
|
||||||
|
PFN_XSetErrorHandler SetErrorHandler;
|
||||||
|
PFN_XSetICFocus SetICFocus;
|
||||||
|
PFN_XSetIMValues SetIMValues;
|
||||||
|
PFN_XSetInputFocus SetInputFocus;
|
||||||
|
PFN_XSetLocaleModifiers SetLocaleModifiers;
|
||||||
|
PFN_XSetScreenSaver SetScreenSaver;
|
||||||
|
PFN_XSetSelectionOwner SetSelectionOwner;
|
||||||
|
PFN_XSetWMHints SetWMHints;
|
||||||
|
PFN_XSetWMNormalHints SetWMNormalHints;
|
||||||
|
PFN_XSetWMProtocols SetWMProtocols;
|
||||||
|
PFN_XSupportsLocale SupportsLocale;
|
||||||
|
PFN_XSync Sync;
|
||||||
|
PFN_XTranslateCoordinates TranslateCoordinates;
|
||||||
|
PFN_XUndefineCursor UndefineCursor;
|
||||||
|
PFN_XUngrabPointer UngrabPointer;
|
||||||
|
PFN_XUnmapWindow UnmapWindow;
|
||||||
|
PFN_XUnsetICFocus UnsetICFocus;
|
||||||
|
PFN_XVisualIDFromVisual VisualIDFromVisual;
|
||||||
|
PFN_XWarpPointer WarpPointer;
|
||||||
|
PFN_XUnregisterIMInstantiateCallback UnregisterIMInstantiateCallback;
|
||||||
|
PFN_Xutf8LookupString utf8LookupString;
|
||||||
|
PFN_Xutf8SetWMProperties utf8SetWMProperties;
|
||||||
|
} xlib;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
PFN_XrmDestroyDatabase DestroyDatabase;
|
||||||
|
PFN_XrmGetResource GetResource;
|
||||||
|
PFN_XrmGetStringDatabase GetStringDatabase;
|
||||||
|
PFN_XrmInitialize Initialize;
|
||||||
|
PFN_XrmUniqueQuark UniqueQuark;
|
||||||
|
} xrm;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GLFWbool available;
|
GLFWbool available;
|
||||||
void* handle;
|
void* handle;
|
||||||
@ -337,6 +638,15 @@ typedef struct _GLFWlibraryX11
|
|||||||
int major;
|
int major;
|
||||||
int minor;
|
int minor;
|
||||||
unsigned int group;
|
unsigned int group;
|
||||||
|
PFN_XkbFreeKeyboard FreeKeyboard;
|
||||||
|
PFN_XkbFreeNames FreeNames;
|
||||||
|
PFN_XkbGetMap GetMap;
|
||||||
|
PFN_XkbGetNames GetNames;
|
||||||
|
PFN_XkbGetState GetState;
|
||||||
|
PFN_XkbKeycodeToKeysym KeycodeToKeysym;
|
||||||
|
PFN_XkbQueryExtension QueryExtension;
|
||||||
|
PFN_XkbSelectEventDetails SelectEventDetails;
|
||||||
|
PFN_XkbSetDetectableAutoRepeat SetDetectableAutoRepeat;
|
||||||
} xkb;
|
} xkb;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -455,4 +765,5 @@ void _glfwReleaseErrorHandlerX11(void);
|
|||||||
void _glfwInputErrorX11(int error, const char* message);
|
void _glfwInputErrorX11(int error, const char* message);
|
||||||
|
|
||||||
void _glfwPushSelectionToManagerX11(void);
|
void _glfwPushSelectionToManagerX11(void);
|
||||||
|
void _glfwCreateInputContextX11(_GLFWwindow* window);
|
||||||
|
|
||||||
|
299
src/x11_window.c
299
src/x11_window.c
@ -590,6 +590,14 @@ static void enableCursor(_GLFWwindow* window)
|
|||||||
updateCursorImage(window);
|
updateCursorImage(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear its handle when the input context has been destroyed
|
||||||
|
//
|
||||||
|
static void inputContextDestroyCallback(XIC ic, XPointer clientData, XPointer callData)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) clientData;
|
||||||
|
window->x11.ic = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Create the X11 window (and its colormap)
|
// Create the X11 window (and its colormap)
|
||||||
//
|
//
|
||||||
static GLFWbool createNativeWindow(_GLFWwindow* window,
|
static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||||
@ -613,46 +621,41 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
|
|
||||||
window->x11.transparent = _glfwIsVisualTransparentX11(visual);
|
window->x11.transparent = _glfwIsVisualTransparentX11(visual);
|
||||||
|
|
||||||
// Create the actual window
|
XSetWindowAttributes wa = { 0 };
|
||||||
|
wa.colormap = window->x11.colormap;
|
||||||
|
wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
|
||||||
|
PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
|
||||||
|
ExposureMask | FocusChangeMask | VisibilityChangeMask |
|
||||||
|
EnterWindowMask | LeaveWindowMask | PropertyChangeMask;
|
||||||
|
|
||||||
|
_glfwGrabErrorHandlerX11();
|
||||||
|
|
||||||
|
window->x11.parent = _glfw.x11.root;
|
||||||
|
window->x11.handle = XCreateWindow(_glfw.x11.display,
|
||||||
|
_glfw.x11.root,
|
||||||
|
0, 0, // Position
|
||||||
|
width, height,
|
||||||
|
0, // Border width
|
||||||
|
depth, // Color depth
|
||||||
|
InputOutput,
|
||||||
|
visual,
|
||||||
|
CWBorderPixel | CWColormap | CWEventMask,
|
||||||
|
&wa);
|
||||||
|
|
||||||
|
_glfwReleaseErrorHandlerX11();
|
||||||
|
|
||||||
|
if (!window->x11.handle)
|
||||||
{
|
{
|
||||||
XSetWindowAttributes wa;
|
_glfwInputErrorX11(GLFW_PLATFORM_ERROR,
|
||||||
const unsigned long wamask = CWBorderPixel | CWColormap | CWEventMask;
|
"X11: Failed to create window");
|
||||||
|
return GLFW_FALSE;
|
||||||
wa.colormap = window->x11.colormap;
|
|
||||||
wa.border_pixel = 0;
|
|
||||||
wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
|
|
||||||
PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
|
|
||||||
ExposureMask | FocusChangeMask | VisibilityChangeMask |
|
|
||||||
EnterWindowMask | LeaveWindowMask | PropertyChangeMask;
|
|
||||||
|
|
||||||
_glfwGrabErrorHandlerX11();
|
|
||||||
|
|
||||||
window->x11.handle = XCreateWindow(_glfw.x11.display,
|
|
||||||
_glfw.x11.root,
|
|
||||||
0, 0,
|
|
||||||
width, height,
|
|
||||||
0, // Border width
|
|
||||||
depth, // Color depth
|
|
||||||
InputOutput,
|
|
||||||
visual,
|
|
||||||
wamask,
|
|
||||||
&wa);
|
|
||||||
|
|
||||||
_glfwReleaseErrorHandlerX11();
|
|
||||||
|
|
||||||
if (!window->x11.handle)
|
|
||||||
{
|
|
||||||
_glfwInputErrorX11(GLFW_PLATFORM_ERROR,
|
|
||||||
"X11: Failed to create window");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
XSaveContext(_glfw.x11.display,
|
|
||||||
window->x11.handle,
|
|
||||||
_glfw.x11.context,
|
|
||||||
(XPointer) window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XSaveContext(_glfw.x11.display,
|
||||||
|
window->x11.handle,
|
||||||
|
_glfw.x11.context,
|
||||||
|
(XPointer) window);
|
||||||
|
|
||||||
if (!wndconfig->decorated)
|
if (!wndconfig->decorated)
|
||||||
_glfwPlatformSetWindowDecorated(window, GLFW_FALSE);
|
_glfwPlatformSetWindowDecorated(window, GLFW_FALSE);
|
||||||
|
|
||||||
@ -682,7 +685,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
||||||
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
||||||
PropModeReplace, (unsigned char*) &states, count);
|
PropModeReplace, (unsigned char*) states, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -773,20 +776,10 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
PropModeReplace, (unsigned char*) &version, 1);
|
PropModeReplace, (unsigned char*) &version, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwPlatformSetWindowTitle(window, wndconfig->title);
|
|
||||||
|
|
||||||
if (_glfw.x11.im)
|
if (_glfw.x11.im)
|
||||||
{
|
_glfwCreateInputContextX11(window);
|
||||||
window->x11.ic = XCreateIC(_glfw.x11.im,
|
|
||||||
XNInputStyle,
|
|
||||||
XIMPreeditNothing | XIMStatusNothing,
|
|
||||||
XNClientWindow,
|
|
||||||
window->x11.handle,
|
|
||||||
XNFocusWindow,
|
|
||||||
window->x11.handle,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
_glfwPlatformSetWindowTitle(window, wndconfig->title);
|
||||||
_glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos);
|
_glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos);
|
||||||
_glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height);
|
_glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height);
|
||||||
|
|
||||||
@ -1171,8 +1164,7 @@ static void processEvent(XEvent *event)
|
|||||||
if (event->type == KeyPress || event->type == KeyRelease)
|
if (event->type == KeyPress || event->type == KeyRelease)
|
||||||
keycode = event->xkey.keycode;
|
keycode = event->xkey.keycode;
|
||||||
|
|
||||||
if (_glfw.x11.im)
|
filtered = XFilterEvent(event, None);
|
||||||
filtered = XFilterEvent(event, None);
|
|
||||||
|
|
||||||
if (_glfw.x11.randr.available)
|
if (_glfw.x11.randr.available)
|
||||||
{
|
{
|
||||||
@ -1257,6 +1249,12 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
|
case ReparentNotify:
|
||||||
|
{
|
||||||
|
window->x11.parent = event->xreparent.parent;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
{
|
{
|
||||||
const int key = translateKey(keycode);
|
const int key = translateKey(keycode);
|
||||||
@ -1541,18 +1539,34 @@ static void processEvent(XEvent *event)
|
|||||||
window->x11.height = event->xconfigure.height;
|
window->x11.height = event->xconfigure.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->xconfigure.x != window->x11.xpos ||
|
int xpos = event->xconfigure.x;
|
||||||
event->xconfigure.y != window->x11.ypos)
|
int ypos = event->xconfigure.y;
|
||||||
{
|
|
||||||
if (window->x11.overrideRedirect || event->xany.send_event)
|
|
||||||
{
|
|
||||||
_glfwInputWindowPos(window,
|
|
||||||
event->xconfigure.x,
|
|
||||||
event->xconfigure.y);
|
|
||||||
|
|
||||||
window->x11.xpos = event->xconfigure.x;
|
// NOTE: ConfigureNotify events from the server are in local
|
||||||
window->x11.ypos = event->xconfigure.y;
|
// coordinates, so if we are reparented we need to translate
|
||||||
}
|
// the position into root (screen) coordinates
|
||||||
|
if (!event->xany.send_event && window->x11.parent != _glfw.x11.root)
|
||||||
|
{
|
||||||
|
_glfwGrabErrorHandlerX11();
|
||||||
|
|
||||||
|
Window dummy;
|
||||||
|
XTranslateCoordinates(_glfw.x11.display,
|
||||||
|
window->x11.parent,
|
||||||
|
_glfw.x11.root,
|
||||||
|
xpos, ypos,
|
||||||
|
&xpos, &ypos,
|
||||||
|
&dummy);
|
||||||
|
|
||||||
|
_glfwReleaseErrorHandlerX11();
|
||||||
|
if (_glfw.x11.errorCode == BadWindow)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xpos != window->x11.xpos || ypos != window->x11.ypos)
|
||||||
|
{
|
||||||
|
_glfwInputWindowPos(window, xpos, ypos);
|
||||||
|
window->x11.xpos = xpos;
|
||||||
|
window->x11.ypos = ypos;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1943,6 +1957,38 @@ void _glfwPushSelectionToManagerX11(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwCreateInputContextX11(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
XIMCallback callback;
|
||||||
|
callback.callback = (XIMProc) inputContextDestroyCallback;
|
||||||
|
callback.client_data = (XPointer) window;
|
||||||
|
|
||||||
|
window->x11.ic = XCreateIC(_glfw.x11.im,
|
||||||
|
XNInputStyle,
|
||||||
|
XIMPreeditNothing | XIMStatusNothing,
|
||||||
|
XNClientWindow,
|
||||||
|
window->x11.handle,
|
||||||
|
XNFocusWindow,
|
||||||
|
window->x11.handle,
|
||||||
|
XNDestroyCallback,
|
||||||
|
&callback,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (window->x11.ic)
|
||||||
|
{
|
||||||
|
XWindowAttributes attribs;
|
||||||
|
XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &attribs);
|
||||||
|
|
||||||
|
unsigned long filter = 0;
|
||||||
|
if (XGetICValues(window->x11.ic, XNFilterEvents, &filter, NULL) == NULL)
|
||||||
|
{
|
||||||
|
XSelectInput(_glfw.x11.display,
|
||||||
|
window->x11.handle,
|
||||||
|
attribs.your_event_mask | filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
@ -2340,18 +2386,67 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (_glfw.x11.NET_WM_STATE &&
|
if (!_glfw.x11.NET_WM_STATE ||
|
||||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&
|
!_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
|
||||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
|
!_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfwPlatformWindowVisible(window))
|
||||||
{
|
{
|
||||||
sendEventToWM(window,
|
sendEventToWM(window,
|
||||||
_glfw.x11.NET_WM_STATE,
|
_glfw.x11.NET_WM_STATE,
|
||||||
_NET_WM_STATE_ADD,
|
_NET_WM_STATE_ADD,
|
||||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
|
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
|
||||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ,
|
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ,
|
||||||
1, 0);
|
1, 0);
|
||||||
XFlush(_glfw.x11.display);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Atom* states = NULL;
|
||||||
|
unsigned long count =
|
||||||
|
_glfwGetWindowPropertyX11(window->x11.handle,
|
||||||
|
_glfw.x11.NET_WM_STATE,
|
||||||
|
XA_ATOM,
|
||||||
|
(unsigned char**) &states);
|
||||||
|
|
||||||
|
// NOTE: We don't check for failure as this property may not exist yet
|
||||||
|
// and that's fine (and we'll create it implicitly with append)
|
||||||
|
|
||||||
|
Atom missing[2] =
|
||||||
|
{
|
||||||
|
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
|
||||||
|
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ
|
||||||
|
};
|
||||||
|
unsigned long missingCount = 2;
|
||||||
|
|
||||||
|
for (unsigned long i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (unsigned long j = 0; j < missingCount; j++)
|
||||||
|
{
|
||||||
|
if (states[i] == missing[j])
|
||||||
|
{
|
||||||
|
missing[j] = missing[missingCount - 1];
|
||||||
|
missingCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (states)
|
||||||
|
XFree(states);
|
||||||
|
|
||||||
|
if (!missingCount)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
||||||
|
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
||||||
|
PropModeAppend,
|
||||||
|
(unsigned char*) missing,
|
||||||
|
missingCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
XFlush(_glfw.x11.display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||||
@ -2371,6 +2466,9 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
|
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION)
|
||||||
|
return;
|
||||||
|
|
||||||
sendEventToWM(window,
|
sendEventToWM(window,
|
||||||
_glfw.x11.NET_WM_STATE,
|
_glfw.x11.NET_WM_STATE,
|
||||||
_NET_WM_STATE_ADD,
|
_NET_WM_STATE_ADD,
|
||||||
@ -2382,7 +2480,7 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
if (_glfw.x11.NET_ACTIVE_WINDOW)
|
if (_glfw.x11.NET_ACTIVE_WINDOW)
|
||||||
sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);
|
sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);
|
||||||
else
|
else if (_glfwPlatformWindowVisible(window))
|
||||||
{
|
{
|
||||||
XRaiseWindow(_glfw.x11.display, window->x11.handle);
|
XRaiseWindow(_glfw.x11.display, window->x11.handle);
|
||||||
XSetInputFocus(_glfw.x11.display, window->x11.handle,
|
XSetInputFocus(_glfw.x11.display, window->x11.handle,
|
||||||
@ -2567,7 +2665,7 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
|||||||
|
|
||||||
if (_glfwPlatformWindowVisible(window))
|
if (_glfwPlatformWindowVisible(window))
|
||||||
{
|
{
|
||||||
const Atom action = enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
const long action = enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
||||||
sendEventToWM(window,
|
sendEventToWM(window,
|
||||||
_glfw.x11.NET_WM_STATE,
|
_glfw.x11.NET_WM_STATE,
|
||||||
action,
|
action,
|
||||||
@ -2576,15 +2674,16 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Atom* states;
|
Atom* states = NULL;
|
||||||
unsigned long i, count;
|
unsigned long i, count;
|
||||||
|
|
||||||
count = _glfwGetWindowPropertyX11(window->x11.handle,
|
count = _glfwGetWindowPropertyX11(window->x11.handle,
|
||||||
_glfw.x11.NET_WM_STATE,
|
_glfw.x11.NET_WM_STATE,
|
||||||
XA_ATOM,
|
XA_ATOM,
|
||||||
(unsigned char**) &states);
|
(unsigned char**) &states);
|
||||||
if (!states)
|
|
||||||
return;
|
// NOTE: We don't check for failure as this property may not exist yet
|
||||||
|
// and that's fine (and we'll create it implicitly with append)
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
@ -2594,32 +2693,36 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == count)
|
if (i < count)
|
||||||
{
|
return;
|
||||||
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
|
||||||
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
||||||
PropModeAppend,
|
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
||||||
(unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
|
PropModeAppend,
|
||||||
1);
|
(unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
|
||||||
}
|
1);
|
||||||
}
|
}
|
||||||
else
|
else if (states)
|
||||||
{
|
{
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
|
if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
|
||||||
{
|
break;
|
||||||
states[i] = states[count - 1];
|
|
||||||
count--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i == count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
states[i] = states[count - 1];
|
||||||
|
count--;
|
||||||
|
|
||||||
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
||||||
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
||||||
PropModeReplace, (unsigned char*) &states, count);
|
PropModeReplace, (unsigned char*) states, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFree(states);
|
if (states)
|
||||||
|
XFree(states);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFlush(_glfw.x11.display);
|
XFlush(_glfw.x11.display);
|
||||||
@ -2684,7 +2787,7 @@ void _glfwPlatformPollEvents(void)
|
|||||||
#endif
|
#endif
|
||||||
XPending(_glfw.x11.display);
|
XPending(_glfw.x11.display);
|
||||||
|
|
||||||
while (XQLength(_glfw.x11.display))
|
while (QLength(_glfw.x11.display))
|
||||||
{
|
{
|
||||||
XEvent event;
|
XEvent event;
|
||||||
XNextEvent(_glfw.x11.display, &event);
|
XNextEvent(_glfw.x11.display, &event);
|
||||||
@ -2787,6 +2890,13 @@ const char* _glfwPlatformGetScancodeName(int scancode)
|
|||||||
if (!_glfw.x11.xkb.available)
|
if (!_glfw.x11.xkb.available)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (scancode < 0 || scancode > 0xff ||
|
||||||
|
_glfw.x11.keycodes[scancode] == GLFW_KEY_UNKNOWN)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const int key = _glfw.x11.keycodes[scancode];
|
const int key = _glfw.x11.keycodes[scancode];
|
||||||
const KeySym keysym = XkbKeycodeToKeysym(_glfw.x11.display,
|
const KeySym keysym = XkbKeycodeToKeysym(_glfw.x11.display,
|
||||||
scancode, _glfw.x11.xkb.group, 0);
|
scancode, _glfw.x11.xkb.group, 0);
|
||||||
@ -2915,8 +3025,9 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
|||||||
|
|
||||||
void _glfwPlatformSetClipboardString(const char* string)
|
void _glfwPlatformSetClipboardString(const char* string)
|
||||||
{
|
{
|
||||||
|
char* copy = _glfw_strdup(string);
|
||||||
free(_glfw.x11.clipboardString);
|
free(_glfw.x11.clipboardString);
|
||||||
_glfw.x11.clipboardString = _glfw_strdup(string);
|
_glfw.x11.clipboardString = copy;
|
||||||
|
|
||||||
XSetSelectionOwner(_glfw.x11.display,
|
XSetSelectionOwner(_glfw.x11.display,
|
||||||
_glfw.x11.CLIPBOARD,
|
_glfw.x11.CLIPBOARD,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
link_libraries(glfw)
|
link_libraries(glfw)
|
||||||
|
|
||||||
include_directories(${glfw_INCLUDE_DIRS} "${GLFW_SOURCE_DIR}/deps")
|
include_directories("${GLFW_SOURCE_DIR}/deps")
|
||||||
|
|
||||||
if (MATH_LIBRARY)
|
if (MATH_LIBRARY)
|
||||||
link_libraries("${MATH_LIBRARY}")
|
link_libraries("${MATH_LIBRARY}")
|
||||||
@ -20,17 +20,6 @@ set(GETOPT "${GLFW_SOURCE_DIR}/deps/getopt.h"
|
|||||||
set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
|
set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
|
||||||
"${GLFW_SOURCE_DIR}/deps/tinycthread.c")
|
"${GLFW_SOURCE_DIR}/deps/tinycthread.c")
|
||||||
|
|
||||||
if (${CMAKE_VERSION} VERSION_EQUAL "3.1.0" OR
|
|
||||||
${CMAKE_VERSION} VERSION_GREATER "3.1.0")
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
|
||||||
else()
|
|
||||||
# Remove this fallback when removing support for CMake version less than 3.1
|
|
||||||
add_compile_options("$<$<C_COMPILER_ID:AppleClang>:-std=c99>"
|
|
||||||
"$<$<C_COMPILER_ID:Clang>:-std=c99>"
|
|
||||||
"$<$<C_COMPILER_ID:GNU>:-std=c99>")
|
|
||||||
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_executable(clipboard clipboard.c ${GETOPT} ${GLAD_GL})
|
add_executable(clipboard clipboard.c ${GETOPT} ${GLAD_GL})
|
||||||
add_executable(events events.c ${GETOPT} ${GLAD_GL})
|
add_executable(events events.c ${GETOPT} ${GLAD_GL})
|
||||||
add_executable(msaa msaa.c ${GETOPT} ${GLAD_GL})
|
add_executable(msaa msaa.c ${GETOPT} ${GLAD_GL})
|
||||||
@ -50,27 +39,28 @@ add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GLAD_GL})
|
|||||||
add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD} ${GLAD_GL})
|
add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD} ${GLAD_GL})
|
||||||
add_executable(timeout WIN32 MACOSX_BUNDLE timeout.c ${GLAD_GL})
|
add_executable(timeout WIN32 MACOSX_BUNDLE timeout.c ${GLAD_GL})
|
||||||
add_executable(title WIN32 MACOSX_BUNDLE title.c ${GLAD_GL})
|
add_executable(title WIN32 MACOSX_BUNDLE title.c ${GLAD_GL})
|
||||||
add_executable(triangle-vulkan WIN32 triangle-vulkan.c ${ICON} ${GLAD_VULKAN})
|
add_executable(triangle-vulkan WIN32 triangle-vulkan.c ${GLAD_VULKAN})
|
||||||
add_executable(windows WIN32 MACOSX_BUNDLE windows.c ${GETOPT} ${GLAD_GL})
|
add_executable(windows WIN32 MACOSX_BUNDLE windows.c ${GLAD_GL})
|
||||||
|
|
||||||
target_link_libraries(empty "${CMAKE_THREAD_LIBS_INIT}")
|
target_link_libraries(empty Threads::Threads)
|
||||||
target_link_libraries(threads "${CMAKE_THREAD_LIBS_INIT}")
|
target_link_libraries(threads Threads::Threads)
|
||||||
if (RT_LIBRARY)
|
if (RT_LIBRARY)
|
||||||
target_link_libraries(empty "${RT_LIBRARY}")
|
target_link_libraries(empty "${RT_LIBRARY}")
|
||||||
target_link_libraries(threads "${RT_LIBRARY}")
|
target_link_libraries(threads "${RT_LIBRARY}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(WINDOWS_BINARIES empty gamma icon inputlag joysticks opacity tearing
|
set(GUI_ONLY_BINARIES empty gamma icon inputlag joysticks opacity tearing
|
||||||
threads timeout title triangle-vulkan windows)
|
threads timeout title triangle-vulkan windows)
|
||||||
set(CONSOLE_BINARIES clipboard events msaa glfwinfo iconify monitors reopen
|
set(CONSOLE_BINARIES clipboard events msaa glfwinfo iconify monitors reopen
|
||||||
cursor)
|
cursor)
|
||||||
|
|
||||||
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
set_target_properties(${GUI_ONLY_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
||||||
|
C_STANDARD 99
|
||||||
FOLDER "GLFW3/Tests")
|
FOLDER "GLFW3/Tests")
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
# Tell MSVC to use main instead of WinMain for Windows subsystem executables
|
# Tell MSVC to use main instead of WinMain for Windows subsystem executables
|
||||||
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
|
||||||
LINK_FLAGS "/ENTRY:mainCRTStartup")
|
LINK_FLAGS "/ENTRY:mainCRTStartup")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -84,12 +74,11 @@ if (APPLE)
|
|||||||
set_target_properties(threads PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Threads")
|
set_target_properties(threads PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Threads")
|
||||||
set_target_properties(timeout PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Timeout")
|
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(triangle-vulkan PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Vulkan Triangle")
|
|
||||||
set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows")
|
set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows")
|
||||||
|
|
||||||
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
|
||||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
|
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
|
||||||
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION}
|
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION}
|
||||||
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/MacOSXBundleInfo.plist.in")
|
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/Info.plist.in")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -241,6 +241,8 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
glfwSetErrorCallback(error_callback);
|
glfwSetErrorCallback(error_callback);
|
||||||
|
|
||||||
|
glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE);
|
||||||
|
|
||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
@ -34,8 +34,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "getopt.h"
|
static GLFWwindow* windows[4];
|
||||||
|
|
||||||
static const char* titles[] =
|
static const char* titles[] =
|
||||||
{
|
{
|
||||||
"Red",
|
"Red",
|
||||||
@ -55,20 +54,26 @@ static const struct
|
|||||||
{ 0.98f, 0.74f, 0.04f }
|
{ 0.98f, 0.74f, 0.04f }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void usage(void)
|
|
||||||
{
|
|
||||||
printf("Usage: windows [-h] [-b] [-f] \n");
|
|
||||||
printf("Options:\n");
|
|
||||||
printf(" -b create decorated windows\n");
|
|
||||||
printf(" -f set focus on show off for all but first window\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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void arrange_windows(void)
|
||||||
|
{
|
||||||
|
int xbase, ybase;
|
||||||
|
glfwGetWindowPos(windows[0], &xbase, &ybase);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
int left, top, right, bottom;
|
||||||
|
glfwGetWindowFrameSize(windows[i], &left, &top, &right, &bottom);
|
||||||
|
glfwSetWindowPos(windows[i],
|
||||||
|
xbase + (i & 1) * (200 + left + right),
|
||||||
|
ybase + (i >> 1) * (200 + top + bottom));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||||
{
|
{
|
||||||
if (action != GLFW_PRESS)
|
if (action != GLFW_PRESS)
|
||||||
@ -87,49 +92,34 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
|
|||||||
case GLFW_KEY_ESCAPE:
|
case GLFW_KEY_ESCAPE:
|
||||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GLFW_KEY_D:
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
const int decorated = glfwGetWindowAttrib(windows[i], GLFW_DECORATED);
|
||||||
|
glfwSetWindowAttrib(windows[i], GLFW_DECORATED, !decorated);
|
||||||
|
}
|
||||||
|
|
||||||
|
arrange_windows();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int i, ch;
|
|
||||||
int decorated = GLFW_FALSE;
|
|
||||||
int focusOnShow = GLFW_TRUE;
|
|
||||||
int running = GLFW_TRUE;
|
|
||||||
GLFWwindow* windows[4];
|
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "bfh")) != -1)
|
|
||||||
{
|
|
||||||
switch (ch)
|
|
||||||
{
|
|
||||||
case 'b':
|
|
||||||
decorated = GLFW_TRUE;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
focusOnShow = GLFW_FALSE;
|
|
||||||
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, decorated);
|
|
||||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
int left, top, right, bottom;
|
if (i > 0)
|
||||||
if (i)
|
glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_FALSE);
|
||||||
glfwWindowHint(GLFW_FOCUS_ON_SHOW, focusOnShow);
|
|
||||||
|
|
||||||
windows[i] = glfwCreateWindow(200, 200, titles[i], NULL, NULL);
|
windows[i] = glfwCreateWindow(200, 200, titles[i], NULL, NULL);
|
||||||
if (!windows[i])
|
if (!windows[i])
|
||||||
@ -143,32 +133,29 @@ int main(int argc, char** argv)
|
|||||||
glfwMakeContextCurrent(windows[i]);
|
glfwMakeContextCurrent(windows[i]);
|
||||||
gladLoadGL(glfwGetProcAddress);
|
gladLoadGL(glfwGetProcAddress);
|
||||||
glClearColor(colors[i].r, colors[i].g, colors[i].b, 1.f);
|
glClearColor(colors[i].r, colors[i].g, colors[i].b, 1.f);
|
||||||
|
|
||||||
glfwGetWindowFrameSize(windows[i], &left, &top, &right, &bottom);
|
|
||||||
glfwSetWindowPos(windows[i],
|
|
||||||
100 + (i & 1) * (200 + left + right),
|
|
||||||
100 + (i >> 1) * (200 + top + bottom));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
arrange_windows();
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
glfwShowWindow(windows[i]);
|
glfwShowWindow(windows[i]);
|
||||||
|
|
||||||
while (running)
|
for (;;)
|
||||||
{
|
{
|
||||||
for (i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
glfwMakeContextCurrent(windows[i]);
|
glfwMakeContextCurrent(windows[i]);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
glfwSwapBuffers(windows[i]);
|
glfwSwapBuffers(windows[i]);
|
||||||
|
|
||||||
if (glfwWindowShouldClose(windows[i]))
|
if (glfwWindowShouldClose(windows[i]))
|
||||||
running = GLFW_FALSE;
|
{
|
||||||
|
glfwTerminate();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwWaitEvents();
|
glfwWaitEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwTerminate();
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user