Compare commits

...

428 Commits

Author SHA1 Message Date
Camilla Löwy cad8f2f7d5 Cocoa: Initial implementation of glfwDragWindow 2017-09-28 19:14:51 +02:00
Camilla Löwy ea46ea0929 Cleanup 2017-08-04 02:41:52 +02:00
Camilla Löwy ce87a1142e Move glfwDragWindow demo to windows test 2017-08-04 02:40:09 +02:00
Felipe Ferreira da Silva a4c76fbeed Add glfwDragWindow
This is the initial implementation of glfwDragWindow, with support for
X11. The function glfwDragWindow requires only the target window to be
dragged. To make the function easier and more portable, the position of
the window and of the cursor are grabbed internally, so the end-user do
not need to pass them manually.

The example 'simple.c' was updated to include this functionality when
clicking on the client area of the window.
2017-08-04 02:38:35 +02:00
Camilla Löwy 5b7281bd41 Add glfwGetJoystickGUID
This function completes the first round of support for
SDL_GameControllerDB.

Fixes #900.
2017-07-30 16:15:12 +02:00
Camilla Löwy 85eda77d35 Update Nuklear to 1.40.0 2017-07-30 16:11:03 +02:00
Camilla Löwy 213dd2d0d6 Add glfwInitHintString
Adds string type init hints.  Adds X11 specific init hints for WM_CLASS
components.  Documentation work.

Fixes #893.
2017-07-25 23:53:52 +02:00
Camilla Löwy 00d2efb9ab Enable verbose makefiles for CI 2017-07-17 23:42:37 +02:00
Camilla Löwy 4feede6dd5 Make enabled warnings errors during CI builds
Related to #1043.
2017-07-17 23:39:39 +02:00
Camilla Löwy c0bc10427c Fix warnings in Vulkan test 2017-07-17 23:16:55 +02:00
Camilla Löwy 2d8d8f5917 Fix signedness in GLFWgamepadstate
The signedness did not match glfwGetJoystickButtons.
2017-07-17 23:16:55 +02:00
Camilla Löwy 472e5fc4a9 Fix warning 2017-07-17 23:15:48 +02:00
Camilla Löwy e55e616f1f Cleanup
Replaces tabs with spaces.  Makes code idiomatic.  Adds credit.

Closes #1043.
2017-07-13 01:37:05 +02:00
Michał Cichoń 50a228394f Win32: Fix bad call to _glfwPlatformPollJoystick
Related to #1043.
2017-07-13 01:34:08 +02:00
Michał Cichoń afbd589348 Fix function signature in null joystick backend
Related to #1043.
2017-07-13 01:28:02 +02:00
Camilla Löwy 82284b86eb Cleanup
Thanks to glfwGetKeyScancode we can now pass only a scancode to the
platform layer for glfwGetKeyName.
2017-07-13 01:26:06 +02:00
Camilla Löwy d3247a8c83 Documentation work 2017-07-13 01:26:06 +02:00
Camilla Löwy 67c9155f3b Documentation work 2017-07-12 00:21:17 +02:00
Camilla Löwy 8e899ccc29 Cocoa: Add support for MoltenVK dynamic library
Tested with MoltenVK 0.18.0.

Related to #870.
2017-07-10 21:34:02 +02:00
Camilla Löwy d55c57b504 Fix Clang -Wmissing-braces warning 2017-07-10 12:55:58 +02:00
Camilla Löwy ea6c50d9e2 Cleanup 2017-07-10 12:53:20 +02:00
Camilla Löwy 6634c47e57 Documentation work 2017-07-09 21:55:06 +02:00
Camilla Löwy 2fa90ae19f Win32: Fix capture logic ignoring last mouse button 2017-07-09 18:37:24 +02:00
Camilla Löwy 2e9aff759e Fix @ref link 2017-07-09 14:46:39 +02:00
Camilla Löwy 617c42b20a Cleanup 2017-07-09 14:01:48 +02:00
Camilla Löwy 953106e74d Add support for SDL_GameControllerDB
This adds support for importing and applying mappings from the
SDL_GameControllerDB database.

Related to #900.
2017-07-07 15:52:33 +02:00
Camilla Löwy 07bf2b166b GLX: Fix segfault when no GLXFBConfigs available
Fixes #1040.
2017-07-07 10:30:10 +02:00
Camilla Löwy 8c0512027f Fix table header text alignment
[ci skip]
2017-07-07 10:30:02 +02:00
Camilla Löwy be51c201dd Cleanup
Related to #1039.
2017-07-03 14:32:23 +02:00
David Carlier 57f872054c Fix GLAPIENTRY re-definition warning on OpenBSD
Closes #1039.
2017-07-03 14:28:44 +02:00
Camilla Löwy 9bb5e880ae Win32: Fix XInput button bit mask array size 2017-07-02 20:15:36 +02:00
Camilla Löwy 9610d68f19 Fix linguist detection for Objective-C
[ci skip]
2017-06-30 15:20:37 +02:00
Camilla Löwy 539a728063 Documentation work
[ci skip]
2017-06-30 12:45:29 +02:00
Camilla Löwy 58c05ba8ee Fix library destination for DLL platforms
Fixes #1035.
2017-06-28 12:07:39 +02:00
Camilla Löwy d5de48ab53 Report invalid constants in the appropriate base
If the expected constants are defined in hexadecimal in the header then
the error string should also use hexadecimal.

Idea by IntellectualKitty.

Related to #970.
2017-06-28 12:07:06 +02:00
Camilla Löwy 99762ad7f0 Cleanup 2017-06-15 20:03:40 +02:00
Camilla Löwy 6da26c8d6c Linux: Ignore partial state after SYN_DROPPED
Related to #1005.
2017-06-15 20:01:45 +02:00
Camilla Löwy d2952e4e92 Cleanup
Related to #1005.
2017-06-15 20:01:44 +02:00
Camilla Löwy 206f9ca4bc Linux: Fix joystick array bugs
Related to #1005.
2017-06-15 20:00:21 +02:00
Anthony Pesch d1a2ec4d20 Linux: Move to evdev for joystick input
Closes #1005.
2017-06-13 18:49:20 +02:00
Camilla Löwy 78666204a1 Linux: Fix path buffer length warning 2017-06-11 23:29:16 +02:00
Camilla Löwy 2ca9a0979e Add note on extra-cmake-modules dependency
The Wayland backend requires this package to generate headers from XML
protocol descriptions.  Although this package was created by the KDE
project, it does not depend on any part of KDE.

Fixes #1013.

[ci skip]
2017-06-09 16:35:11 +02:00
Camilla Löwy 5bcf9c76fd Linux: Fix path buffer length warning
Fixes #1025.
2017-06-08 19:29:57 +02:00
ryogo.yoshimura 4dee58d480 Cocoa: Fix conversion between NSPoint and CGPoint
GLFW still supports versions of macOS before these became the same
underlying type.

Closes #1023.
2017-06-08 16:39:02 +02:00
Camilla Löwy 32f482a6d8 Cleanup 2017-06-08 16:38:45 +02:00
Camilla Löwy 0321bec232 Documentation work
[ci skip]
2017-06-08 16:09:17 +02:00
Camilla Löwy 2bb8517e9e EGL: Fix EGL_KHR_create_context_no_error support 2017-06-08 16:09:16 +02:00
Camilla Löwy f4ea29cd06 GLX: Add GLX_ARB_create_context_no_error support 2017-06-08 16:09:16 +02:00
Camilla Löwy 52f7684487 WGL: Add WGL_ARB_create_context_no_error support 2017-06-08 16:09:15 +02:00
Camilla Löwy d2779aa765 Documentation work
[ci skip]
2017-06-08 16:09:14 +02:00
Camilla Löwy a3007b9b0e Rename thread source files
This to reflect that they now contain more than TLS.
2017-06-08 16:09:14 +02:00
Camilla Löwy 14a3fe0ac0 Make glfwGetError also provide description
Related to #970.
2017-06-08 16:08:36 +02:00
Camilla Löwy beaeb0d4af Add missing pixel format documentation
Fixes #1027.
2017-06-07 20:07:24 +02:00
Camilla Löwy c48127fa9e Fix some CSS issues caused by Doxygen 1.8.12 2017-06-06 18:02:20 +02:00
Camilla Löwy 372e908682 Remove internal header inclusion guards
Inclusion of internal headers is already both centralized and follows
strict rules.  Inclusion guards are both an unneccessary maintenance
burden and may hide inclusion order bugs.
2017-05-25 19:35:13 +02:00
Camilla Löwy bc7ebc1a89 Fix joystick test attention request
Fixes #1020.
2017-05-22 15:16:47 +02:00
Camilla Löwy 186d03b32a Cleanup
Related to #983.
2017-05-17 22:26:15 +02:00
Camilla Löwy c8ea64976f XKB: Workaround for Num Lock
Related to #983.
2017-05-17 22:26:08 +02:00
Camilla Löwy 2023095d8e XKB: Fix Unicode lookup regression
This fixes a sorting error introduced by
8597002a17.  The array must be sorted for
the binary search.
2017-05-17 22:24:26 +02:00
Denis Bernard 8597002a17 X11: Make glfwGetKeyName return UTF-8 strings
Fixes #981.
Closes #983.
2017-05-17 22:21:22 +02:00
Camilla Löwy 4f7102be26 Clarify joystick ID error message 2017-05-17 22:21:22 +02:00
Jonathan Hale e4e3e50867 Fix Travis build
By setting dist explicitly to trusty, which has cmake >= 2.8.12 in their
official package repository and installing newly non-default packages
explicitly.

Closes #1015.
2017-05-16 16:22:24 +02:00
Camilla Löwy fa0b5e1b85 Additional client API logic cleanup 2017-05-16 15:43:29 +02:00
Camilla Löwy 018ae69b33 Cleanup
Related to #985.
2017-05-16 15:43:28 +02:00
Konstantin Käfer 244d6d7823 Allow OpenGL ES header inclusion on macOS
Related to #985.
2017-05-16 15:42:51 +02:00
Konstantin Käfer d1d08ef99f Cocoa: Fix EGL support
This adds support for using GLFW with EGL backends on macOS.  While EGL
isn't available by default on macOS, there are third-party
implementations like SwiftShader.

The addition of MoltenVK support added an override to makeBackingLayer.
In non-Vulkan mode, this means that we are returning nil from that
function.  The NSGL implementation creates this layer manually later on,
but other OpenGL backends don't necessarily do that.

Closes #985.
2017-05-16 15:42:19 +02:00
Camilla Löwy 85c6168bba Fix missing type cast
Thanks, Clang!
2017-05-16 14:33:14 +02:00
Camilla Löwy 2f5e230338 Add attention request to joystick test 2017-05-11 20:10:28 +02:00
Camilla Löwy baa9cd8968 Cleanup
Closes #988.
2017-05-11 20:10:04 +02:00
Felipe Ferreira da Silva 412eb6a611 Add glfwRequestWindowAttention
Related to #988.
2017-05-11 13:36:39 +02:00
Camilla Löwy 4e8e25a521 Documentation work 2017-05-11 13:34:22 +02:00
Camilla Löwy 731ff91acd WGL: Add support for WGL_EXT_colorspace 2017-05-10 19:36:26 +02:00
Camilla Löwy b234e28d5d Win32: Stop exporting GUIDs from static library 2017-05-10 19:36:17 +02:00
Arkady Shapkin d6fcbdc38b Move CMAKE_LEGACY_CYGWIN_WIN32 to its proper place
Closes #1006.
2017-05-07 02:19:32 +02:00
Camilla Löwy f737e8ce9f Documentation work 2017-05-05 19:05:00 +02:00
Camilla Löwy 6350641f0a Add glfwGetError
Related to #970.

If you have opinions on the design or implementation of this function,
please come join us in #970 before it is frozen for release.
2017-05-03 18:30:11 +02:00
Camilla Löwy 16ddfafeaa Allow object creation from callbacks 2017-05-03 15:10:36 +02:00
pengo 4884232360 Wayland: Update serial on button callback
The serial needs to be update for starting operations like moving and
resizing a window.

Closes #992.
2017-04-13 03:59:49 +02:00
Camilla Löwy 9457cf33d1 Documentation work 2017-04-06 14:40:02 +02:00
Camilla Löwy 66b16f1fc1 X11: Add validation of RandR gamma ramp size 2017-04-05 17:53:00 +02:00
Camilla Löwy 2226e60944 Formatting 2017-04-05 17:52:03 +02:00
Camilla Löwy 9558b85f7b Documentation work
Related to #981.
2017-04-04 18:53:47 +02:00
Brandon Schaefer c9003b5547 Mir: Get ready for Mir 1.0
Clean up CMake finding and check version.  Change last remaining
deprecations.

Closes #979.
2017-03-30 00:43:03 +02:00
Camilla Löwy 9f63a8abfa Update changelog
Issue #682 was implicitly fixed by
77a8f103d8.

Closes #682.
2017-03-27 18:40:04 +02:00
Camilla Löwy 4ff66a7818 X11: Fix IM-duplicated key events leaking through
Fixes #747.
Fixes #964.
2017-03-27 02:00:31 +02:00
Camilla Löwy 72d58d7b93 Cleanup 2017-03-26 16:46:17 +02:00
Camilla Löwy 11c15b562d Remove superfluous comments 2017-03-26 16:46:17 +02:00
Camilla Löwy 9b81d72c46 X11: Fix libXi soname 2017-03-26 16:46:17 +02:00
Camilla Löwy b0277a129b Fix comment 2017-03-26 16:46:17 +02:00
Camilla Löwy 120082ee3a Add Git commit message article 2017-03-26 16:46:17 +02:00
Camilla Löwy 6abb5cbcbb Formatting 2017-03-26 16:46:17 +02:00
Camilla Löwy b215a989f5 Win32: Check for monitor object creation failure 2017-03-26 16:46:17 +02:00
Camilla Löwy 5fe4dfb511 X11: Narrow criteria for disabling RandR
Fixes #972.
2017-03-26 16:46:17 +02:00
Camilla Löwy cf2eab5b4e Cocoa: Made axis auto-calibration less jumpy 2017-03-23 17:33:05 +01:00
Camilla Löwy 55d0560746 Cocoa: Fix range handling for hats and buttons
Fixes #888.
2017-03-23 15:58:14 +01:00
Camilla Löwy 1982543cd2 Cleanup 2017-03-19 02:46:16 +01:00
Camilla Löwy aaf2800c9c Add internal TLS support
Related to #970.
2017-03-19 00:52:46 +01:00
Camilla Löwy 62414bff6e X11: Fix inverted coordinate transform 2017-03-17 14:09:07 +01:00
Camilla Löwy 2376d3b16a Formatting 2017-03-17 01:11:28 +01:00
Camilla Löwy 6a65341e14 X11: Fix multiple issues in XDND support
The code blindly expected UTF8_STRING for files.  It did not downgrade
based on source protocol version.  It did not handle hostnames in
text/uri-list data.  It did not specify the source time stamp when
converting the selection.  It did not search the XdndTypeList when
necessary.  It did not ignore sources that specified invalid versions.

While better, this is still not fully conformant.  Hostnames are not
validated and it does not guard against source crashes.

Fixes #968.
2017-03-16 23:41:06 +01:00
Camilla Berglund bff31f006e Formatting 2017-03-16 16:22:00 +01:00
Camilla Berglund 7410346c5c Cocoa: Allow undecorated windows to become main 2017-03-16 15:46:21 +01:00
Camilla Löwy 27a8b3c17b EGL: Add support for EGL_KHR_context_flush_control 2017-03-15 17:37:33 +01:00
Camilla Löwy 7c070f55be EGL: Add support for Cygwin 2017-03-15 14:40:21 +01:00
Camilla Löwy 3d8aa53573 Cocoa: Fix full screen window not being restorable
Once a full screen window was iconified, it would appear to restore but
then disappear.

Fixes #848.
2017-03-15 01:27:46 +01:00
Camilla Löwy 7c88c92778 Cocoa: Fix window rect on leaving video mode
Fixes #748.
2017-03-14 21:23:48 +01:00
Camilla Löwy 21355e31db Cleanup 2017-03-14 20:39:18 +01:00
Camilla Löwy 97dbd8b63b Win32: Fix monitor event emission
Fixes #784.
2017-03-14 19:21:57 +01:00
Camilla Löwy 0df9cc2fc5 Win32: Improve monitor enumeration
This changes enumeration to add as a GLFW monitor any active adapter
without displays, even if other active adapters do have displays.

Related to #441.
Fixes #960.
2017-03-14 19:10:57 +01:00
Camilla Löwy e2ce3026a0 Rename license file 2017-03-14 14:49:30 +01:00
Camilla Löwy 6a8ade99c7 Cocoa: Remove errors emitted on headless systems
Related to #958.
2017-03-10 14:44:55 +01:00
Camilla Löwy 43fc399cd1 Add hat button toggling to joystick test 2017-03-08 12:39:16 +01:00
A. Tombs 5ae781586f X11: Handle Selection* events despite NULL window
X11 event processing currently discards events that can not be mapped to
a current GLFW window.  However, this breaks clipboard functionality by
failing to respond to SelectionRequest and SelectionClear events.

This commit moves processing of these important clipboard events to
before the NULL window test so that they are always considered.

Fixes #961.
Closes #963.
2017-03-07 19:24:31 +01:00
Camilla Löwy 798d7c6d68 Implement glfwGetJoystickHats
This moves the buttons-as-hats logic to shared code and adds the
GLFW_JOYSTICK_HAT_BUTTONS input mode as a way to disable this legacy
behavior.

Fixes #889.
2017-03-06 03:23:29 +01:00
IntellectualKitty 368dec7ac7 Add glfwGetJoystickHats
This merges the public part of the glfwGetJoystickHats work by
@IntellectualKitty.  The implementation needs replacing due to
refactoring in preparation for gamecontrollerdb support.

Closes #906.
2017-03-05 23:20:07 +01:00
Camilla Löwy 12dcfd08b8 Documentation work
[ci skip]
2017-03-05 23:20:03 +01:00
Emmanuel Gil Peyrot 0e0862cfc7 Wayland: Fix broken build
Regression caused by e9560ef021.
2017-03-03 17:51:40 +00:00
Camilla Löwy 5b306f0390 Cleanup 2017-03-03 14:22:38 +01:00
Camilla Löwy d88347ee7d Mir: Fix broken build
Regression caused by e9560ef021.
2017-03-02 17:52:32 +01:00
Camilla Löwy 7a8516d296 Cleanup 2017-03-01 04:36:00 +01:00
Camilla Löwy c50aba1335 Cocoa: Add support for MainMenu.nib loading 2017-03-01 04:36:00 +01:00
Camilla Löwy 6d9a58bfef Add glfwInitHint
This allows setting hints that control how the library is initialized,
transforming more compile-time options into run-time ones.
2017-03-01 04:35:41 +01:00
Camilla Löwy 071a049f07 Documentation work
[ci skip]
2017-02-28 22:54:50 +01:00
Camilla Löwy e019f7e7f2 Remove misleading platform API documentation
[ci skip]
2017-02-28 22:54:45 +01:00
Camilla Löwy 315c9455d5 OSMesa: Use framebuffer size for framebuffer 2017-02-28 22:21:42 +01:00
Camilla Löwy 97b0c645bf Remove unused stub 2017-02-28 22:21:02 +01:00
Camilla Löwy 53f46d32e2 Make OSMesa backend an almost proper null backend
It still depends on POSIX time and TLS.
2017-02-28 21:57:43 +01:00
Camilla Löwy e9560ef021 Add GLFW_OSMESA_CONTEXT_API
This allows the creation of OpenGL contexts via OSMesa on existing
platforms.  It does not add a compile- or link-time dependency on
OSMesa.

Fixes #281.
2017-02-28 20:38:10 +01:00
Camilla Löwy a44f2c0e65 Win32: Fix VC++ warning 2017-02-28 00:07:37 +01:00
Camilla Löwy c54b5da403 Win32: Fix Vulkan library paths for 1.0.42.0 SDK
Libraries have moved from Bin and Bin32 to Lib and Lib32.

Fixes #956.
2017-02-27 23:55:52 +01:00
Camilla Löwy c745f434f5 Win32: Fix VULKAN_STATIC_LIBRARY not set on 32-bit 2017-02-27 23:51:35 +01:00
Camilla Löwy 3fa6f48ac6 Documentation work
Related to a570d0a129.
2017-02-27 01:31:20 +01:00
Camilla Löwy ce8fe645f4 Cleanup 2017-02-26 22:22:53 +01:00
Camilla Löwy 79eaf49ec0 Fix warning in Nuklear with Clang 2017-02-26 22:20:30 +01:00
Camilla Löwy 9950d8a319 Cleanup 2017-02-26 22:18:47 +01:00
Camilla Löwy 4928e2bf0a Clarify undocumented platform errors 2017-02-26 20:09:46 +01:00
Camilla Löwy a570d0a129 X11: Use XI_RawMotion for disabled cursor motion
Related to #125.
2017-02-26 18:48:04 +01:00
Camilla Löwy 918b4e81d2 Win32: Move to WM_INPUT for disabled cursor motion
Related to #125.
2017-02-26 18:48:03 +01:00
Camilla Löwy dd96d0ac93 Win32: Fix mouse button messages lost by capture
Fixes #954.
2017-02-26 18:48:02 +01:00
Camilla Löwy 106a617fa8 Update Nuklear to 1.33.0 2017-02-26 18:47:53 +01:00
Camilla Löwy 3817b4e1c5 Add more assertions 2017-02-23 17:47:41 +01:00
Camilla Löwy 2ba461e348 Formatting 2017-02-23 17:46:59 +01:00
Camilla Löwy 5352e2caa0 X11: Fix read past top of stack on 64-bit
Fixes #951.
2017-02-23 03:27:23 +01:00
Camilla Löwy 463930761b Documentation work
[ci skip]
2017-02-20 16:35:02 +01:00
Camilla Löwy 980f955f6c Fix undefined behavior
Fixes #950.
2017-02-16 05:23:10 +01:00
Camilla Löwy f69829f7b4 Documentation work
[ci skip]
2017-02-14 14:56:29 +01:00
Camilla Löwy c3fd757b03 Documentation work
[ci skip]
2017-02-11 21:17:32 +01:00
Camilla Löwy 343288c1f6 Fix line endings
[ci skip]
2017-02-11 21:17:26 +01:00
Camilla Löwy 355b46e6c5 Win32: Fix screensaver and blanking prevention
On Vista and later, Handling WM_SYSCOMMAND is not enough to prevent
password protected screensavers or monitor blanking.

Fixes #851.
2017-02-10 02:28:55 +01:00
Camilla Löwy 366b90be1a Documentation work 2017-02-10 01:55:03 +01:00
Camilla Löwy 77a8f103d8 Add GLFW_COCOA_GRAPHICS_SWICTHING
This provides control over whether the context should participate in
macOS Automatic Graphics Switching.

Closes #377.
Closes #935.
2017-02-10 01:29:29 +01:00
Camilla Löwy 4250725a60 Fix missing include in Nuklear GLFW backend 2017-02-08 15:32:34 +01:00
Camilla Löwy b151904316 Remove not-fixed issue number 2017-02-08 06:53:04 +01:00
Camilla Löwy 558afefc04 X11: Fix sonames for dynamically loaded libraries
Fixes #941.
2017-02-08 06:53:04 +01:00
Camilla Löwy 21eabd3938 Documentation work 2017-02-08 06:53:04 +01:00
Camilla Löwy 0c090a8c8b Perform full termination on platform init failure 2017-02-08 06:53:04 +01:00
Camilla Löwy 926d2beddb Move initialized flag into library struct 2017-02-08 06:53:04 +01:00
Camilla Löwy 98bdd36231 Fix glfwVulkanSupported semantics 2017-02-07 21:28:50 +01:00
Camilla Löwy 8e870d4cc0 Win32: Fix bad error from glfwVulkanSupported
A VK_ERROR_OUT_OF_HOST_MEMORY error would be passed on to client code on
systems that had a Vulkan loader but no ICD.

Fixes #916.
2017-02-07 20:08:14 +01:00
Camilla Löwy afb5449ca4 Update Nuklear to 1.20 2017-02-07 19:12:22 +01:00
Camilla Löwy 5a74b5008d Cleanup
Related to #842.
2017-02-06 15:16:27 +01:00
Liam Middlebrook 72ac5badb0 Add GLFW_CENTER_CURSOR
Adds a hint for controlling whether the cursor is centered over newly
created full screen windows.

Fixes #749.
Closes #842.
2017-02-06 15:16:26 +01:00
Camilla Löwy 3af0c47c97 Update Vulkan headers to 1.0.39.1 SDK 2017-02-06 15:16:22 +01:00
Camilla Löwy a46c95c7f2 Clarify requirements for receiving joystick events
As of c5694b3013 this is now consistent
enough across platforms to describe.

Fixes #887.

[ci skip]
2017-02-01 05:40:48 +01:00
Camilla Löwy 6801478a13 Lengthen lifetime of joystick information pointers
This is possible because publicly available joystick information is now
managed by shared code and there is now a joystick callback.

[ci skip]
2017-02-01 05:37:38 +01:00
Camilla Löwy ef5a21496c X11: Fix set not being reset each call to select 2017-02-01 03:16:29 +01:00
Camilla Löwy 67a55efa27 Add null joystick backend
This prepares the X11 backend to support other joystick APIs, for
example the FreeBSD libusb one.
2017-02-01 03:07:25 +01:00
Camilla Löwy c5694b3013 Linux: Fix joystick disconnection detection
Joystick disconnection was not dectected by the event processing
functions and required calling a joystick function.

Fixes #932.
2017-01-31 00:21:53 +01:00
Camilla Löwy 466347a335 Documentation work 2017-01-30 18:15:23 +01:00
Camilla Löwy 9cfaf0944c Fix file API version number 2017-01-30 16:52:49 +01:00
Camilla Löwy bfd564f257 Move internals to shared joystick objects
Preparation for gamecontrollerdb support and the gamepad API.
2017-01-30 16:52:49 +01:00
Camilla Löwy 43c1910453 Win32: Cleanup 2017-01-29 19:50:41 +01:00
Camilla Löwy 260dbf0a1d Win32: Cleanup 2017-01-29 19:50:35 +01:00
Camilla Löwy f3e20ca437 Pass scancode with synthetic key release events 2017-01-29 16:44:38 +01:00
Camilla Löwy a2867ff6ea Cleanup 2017-01-29 16:44:37 +01:00
Camilla Löwy 9689f7b925 Remove superfluous comments 2017-01-29 16:44:37 +01:00
Camilla Löwy 2037b5ce39 Fix matrix not being fully initialized
Regression introduced with a28236d939
and found by @cher-nov.

Closes #937.
2017-01-29 16:44:14 +01:00
Emmanuel Gil Peyrot f4c5e6568e Wayland: Commit shell surface creation
This fixes any program using hidden windows, like tests/windows.c.
2017-01-26 18:13:15 +00:00
Emmanuel Gil Peyrot 865bf67b1a OSMesa: Fix context struct indentation 2017-01-26 18:13:12 +00:00
Camilla Löwy f474b6da85 Wayland: Fix missing scancode for Space key
Fixes #936.
2017-01-26 17:02:10 +01:00
Camilla Löwy a578bc2fad Mir: Fix missing scancode for Space key
Related to #936.
2017-01-26 17:02:10 +01:00
Camilla Löwy 5a11d19940 Start adding links to GLU replacements 2017-01-24 21:45:03 +01:00
Camilla Löwy c28778e28c Win32: Improve platform error messages
Related to #733.
2017-01-20 01:35:24 +01:00
Camilla Löwy c873327fe3 Fix NOTFOUND paths being added as dependencies
Fixes #930.
2017-01-20 01:29:46 +01:00
Camilla Löwy d25b427efe Remove URL 2017-01-20 01:17:16 +01:00
paul4334 9cd378caa7 GLX: Check whether client string is NULL
In very rare cases the X server reports the GLX extension as present but
functions return invalid fallback values.

Closes #912.
2017-01-19 03:46:49 +01:00
Camilla Löwy b0258803c6 X11: Clarified broken RandR error messages 2017-01-16 18:26:53 +01:00
Camilla Löwy 77eb94409c X11: Fix segfault on Cygwin/X RandR 1.5 2017-01-16 17:53:56 +01:00
Camilla Löwy 0735250eb1 X11: Fix potential window property data leaks 2017-01-16 17:53:28 +01:00
Camilla Löwy fa21cd13d2 Cleanup
[ci skip]
2017-01-15 15:21:39 +01:00
Josh Kilmer d74fffd5de Win32: Fix FindVulkan.cmake bitness test
Bitness test was VC++ specific.

Closes #928.
2017-01-15 15:11:31 +01:00
Camilla Löwy e7722af9a2 Cleanup 2017-01-12 05:30:56 +01:00
Camilla Löwy 0cd409bd6d Comment work 2017-01-11 19:55:33 +01:00
Camilla Löwy 2ea7f9769a OSMesa: Fix invalid window frame size 2017-01-10 19:01:10 +01:00
Camilla Löwy 221451b817 Cleanup 2017-01-10 15:46:00 +01:00
Camilla Löwy 48a795c101 Merge single-use function _glfwFreeMonitors
All other uses were elminiated by _glfwInputMonitor.
2017-01-10 15:01:55 +01:00
Camilla Löwy f29c963030 Add MoltenVK link
[ci skip]
2017-01-03 19:41:02 +01:00
Camilla Löwy dd81707992 EGL: Fix test for EGL_RGB_BUFFER 2017-01-02 16:02:40 +01:00
Camilla Löwy ec410fb6fe Cocoa: Enable EGL 2017-01-02 15:32:55 +01:00
Camilla Löwy 3edaa5280d Add GLFW_INCLUDE_ES32 2017-01-02 06:06:01 +01:00
Camilla Löwy 51e415a026 Cocoa: Fix CGDisplayModeCopyPixelEncoding cutoff 2017-01-02 06:06:01 +01:00
Camilla Löwy 04f559e28d Restructure monitor enumeration
This way is both kinder on event-based enumeration and less work to
unwind allocations for when properly implementing GLFW_OUT_OF_MEMORY.
2017-01-02 06:03:02 +01:00
Camilla Löwy ecda05af29 Cocoa: Implement window cascading
Related to #195.
2017-01-02 04:49:16 +01:00
Camilla Löwy 4661315192 Add GLFW_COCOA_FRAME_AUTOSAVE
Fixes #195.
2017-01-01 19:58:34 +01:00
Camilla Löwy 0f488ac286 Win32: Fix underflow in deadzone logic
Fixes #910.
2016-12-19 13:13:46 +01:00
Camilla Löwy e649708cb2 X11: Make more use of XRRGetScreenResourcesCurrent
Closes #877.
2016-12-18 15:49:17 +01:00
Camilla Löwy f656d95339 Documentation work 2016-12-15 20:21:07 +01:00
Camilla Löwy 6eae8f22dc X11: Load Xxf86vm at run-time 2016-12-11 00:05:15 +01:00
Camilla Löwy 21eeaffc23 Documentation fix
Doxygen cannot handle line breaks in Markdown links.
2016-12-09 01:32:09 +01:00
Camilla Löwy 831426ca63 Documentation work
[ci skip]
2016-12-08 17:08:53 +01:00
Camilla Löwy 58ceab5f1e Add GLFW_COCOA_RETINA_FRAMEBUFFER
Look, a can of worms!  I wonder what's inside.

This adds the first platform specific window hint, transforming
a compile-time option to a run-time per-window one.
2016-12-08 16:56:05 +01:00
Camilla Löwy 766a9dc9fd Documentation work
Related to glfw/website#34.
2016-12-08 16:56:05 +01:00
Camilla Löwy 0e8ba24f32 Formatting 2016-12-08 16:56:05 +01:00
Camilla Löwy 744cee6ec9 Cleanup 2016-12-08 16:56:05 +01:00
Camilla Löwy 32eb50b75e Move to Vulkan style function typedefs
PFN_FunctionName is more readable than SCREAMSOUP_T.

Context creation API function typedefs are kept as-is where the original
header provided them, for compatibility and familiarity reasons.
2016-12-08 16:56:05 +01:00
Camilla Löwy 887e58bd21 Cleanup
Related to #882.
2016-12-06 17:39:51 +01:00
Sergey Tikhomirov 11a2413476 Cocoa: Fix issue with application sandboxing
Fixes #816.
Closes #882.
2016-12-06 17:39:51 +01:00
Camilla Löwy be4eb6fb2b OSMesa: Add missing stubs 2016-12-06 16:11:38 +01:00
Camilla Löwy 9e56099edd Add glfwSetWindowAttrib
This function allows updating the GLFW_DECORATED, GLFW_RESIZABLE,
GLFW_FLOATING and GLFW_AUTO_ICONIFY attributes for existing windows.

Fixes #537.
2016-12-06 15:59:18 +01:00
Camilla Löwy d92bb41e25 Fix typo
[ci skip]
2016-12-06 13:59:04 +01:00
Camilla Löwy 69e351b44a Cleanup
[ci skip]
2016-12-06 13:58:52 +01:00
Camilla Löwy ce161c2c02 Documentation work
[ci skip]
2016-12-06 13:58:45 +01:00
Camilla Löwy f383f7721c Fix warnings in Nuklear 2016-12-05 14:17:33 +01:00
Camilla Löwy 1252016b9c Add remaining GLSL version directives
Related to #864.
2016-12-05 14:16:56 +01:00
A. Tombs 1b17a5293c Add version directives to GLSL shaders
Although not technically required, I believe it is best practice for
shaders to specify which version of the GLSL spec they conform to.

Closes #864.
2016-12-05 14:06:39 +01:00
Camilla Löwy 3e4752f99e Fix warnings in Nuklear GL2 backend 2016-12-03 20:46:36 +01:00
Camilla Löwy f44307da4e Update Nuklear to 1.18
Fixes #907.
2016-12-03 20:35:17 +01:00
Camilla Löwy fd127d59fa Cocoa: Improve OpenGL version restriction messages
Fixes #904.
2016-12-03 20:15:26 +01:00
Camilla Löwy 29b72c59f3 Documentation work
Related to #902.

[ci skip]
2016-12-03 20:15:26 +01:00
Camilla Löwy 11376a2dd0 Cleanup 2016-12-03 20:06:24 +01:00
Camilla Löwy cc9168bda1 Win32: Fix build on VC++ 2008
This is not official support for VC++ 2008.

Fixes #821.
2016-12-03 20:06:23 +01:00
Camilla Löwy f4d0c83181 Paperwork done 2016-11-30 14:00:41 +01:00
Camilla Berglund 096efdf798 Documentation work 2016-11-16 17:05:12 +01:00
Camilla Berglund 20735bf840 Add offscreen example to IDE folder 2016-11-16 17:04:23 +01:00
Camilla Berglund e3c3e780ae Update .gitignore 2016-11-16 15:13:20 +01:00
Camilla Berglund 9190cf8796 Cocoa: Disable deprecated function on macOS 10.12+
CGDisplayModeCopyPixelEncoding is deprecated starting with macOS 10.12.
2016-11-16 15:10:29 +01:00
Camilla Berglund d19a21bd01 Cocoa: Monitor name cleanup
Only retrieve the display info dictionary once.  Remove non-standard
function name.
2016-11-16 15:09:07 +01:00
Matthew Henry 94b8486d4b Cocoa: Replace deprecated CGDisplayIOServicePort
This replaces CGDisplayIOServicePort with manually finding a service
port with matching vendor and product IDs.  This may technically not be
the one corresponding to the display ID, but it is only used to retrieve
the human-readable make/model string.

This could be cleaned up and refined a bit by comparing more display
attributes when available, but it gets the job done.

Fixes #165.
Closes #192.
Closes #508.
Closes #511.
2016-11-16 15:06:37 +01:00
Denis cce430fbfa Cocoa: Fix typo
Closes #897.
2016-11-16 04:07:16 +01:00
Camilla Berglund 5b8051581e OSMesa: Allow cursor creation 2016-11-09 01:36:24 +01:00
Camilla Berglund 0e8d129efb OSMesa: Context creation compliance fixes 2016-11-09 01:36:24 +01:00
Camilla Berglund 62012e3c68 OSMesa: Add fallback to OSMesaCreateContextExt 2016-11-09 01:36:23 +01:00
Camilla Berglund b8c71e7f2d Add offscreen rendering example 2016-11-09 01:36:23 +01:00
Camilla Berglund ac83639631 Add stb_image_write 2016-11-09 01:36:23 +01:00
Camilla Berglund fef21361c5 OSMesa: Cleanup
Fixes formatting, semantics and documentation.  Adds
glfwGetOSMesaContext.  Adds support for OSMesa context attributes.
Updates changelog and credits.  Adds license and copyright headers.
Removes superfluous code (the shared code provides many conveniences).
Removes loading of unused OSMesa functions.  Removes empty platform
structs.  Fixes version string format.  Removes build dependency on
the OSMesa header and library (only the library is needed and only at
runtime).

Closes #850.
2016-11-09 01:36:21 +01:00
Jason Daly 368fa9475d Add headless OSMesa backend
Allows creation and drawing to in-memory OpenGL contexts.

This backend does not provide input.

Related to #850.
2016-11-09 01:23:43 +01:00
Camilla Berglund a90ee65f7b Add definition of GLAPIENTRY 2016-11-08 12:39:18 +01:00
Camilla Berglund e83be1d73a Note that mode switching does not affect context 2016-11-08 12:19:06 +01:00
Camilla Berglund e8c3e54dda Documentation work
[ci skip]
2016-11-07 19:53:42 +01:00
Camilla Berglund 2aee114950 Clarify glfwinfo output for no Vulkan extensions 2016-11-07 19:53:30 +01:00
Camilla Berglund 4d322a97e1 Fix Vulkan extension count when none were found 2016-11-07 19:53:30 +01:00
Emmanuel Gil Peyrot 8210f89b12 Wayland: Set a proper name for outputs.
glfwGetMonitorName()’s documentation says “this function returns a
human-readable name”, which “typically reflects the make and model of
the monitor”.  We get these two strings in the geometry event, so we
only set the name at this point.
2016-11-04 09:58:45 +00:00
Emmanuel Gil Peyrot a28baabefe Allow a monitor to be created without a name. 2016-11-04 09:57:59 +00:00
Camilla Berglund e94d16667b Cocoa: Add basic support for Vulkan via MoltenVK
This adds basic support for MoltenVK, a Vulkan implementation on top of
Metal, on macOS 10.11 and later.  It looks for MoltenVK in the process
via RTLD_DEFAULT symbol lookup if _GLFW_VULKAN_STATIC is disabled.

glfwCreateWindowSurface now creates and sets a CAMetalLayer for the
window content view, which is required for MoltenVK to function.

You must help CMake find MoltenVK for the Vulkan test to be built.

Fixes #870.
2016-11-01 21:39:54 +01:00
Camilla Berglund c3db1cae3f Fix glfwGetInstanceProcAddress for static linking 2016-11-01 21:34:26 +01:00
Camilla Berglund 017162e3fd Cocoa: Stop searching for system frameworks 2016-11-01 21:34:26 +01:00
Camilla Berglund fef25ea934 Emit all Vulkan init errors from init function 2016-11-01 21:34:26 +01:00
Camilla Berglund a9282bad29 Disable all dl* calls for _GLFW_VULKAN_STATIC 2016-11-01 21:34:26 +01:00
Camilla Berglund 67931bdeb2 Replace last @remarks with @remark 2016-11-01 21:34:26 +01:00
Camilla Berglund 85f867983f Update Vulkan test to 1.0.26.0
Fixes #727.
Fixes #758.
2016-11-01 21:34:26 +01:00
Camilla Berglund ec17161651 Note that mode switching does not affect context 2016-11-01 21:34:26 +01:00
Camilla Berglund 3d4bd9667a Win32: Fix joystick error message prefix 2016-10-25 21:28:21 +02:00
Camilla Berglund 7420814fe2 Win32: Poll only helper window messages at init 2016-10-25 21:25:04 +02:00
Camilla Berglund 8d6f265441 Update default name from OS X to macOS
Note that earlier releases are still referred to by their proper names;
OS X <version> or Mac OS X <version>.
2016-10-20 00:53:37 +02:00
linkmauve bc8b0480e9 Wayland: Document when behaviour differs
This should describe all of the Wayland-specific points, mostly in
three categories:
- Missing GLFW features, for example window frame, screensaver
  inhibition, clipboard or file drop.
- Missing protocols, like setting gamma on a monitor or specifying a
  window icon.
- Fundamental incompatibilities with Wayland concepts, like trying to
  handle global positioning of a window in a 2D space, trying to bring
  a window to front, or trying to change the monitor’s mode.

Closes #881.
2016-10-16 16:52:39 +02:00
Emmanuel Gil Peyrot 046d281abc Wayland: Implement compose key for character input
This commit has been copied almost verbatim from Bryce Harrington’s
patch against Weston’s toytoolkit[1].  He gave his agreement to
relicense it under zlib[2].

[1] https://patchwork.freedesktop.org/patch/114661/
[2] https://github.com/glfw/glfw/pull/879#issuecomment-252988257
2016-10-16 13:51:59 +01:00
Camilla Berglund efc6b35615 Rename joystick ID variables 2016-10-16 14:07:18 +02:00
Camilla Berglund bf747e32b4 Remove unused variables in gamma test 2016-10-16 14:07:18 +02:00
Camilla Berglund ef15735161 Make Escape exit threads test 2016-10-16 14:07:18 +02:00
Camilla Berglund 99c65bb67c Cleanup
Related to #883.
2016-10-16 13:59:21 +02:00
Sergey Tikhomirov 967e837c73 Cocoa: Fix 'first responder' error on macOS 10.12
Error message is displayed during the startup because Cocoa view is set
as the first responder for window but this view isn't in this window
(actually it is not in any window at all).

Fixes #876.
Closes #883.
2016-10-16 13:58:52 +02:00
Camilla Berglund ca084d40c1 Cleanup
Related to #852.
2016-10-14 01:05:23 +02:00
Mário Freitas 238ebb600d Cocoa: Fix assert on disabling window aspect ratio
When disabling window aspect ratio, a system assert would trigger.  The
correct way to disable window aspect ratio is to set a resize increment.

Closes #852.
2016-10-14 01:05:23 +02:00
Emmanuel Gil Peyrot a49601ba87 Wayland: Rename snake_case identifiers to camelCase for consistency 2016-10-12 14:13:52 +01:00
Emmanuel Gil Peyrot aa10ec6e45 Wayland: Replace all deprecated xkbcommon aliases. 2016-10-11 01:49:23 +01:00
Emmanuel Gil Peyrot be935debe9 Wayland: Properly unref all xkbcommon objects. 2016-10-11 01:49:23 +01:00
Emmanuel Gil Peyrot 1c8a74b661 Wayland: Properly destroy all bound objects. 2016-10-11 01:49:23 +01:00
Camilla Berglund 73ddbc3acd Cocoa: Add workaround for hasty deprecation 2016-10-09 13:11:52 +02:00
Camilla Berglund 7f9840cecf Cocoa: Fix macOS 10.12 deprecation warnings 2016-10-09 01:39:31 +02:00
Camilla Berglund cc3036860a Add list window to joystick test 2016-10-06 19:08:35 +02:00
Camilla Berglund 2af40c3fe6 Update Nuklear to 1.156 2016-10-06 19:07:47 +02:00
Camilla Berglund ea1958a948 Replace sprintf with snprintf 2016-09-30 05:31:07 +02:00
Camilla Berglund 9d42e146e7 Add aspect ratio to monitor test mode listing 2016-09-30 03:44:13 +02:00
Camilla Berglund c156b50e4c Add glfwSetWindowMaximizeCallback
Fixes #778.
2016-09-29 01:24:56 +02:00
Camilla Berglund 3752d68e7d Fix Clang warnings in Nuklear 2016-09-29 01:24:56 +02:00
Camilla Berglund cb860e8150 Fix gamma test rendering using wrong unit 2016-09-29 01:24:56 +02:00
Camilla Berglund 434238fcd4 Fix checks for Vulkan surface extension presence 2016-09-29 01:24:56 +02:00
Camilla Berglund 2d10547266 Add missing changelog issue number 2016-09-29 01:06:40 +02:00
Camilla Berglund f9a21281c4 Cleanup
Related to #871.
2016-09-28 23:51:08 +02:00
Kyle Brenneman d590eb074f Add support for EGL_KHR_get_all_proc_addresses
If EGL_KHR_get_all_proc_addresses extension is supported, then don't try
to load a separate client library. Instead, just use eglGetProcAddress
to load everything.

This can also avoid problems with trying to use OpenGL functions from
libGL.so.1 (which is the GLX library) when an EGL context is current.

Closes #871.
2016-09-28 22:50:22 +02:00
Camilla Berglund 66ff4aae89 Convert joystick test to Nuklear 2016-09-27 02:13:55 +02:00
Camilla Berglund 450d0d69af Convert gamma test to Nuklear 2016-09-27 02:13:42 +02:00
Camilla Berglund 28889954ef Use glad booleans in glfwinfo 2016-09-26 14:55:55 +02:00
Camilla Berglund f0a55df963 Cleanup 2016-09-26 13:26:36 +02:00
Camilla Berglund 40fff219b5 Add Nuklear 2016-09-25 14:12:04 +02:00
Camilla Berglund 2ed818bc03 Move to GL_KHR_debug
Thank you, @linkmauve.
2016-09-23 14:27:20 +02:00
Camilla Berglund 9017eaee08 Add debug extension support to sharing test 2016-09-22 01:43:26 +02:00
Camilla Berglund 38aae024cd Update glad, add debug extensions 2016-09-22 01:09:36 +02:00
Camilla Berglund 1fc11c27e7 Fix broken GLSL in sharing test
Thank you, Intel, for sticking to the spec.
2016-09-21 18:19:15 +02:00
Camilla Berglund c4a8930909 Cleanup 2016-09-21 16:23:38 +02:00
Camilla Berglund a280c97321 Convert reopen test to GL2 2016-09-21 16:21:03 +02:00
Camilla Berglund dfd1c85916 Clarify sharing test output 2016-09-21 16:20:04 +02:00
Camilla Berglund fc86d741db Fix copypaste mistake 2016-09-20 15:01:15 +02:00
Camilla Berglund ca38af0d83 Convert sharing test to GL2 2016-09-20 15:00:18 +02:00
Camilla Berglund f7584bf14c Convert cursor test to GL2 2016-09-19 22:19:20 +02:00
Camilla Berglund 0090ce3df7 Update Vulkan headers to 1.0.26.0 SDK 2016-09-14 23:27:34 +02:00
Camilla Berglund 433db8f9f9 Allow combining Vulkan and GL/GLES header macros 2016-09-14 22:59:12 +02:00
Camilla Berglund 7e9e321c38 Add @ref tags for Vim syntax highlighting 2016-09-14 22:59:11 +02:00
Camilla Berglund 6ac1ed18ea Formatting 2016-09-14 22:59:10 +02:00
Camilla Berglund 54930ddd33 Check only for relevant Vulkan extensions
Related to #858.
2016-09-14 22:59:03 +02:00
Camilla Berglund 3e59b7345c Fix early-out in Vulkan extension check
Related to #858.
2016-09-14 18:15:09 +02:00
Camilla Berglund 838c4e938c Win32: Allow iconifying undecorated windows
Fixes #861.
2016-09-14 18:12:21 +02:00
Camilla Berglund f79a52fe9b Win32: Make glfwPostEmptyEvent use helper window 2016-09-14 13:07:52 +02:00
Emmanuel Gil Peyrot 2eb1657d91 Wayland: Only input a character on GLFW_PRESS action
Closes #804.
2016-09-13 13:09:25 +09:00
Camilla Berglund e6a32db7b9 Cleanup 2016-09-07 16:49:29 +02:00
Brandon Schaefer acce7ec9cf Mir: Add cursor mode support
Implements a few other missing functions. Cleaning up naming convention
as well.

Fix FindMir.cmake was not finding the correct mirclient.so when
you wanted something other then the system library.

Closes #839.
2016-09-07 16:49:29 +02:00
Camilla Berglund fbb2d5e10d Convert tearing test to GL2 2016-09-07 16:49:29 +02:00
Camilla Berglund f86edf8d3c Remove GL1 from gamma test 2016-09-07 16:49:28 +02:00
Camilla Berglund 08ba147241 Remove GL1 from clipboard test 2016-09-07 16:49:28 +02:00
Camilla Berglund 2b6a139526 Make Escape exit msaa test 2016-09-07 16:49:28 +02:00
Camilla Berglund 9f60cd18e3 Convert msaa test to GL2 2016-09-07 16:49:28 +02:00
Camilla Berglund ac7b3e405c Cleanup 2016-09-07 16:49:28 +02:00
Camilla Berglund bb3cb8f233 Cleanup
Clean up code and documentation for glfwGetKeyScancode and add
implementation for Wayland and Mir.

Related to #830.
2016-09-07 16:46:48 +02:00
Michael Stocker e745b0dd47 Add glfwGetKeyScancode
Allows retrieval of platform scancode from GLFW_KEY_*.  Implemented for
Win32, Cocoa and X11.  Stubs for Mir and Wayland.

Closes #830.
2016-09-07 16:38:22 +02:00
Camilla Berglund f17d60da64 Add scancode arrays for Wayland and Mir
Related to #830.
2016-09-07 16:33:41 +02:00
Camilla Berglund afb6e485b7 X11: Make selection event checks include window 2016-09-07 16:33:41 +02:00
Camilla Berglund ccfd6dde45 X11: Make clipboard IPC use helper window 2016-09-07 16:33:41 +02:00
Camilla Berglund 706868dad8 X11: Make glfwPostEmptyEvent use helper window 2016-09-07 16:33:41 +02:00
Camilla Berglund 3b3a1390ad X11: Add IPC helper window 2016-09-07 16:33:41 +02:00
Camilla Berglund fafe1732b5 Cleanup 2016-09-07 16:33:41 +02:00
Camilla Berglund 5ff7d9505f Simplify Vulkan extension checks
Related to #478.
2016-09-07 16:31:18 +02:00
Camilla Berglund 2e6a110181 Add credit
Add missing credit for 1592b40e25.
2016-08-22 16:12:04 +02:00
Camilla Berglund 1592b40e25 Fix particles stutter caused by malformed timeout
Closes #836.
2016-08-22 15:55:29 +02:00
Camilla Berglund 9cd0c101f0 Fix glfwMaximizeWindow not checking window mode 2016-08-21 17:43:40 +02:00
Camilla Berglund 3d62c9ed9d Update .gitignore 2016-08-18 23:59:52 +02:00
Camilla Berglund 53fafad915 Start 3.3 2016-08-18 23:55:49 +02:00
Camilla Berglund 999f3556fd Documentation work 2016-08-18 13:32:27 +02:00
Camilla Berglund 4f5731ac39 Add description of 3.2.1 release 2016-08-17 16:09:11 +02:00
Camilla Berglund 4aafdea5a7 X11: Fix glfw*WindowPos operating on window frame
Fixes #800.
2016-08-17 01:45:41 +02:00
Camilla Berglund c18d3aecbc Cocoa: Remove duplicate includes
Fixes #838.
2016-08-17 01:39:47 +02:00
Camilla Berglund f1c536fe13 X11: Fix BadMatch on XSetInputFocus
Input focus was in some cases set before the window was visible (ICCCM
section 4.2.2).

Related to #798.
Fixes #789.
2016-08-12 14:01:03 +02:00
Camilla Berglund ad9233e620 X11: Clean up event wait timeout logic
Simplify interface and implement timeout updating.
2016-08-12 13:33:21 +02:00
Camilla Berglund f88a609000 X11: Only unmaximize visible windows 2016-08-12 13:33:21 +02:00
Camilla Berglund 80ba9944e5 Remove msvcrt recommendation 2016-08-12 13:33:03 +02:00
Camilla Berglund 0f12be7549 Documentation work 2016-08-12 01:57:17 +02:00
Camilla Berglund b581799c9a Fix comment 2016-08-12 01:46:21 +02:00
Camilla Berglund 067d1d6935 Cleanup 2016-08-12 01:46:21 +02:00
Camilla Berglund ada1fdc14d Formatting 2016-08-12 01:46:21 +02:00
Camilla Berglund c98d09f15d Documentation work 2016-08-12 01:46:17 +02:00
Camilla Berglund a6676e6bc2 Update changelog 2016-08-08 17:34:05 +02:00
Camilla Berglund 51e59f4873 Cleanup
Cleanup of 74ed35792f.

Add credit and change log entry.
2016-08-08 16:59:50 +02:00
Patrick Snape 74ed35792f Cocoa: Add missing call to removeObserver:
As noted in the documentation for NSDistributedNotificationCenter,
(under the Discussion heading) before an observer is deallocated a call
should be made to removeObserver: in order to ensure that the listener
is correctly removed from all observation pools.

Fixes #817.
Closes #826.
2016-08-08 16:57:24 +02:00
Camilla Berglund 25914d381a Fix glfwVulkanSupported emitting errors
Regression caused by 614debd13f.
2016-08-05 11:50:05 +02:00
Camilla Berglund fcdef1d0a0 Fix potential context resource leaks
There is a gap between the creation of the context and the call to
_glfwRefreshContextAttribs.
2016-08-05 11:23:05 +02:00
Camilla Berglund 1d3240ff9c Fix Vulkan header macro not breaking compilation
Fixes #823.
2016-08-05 01:32:23 +02:00
Camilla Berglund 7c3706763a Cleanup
Cleanup of 8bdb105897.

Add build macro to configuration header and documentation.  Add
corresponding CMake option.  Add change log entry and credit.  Add
loader static library to link dependencies and add detection to
FindVulkan.cmake.
2016-08-05 01:00:08 +02:00
Philip Rideout 8bdb105897 Add _GLFW_VULKAN_STATIC build macro
This allows clients to link GLFW with a staticly-built loader library.
This is useful in hermetic build systems that build the Khronos loader
from source, rather than depending on the LunarG SDK binaries.

Closes #820.
2016-08-04 18:24:41 +02:00
Alexandre Pretyman d3775b973e Fix clobbering of CMAKE_MODULE_PATH
Closes #822.
2016-08-04 18:14:44 +02:00
Camilla Berglund e77a76a284 Cleanup 2016-08-04 13:19:22 +02:00
Camilla Berglund 00b91a07cb Documentation work 2016-08-02 15:58:58 +02:00
Camilla Berglund 52e47b5a53 Formatting 2016-08-02 15:39:01 +02:00
Camilla Berglund 7be62631ae Cleanup 2016-08-01 23:13:11 +02:00
Camilla Berglund d2686c8413 Fix comment 2016-08-01 23:13:11 +02:00
Camilla Berglund cba652e4f3 Cleanup 2016-08-01 23:13:11 +02:00
Camilla Berglund 370cd14b46 Comment work 2016-08-01 23:13:11 +02:00
Camilla Berglund d3e288cc4d Fix glfwinfo not accepting -c option 2016-08-01 23:13:11 +02:00
Camilla Berglund 06a6629eef EGL: Fix missing include 2016-08-01 23:13:11 +02:00
Camilla Berglund a19490c291 Cleanup
Cleanup of a42d27011b3ef1e6229a1b83aaa075727a5521f3.
2016-08-01 23:13:11 +02:00
Keringar d4eb88b255 X11: Fix application of window size limits
Closes #805.
2016-08-01 23:12:05 +02:00
Camilla Berglund c844fea9df Improve client API error messages
Add separate strings for each client API to make it easier to grep.
Remove 'client' from fallback error messages as API-related error tokens
are used for non-client APIs as well.
2016-08-01 20:49:22 +02:00
Camilla Berglund 923568a279 Add support for WGL_ARB_create_context errors 2016-08-01 20:46:59 +02:00
Camilla Berglund 2c32503b10 Fix comment 2016-08-01 12:15:08 +02:00
Camilla Berglund fe0317aee5 Documentation work 2016-08-01 11:51:30 +02:00
Camilla Berglund 751be1ae8c Fix comment 2016-07-31 19:26:57 +02:00
Camilla Berglund f48b63de38 Fix Valgrind false-positive
Fixes #818.
2016-07-31 17:54:30 +02:00
Camilla Berglund 3beb200c68 Remove unused variable 2016-07-31 13:48:11 +02:00
Camilla Berglund d43b743ff4 Fix GCC warnings 2016-07-21 00:15:55 +02:00
Camilla Berglund 70423af38c Clarify comments 2016-07-21 00:15:42 +02:00
Camilla Berglund f7006f64fb Update changelog 2016-07-20 15:51:57 +02:00
Camilla Berglund 6431c26e8b Add EGL library missing error 2016-07-20 15:39:38 +02:00
Camilla Berglund 04d05fbdc2 Formatting 2016-07-20 15:19:02 +02:00
Camilla Berglund 614debd13f Initialize Vulkan API on demand 2016-07-20 15:18:42 +02:00
Camilla Berglund 2060de5ed0 Match presence of lib prefix on EGL/GLES binaries 2016-07-20 13:11:08 +02:00
Camilla Berglund d5e00e6b0f Initialize context creation APIs on demand 2016-07-20 13:10:51 +02:00
Camilla Berglund 52d801bd19 Cleanup 2016-07-19 00:15:34 +02:00
Camilla Berglund ac09592355 Call context GetProcAddress directly 2016-07-18 23:31:54 +02:00
Camilla Berglund fb418b26d7 Fix grammar
Fixes #776.
2016-07-17 15:39:25 +02:00
Camilla Berglund 4888d7d410 Documentation work
[ci skip]
2016-07-14 18:36:45 +02:00
Camilla Berglund 89bc316a7a Documentation work
[ci skip]
2016-07-14 18:36:42 +02:00
Camilla Berglund c1b1e0aab1 Documentation work
[ci skip]
2016-07-14 18:21:43 +02:00
Camilla Berglund 2bea621f7d Documentation work
[ci skip]
2016-07-14 18:16:49 +02:00
Camilla Berglund 868f248696 Documentation work 2016-07-14 18:07:25 +02:00
A. Tombs 30111efc6d Update name in credits
Closes #807.
2016-07-14 12:49:46 +02:00
Camilla Berglund a28236d939 Fix matrix rotation regression
Related to #785.
2016-07-13 22:22:43 +02:00
Camilla Berglund 6fd4a87881 Update changelog 2016-07-13 22:22:41 +02:00
Camilla Berglund 9c5b994369 Make readme reference contribution guide 2016-07-12 16:29:59 +02:00
Camilla Berglund 9befef1b03 Update changelog 2016-07-12 16:23:46 +02:00
Camilla Berglund 0ff22e4a49 Win32: Fix GLFW_MAXIMIZED ignored by first window
Fixes #780.
2016-07-12 16:04:02 +02:00
Camilla Berglund 18b6ba0af4 Remove trailing whitespace 2016-07-12 15:35:06 +02:00
Camilla Berglund 9f14ac291f Add question section to contribution guide 2016-07-12 01:03:08 +02:00
ndogxj 65d4652e92 Fix VS 2010 build errors
VS 2010 cannot handle C99-style variable declarations in C mode.

Fixes #785.
2016-07-12 01:02:58 +02:00
Camilla Berglund 613868b893 Add missing assertion 2016-07-11 16:39:53 +02:00
Camilla Berglund 73abf8a800 Documentation work 2016-07-06 13:06:59 +02:00
Camilla Berglund 3bb5c459d6 GLX: Verify all entry points during load 2016-07-01 18:18:04 +02:00
Camilla Berglund 145ea03ca2 EGL: Verify all entry points during load 2016-07-01 18:17:30 +02:00
Camilla Berglund 49f429018e Win32: Fix code analysis warning 2016-06-23 17:41:22 +02:00
Camilla Berglund 66149a29da Cleanup 2016-06-23 17:40:30 +02:00
Camilla Berglund 0ee8159f6c Win32: Remove intermediate clipboard string copy 2016-06-23 17:06:03 +02:00
Camilla Berglund e81f4b29db Add Coverity badge, I guess 2016-06-23 16:09:55 +02:00
Camilla Berglund 1b82546b90 Cleanup 2016-06-23 15:34:23 +02:00
Camilla Berglund e250c226ca Cleanup 2016-06-23 14:48:25 +02:00
Camilla Berglund d67a0259cf Documentation work
[ci skip]
2016-06-23 14:18:01 +02:00
Camilla Berglund 7f2e4d8ace Win32: Fix possible leak of dummy context 2016-06-23 14:17:54 +02:00
Camilla Berglund 6f313ff245 Win32: Use helper window to load WGL extensions
This removes window re-creation logic by performing the initial context
creation on the helper window, simplifying both window and context
creation and paving the way for attaching to existing window handles
without compromising on context or framebuffer hint support.
2016-06-22 23:33:34 +02:00
Camilla Berglund a991c01731 Fail sharing if either window is context-less 2016-06-22 14:36:46 +02:00
Camilla Berglund b5aae7e901 Documentation work
[ci skip]
2016-06-22 13:33:25 +02:00
Camilla Berglund 5b7d6ed8b9 Documentation work 2016-06-21 16:46:17 +02:00
Camilla Berglund 38856886e6 Documentation work 2016-06-21 16:36:16 +02:00
Camilla Berglund f2ba78e04b Rename static functions to allow unity build
Fixes regression introduced by GLFW_CONTEXT_CREATION_API.

Fixes #783.
2016-06-15 01:35:07 +02:00
Camilla Berglund ae32d968b9 Fix test program line endings 2016-06-15 01:35:07 +02:00
Camilla Berglund df5dcf5162 Win32: Fix stub comment 2016-06-15 01:35:07 +02:00
Camilla Berglund 76801973e1 Cocoa: Clean up joystick globals 2016-06-15 01:35:07 +02:00
Camilla Berglund b6b8ff591d Fix cursor position coordinate delimiter
Comma would be great but we don't control the locale.
2016-06-15 01:35:07 +02:00
Camilla Berglund 9a781cef53 Formatting 2016-06-15 01:35:07 +02:00
Camilla Berglund aaccfd8201 I don't know how to C
Fixes #773.
2016-06-15 01:35:07 +02:00
Camilla Berglund 4bccb3dc9f Start 3.2.1 2016-06-15 01:35:05 +02:00
A. Tombs d8c278bf52 Add explanation of parameters to gamma test
Unlike similar test programs (e.g. tearing.c), the gamma test does not
explain the meanings of the optional parameters `h` and `f`. This patch
adds these explanations to the usage text.

Closes #775.
2016-06-06 21:25:13 +02:00
A. Tombs 407385dc72 Correct program name printed by tearing test
The tearing test incorrectly calls itself "iconify" when printing usage
information, probably just a copy-paste error.

Closes #774.
2016-06-06 21:23:30 +02:00
129 changed files with 39301 additions and 6648 deletions
+2 -1
View File
@@ -4,6 +4,7 @@ branches:
- master
skip_tags: true
environment:
CFLAGS: /WX
matrix:
- BUILD_SHARED_LIBS: ON
- BUILD_SHARED_LIBS: OFF
@@ -12,7 +13,7 @@ matrix:
build_script:
- mkdir build
- cd build
- cmake -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% ..
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% ..
- cmake --build .
notifications:
- provider: Email
+1
View File
@@ -0,0 +1 @@
*.m linguist-language=Objective-C
+330 -45
View File
@@ -1,35 +1,139 @@
# Contribution Guide
This file is a work in progress and you can report errors or submit patches for
it the same as any other file.
## Contents
- [Asking a question](#asking-a-question)
- [Reporting a bug](#reporting-a-bug)
- [Reporting a compile or link bug](#reporting-a-compile-or-link-bug)
- [Reporting a segfault or other crash bug](#reporting-a-segfault-or-other-crash-bug)
- [Reporting a context creation bug](#reporting-a-context-creation-bug)
- [Reporting a monitor or video mode bug](#reporting-a-monitor-or-video-mode-bug)
- [Reporting a window, input or event bug](#reporting-a-window-input-or-event-bug)
- [Reporting some other library bug](#reporting-some-other-library-bug)
- [Reporting a documentation bug](#reporting-a-documentation-bug)
- [Reporting a website bug](#reporting-a-website-bug)
- [Requesting a feature](#requesting-a-feature)
- [Contributing a bug fix](#contributing-a-bug-fix)
- [Contributing a feature](#contributing-a-feature)
## Asking a question
Questions about how to use GLFW should be asked either in the [support
section](http://discourse.glfw.org/c/support) of the forum, under the [Stack
Overflow tag](https://stackoverflow.com/questions/tagged/glfw) or [Game
Development tag](https://gamedev.stackexchange.com/questions/tagged/glfw) on
Stack Exchange or in the IRC channel `#glfw` on
[Freenode](http://freenode.net/).
Questions about the design or implementation of GLFW or about future plans
should be asked in the [dev section](http://discourse.glfw.org/c/dev) of the
forum or in the IRC channel. Please don't open a GitHub issue to discuss design
questions without first checking with a maintainer.
## Reporting a bug
If GLFW is behaving unexpectedly, make sure you have set an error callback.
GLFW will often tell you the cause of an issue via this callback.
If GLFW is behaving unexpectedly at run-time, start by setting an [error
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling).
GLFW will often tell you the cause of an error via this callback. If it
doesn't, that might be a separate bug.
If GLFW is crashing or triggering asserts, make sure that all your object
handles and other pointers are valid.
Always include the __operating system name and version__ (i.e. `Windows
7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW,
include the __GLFW release version__ (i.e. `3.1.2`), otherwise include the
__GLFW commit ID__ (i.e. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
If possible, please also include the __GLFW version string__ (`3.2.0 X11 EGL
clock_gettime /dev/js XI Xf86vm`), as described
[here](http://www.glfw.org/docs/latest/intro.html#intro_version_string).
For bugs where it makes sense, a short, self contained example is absolutely
invaluable. Just put it inline in the body text. Note that if the bug is
reproducible with one of the test programs that come with GLFW, just mention
that instead.
__Don't worry about adding too much information__. Unimportant information can
be abbreviated or removed later, but missing information can stall bug fixing,
especially when your schedule doesn't align with that of the maintainer.
__Please provide text as text, not as images__. This includes code, error
messages and any other text. Text in images cannot be found by other users
searching for the same problem and may have to be re-typed by maintainers when
debugging.
You don't need to manually indent your code or other text to quote it with
GitHub Markdown; just surround it with triple backticks:
```
Some quoted text.
```
You can also add syntax highlighting by appending the common file extension:
```c
int five(void)
{
return 5;
}
```
There are issue labels for both platforms and GPU manufacturers, so there is no
need to mention these in the subject line. If you do, it will be removed when
the issue is labeled.
If your bug is already reported, please add any new information you have, or if
it already has everything, give it a :+1:.
### Reporting a compile or link bug
__Note:__ GLFW needs many system APIs to do its job. See the [Building
applications](http://www.glfw.org/docs/latest/build.html) guide for more
information.
__Note:__ GLFW needs many system APIs to do its job, which on some platforms
means linking to many system libraries. If you are using GLFW as a static
library, that means your application needs to link to these in addition to GLFW.
In addition to the information above, always include the complete build log from
your compiler and linker. Issue posts are editable so it can always be
shortened later.
__Note:__ Check the [Compiling
GLFW](http://www.glfw.org/docs/latest/compile.html) guide and or [Building
applications](http://www.glfw.org/docs/latest/build.html) guide for before
opening an issue of this kind. Most issues are caused by a missing package or
linker flag.
Always include the __operating system name and version__ (e.g. `Windows
7 64-bit` or `Ubuntu 15.10`) and the __compiler name and version__ (e.g. `Visual
C++ 2015 Update 2`). If you are using an official release of GLFW,
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
Please also include the __complete build log__ from your compiler and linker,
even if it's long. It can always be shortened later, if necessary.
#### Quick template
```
OS and version:
Compiler version:
Release or commit:
Build log:
```
### Reporting a segfault or other crash bug
Always include the __operating system name and version__ (e.g. `Windows
7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW,
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
Please also include any __error messages__ provided to your application via the
[error
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
the __full call stack__ of the crash, or if the crash does not occur in debug
mode, mention that instead.
#### Quick template
```
OS and version:
Release or commit:
Error messages:
Call stack:
```
### Reporting a context creation bug
@@ -38,23 +142,45 @@ __Note:__ Windows ships with graphics drivers that do not support OpenGL. If
GLFW says that your machine lacks support for OpenGL, it very likely does.
Install drivers from the computer manufacturer or graphics card manufacturer
([Nvidia](http://www.geforce.com/drivers),
[AMD](http://support.amd.com/en-us/download),
[Intel](https://www-ssl.intel.com/content/www/us/en/support/detect.html)) to
[AMD](http://support.amd.com/en-us/download),
[Intel](https://www-ssl.intel.com/content/www/us/en/support/detect.html)) to
fix this.
__Note:__ AMD only supports OpenGL ES on Windows via EGL. EGL support is not
enabled in GLFW by default. You need to [enable EGL when
compiling](http://www.glfw.org/docs/latest/compile.html) GLFW to use this.
__Note:__ AMD only supports OpenGL ES on Windows via EGL. See the
[GLFW\_CONTEXT\_CREATION\_API](http://www.glfw.org/docs/latest/window_guide.html#window_hints_ctx)
hint for how to select EGL.
The `glfwinfo` tool is included in the GLFW source tree as `tests/glfwinfo.c`
and is built along with the library. It lets you request any kind of context
and framebuffer format supported by the GLFW API without having to recompile.
If context creation fails in your application, please verify that it also fails
with this tool before reporting it as a bug.
Please verify that context creation also fails with the `glfwinfo` tool before
reporting it as a bug. This tool is included in the GLFW source tree as
`tests/glfwinfo.c` and is built along with the library. It has switches for all
GLFW context and framebuffer hints. Run `glfwinfo -h` for a complete list.
In addition to the information above (OS and GLFW version), always include the
__GPU model and driver version__ (i.e. `GeForce GTX660 with 352.79`) when
reporting this kind of bug.
Always include the __operating system name and version__ (e.g. `Windows
7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW,
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
If you are running your program in a virtual machine, please mention this and
include the __VM name and version__ (e.g. `VirtualBox 5.1`).
Please also include the __GLFW version string__ (`3.2.0 X11 EGL clock_gettime
/dev/js`), as described
[here](http://www.glfw.org/docs/latest/intro.html#intro_version_string), the
__GPU model and driver version__ (e.g. `GeForce GTX660 with 352.79`), and the
__output of `glfwinfo`__ (with switches matching any hints you set in your
code) when reporting this kind of bug. If this tool doesn't run on the machine,
mention that instead.
#### Quick template
```
OS and version:
GPU and driver:
Release or commit:
Version string:
glfwinfo output:
```
### Reporting a monitor or video mode bug
@@ -63,23 +189,47 @@ __Note:__ On headless systems on some platforms, no monitors are reported. This
causes glfwGetPrimaryMonitor to return `NULL`, which not all applications are
prepared for.
__Note:__ Some third-party tools report more video modes than those approved of
by the OS. For safety and compatbility, GLFW only reports video modes the OS
__Note:__ Some third-party tools report more video modes than are approved of
by the OS. For safety and compatibility, GLFW only reports video modes the OS
wants programs to use. This is not a bug.
The `monitors` tool is included in the GLFW source tree as `tests/monitors.c`
and is built along with the library. lists all information about connected
monitors made available by GLFW.
and is built along with the library. It lists all information GLFW provides
about monitors it detects.
In addition to the information above (OS and GLFW version), please also include
the output of the `monitors` tool when reporting this kind of bug. If it
doesn't work at all, please mention this.
Always include the __operating system name and version__ (e.g. `Windows
7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW,
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
If you are running your program in a virtual machine, please mention this and
include the __VM name and version__ (e.g. `VirtualBox 5.1`).
Please also include any __error messages__ provided to your application via the
[error
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
the __output of `monitors`__ when reporting this kind of bug. If this tool
doesn't run on the machine, mention this instead.
### Reporting a window event bug
#### Quick template
__Note:__ While GLFW tries to provide the exact same behavior between platforms,
the exact ordering of related window events will sometimes differ.
```
OS and version:
Release or commit:
Error messages:
monitors output:
```
### Reporting a window, input or event bug
__Note:__ The exact ordering of related window events will sometimes differ.
__Note:__ Window moving and resizing (by the user) will block the main thread on
some platforms. This is not a bug. Set a [refresh
callback](http://www.glfw.org/docs/latest/window.html#window_refresh) if you
want to keep the window contents updated during a move or size operation.
The `events` tool is included in the GLFW source tree as `tests/events.c` and is
built along with the library. It prints all information provided to every
@@ -87,20 +237,155 @@ callback supported by GLFW as events occur. Each event is listed with the time
and a unique number to make discussions about event logs easier. The tool has
command-line options for creating multiple windows and full screen windows.
Always include the __operating system name and version__ (e.g. `Windows
7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW,
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
If you are running your program in a virtual machine, please mention this and
include the __VM name and version__ (e.g. `VirtualBox 5.1`).
Please also include any __error messages__ provided to your application via the
[error
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
if relevant, the __output of `events`__ when reporting this kind of bug. If
this tool doesn't run on the machine, mention this instead.
__X11:__ If possible, please include what desktop environment (e.g. GNOME,
Unity, KDE) and/or window manager (e.g. Openbox, dwm, Window Maker) you are
running. If the bug is related to keyboard input, please include any input
method (e.g. ibus, SCIM) you are using.
#### Quick template
```
OS and version:
Release or commit:
Error messages:
events output:
```
### Reporting some other library bug
Always include the __operating system name and version__ (e.g. `Windows
7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW,
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
Please also include any __error messages__ provided to your application via the
[error
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling), if
relevant.
#### Quick template
```
OS and version:
Release or commit:
Error messages:
```
### Reporting a documentation bug
If you found the error in the generated documentation then it's fine to just
link to that webpage. You don't need to figure out which documentation source
file the text comes from.
If you found a bug in the documentation, including this file, then it's fine to
just link to that web page or mention that source file. You don't need to match
the source to the output or vice versa.
### Reporting a website bug
If the bug is in the documentation (anything under `/docs/`) then please see the
section above. Bugs in the rest of the site are reported to to the [website
source repository](https://github.com/glfw/website/issues).
## Requesting a feature
Please explain why you need the feature and how you intend to use it. If you
have a specific API design in mind, please add that as well. If you have or are
planning to write code for the feature, see the section below.
If there already is a request for the feature you need, add your specific use
case unless it is already mentioned. If it is, give it a :+1:.
## Contributing a bug fix
There should be text here, but there isn't.
__Note:__ You must have all necessary [intellectual
property rights](https://en.wikipedia.org/wiki/Intellectual_property) to any
code you contribute. If you did not write the code yourself, you must explain
where it came from and under what license you received it. Even code using the
same license as GLFW may not be copied without attribution.
__There is no preferred patch size__. A one character fix is just as welcome as
a thousand line one, if that is the appropriate size for the fix.
In addition to the code, a complete bug fix includes:
- Change log entry in `README.md`, describing the incorrect behavior
- Credits entries for all authors of the bug fix
Bug fixes will not be rejected because they don't include all the above parts,
but please keep in mind that maintainer time is finite and that there are many
other bugs and features to work on.
If the patch fixes a bug introduced after the last release, it should not get
a change log entry.
If you haven't already, read the excellent article [How to Write a Git Commit
Message](https://chris.beams.io/posts/git-commit/).
## Contributing a feature
This is not (yet) the text you are looking for.
__Note:__ You must have all necessary rights to any code you contribute. If you
did not write the code yourself, you must explain where it came from and under
what license. Even code using the same license as GLFW may not be copied
without attribution.
__Note:__ If you haven't already implemented the feature, check first if there
already is an open issue for it and if it's already being developed in an
[experimental branch](https://github.com/glfw/glfw/branches/all).
__There is no preferred patch size__. A one character change is just as welcome
as one adding a thousand line one, if that is the appropriate size for the
feature.
In addition to the code, a complete feature includes:
- Change log entry in `README.md`, listing all new symbols
- News page entry, briefly describing the feature
- Guide documentation, with minimal examples, in the relevant guide
- Reference documentation, with all applicable tags
- Cross-references and mentions in appropriate places
- Credits entries for all authors of the feature
If the feature requires platform-specific code, at minimum stubs must be added
for the new platform function to all supported and experimental platforms.
If it adds a new callback, support for it must be added to `tests/event.c`.
If it adds a new monitor property, support for it must be added to
`tests/monitor.c`.
If it adds a new OpenGL, OpenGL ES or Vulkan option or extension, support
for it must be added to `tests/glfwinfo.c` and the behavior of the library when
the extension is missing documented in `docs/compat.dox`.
If you haven't already, read the excellent article [How to Write a Git Commit
Message](https://chris.beams.io/posts/git-commit/).
Features will not be rejected because they don't include all the above parts,
but please keep in mind that maintainer time is finite and that there are many
other features and bugs to work on.
Please also keep in mind that any part of the public API that has been included
in a release cannot be changed until the next _major_ version. Features can be
added and existing parts can sometimes be overloaded (in the general sense of
doing more things, not in the C++ sense), but code written to the API of one
minor release should both compile and run on subsequent minor releases.
+5 -3
View File
@@ -40,11 +40,11 @@ src/wayland-relative-pointer-unstable-v1-protocol.c
# Compiled binaries
src/libglfw.so
src/libglfw.so.3
src/libglfw.so.3.2
src/libglfw.so.3.3
src/libglfw.dylib
src/libglfw.dylib
src/libglfw.3.dylib
src/libglfw.3.2.dylib
src/libglfw.3.3.dylib
src/libglfw3.a
src/glfw3.lib
src/glfw3.dll
@@ -55,6 +55,7 @@ examples/*.exe
examples/boing
examples/gears
examples/heightmap
examples/offscreen
examples/particles
examples/splitview
examples/simple
@@ -67,6 +68,7 @@ tests/empty
tests/events
tests/gamma
tests/glfwinfo
tests/icon
tests/iconify
tests/joysticks
tests/monitors
@@ -75,8 +77,8 @@ tests/reopen
tests/sharing
tests/tearing
tests/threads
tests/timeout
tests/title
tests/version
tests/vulkan
tests/windows
+11 -3
View File
@@ -8,19 +8,27 @@ os:
- linux
- osx
sudo: false
dist: trusty
addons:
apt:
sources:
- kubuntu-backports
packages:
- cmake
- libxrandr-dev
- libxinerama-dev
- libxcursor-dev
- libxi-dev
env:
- BUILD_SHARED_LIBS=ON
- BUILD_SHARED_LIBS=OFF
global:
- CFLAGS=-Werror
matrix:
- BUILD_SHARED_LIBS=ON
- BUILD_SHARED_LIBS=OFF
script:
- mkdir build
- cd build
- cmake -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} ..
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} ..
- cmake --build .
notifications:
email:
+28 -12
View File
@@ -1,18 +1,34 @@
# Try to find Mir on a Unix system
# FindMir
# -------
# Finds the Mir library
#
# This will define:
# This will will define the following variables::
#
# MIR_LIBRARIES - Link these to use Wayland
# MIR_INCLUDE_DIR - Include directory for Wayland
#
# Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
# MIR_FOUND - the system has Mir
# MIR_INCLUDE_DIRS - the Mir include directory
# MIR_LIBRARIES - the Mir libraries
# MIR_DEFINITIONS - the Mir definitions
if (NOT WIN32)
find_package (PkgConfig)
pkg_check_modules (PKG_MIR QUIET mirclient)
find_package (PkgConfig)
if(PKG_CONFIG_FOUND)
pkg_check_modules (PC_MIR mirclient>=0.26.2 QUIET)
set (MIR_INCLUDE_DIR ${PKG_MIR_INCLUDE_DIRS})
set (MIR_LIBRARIES ${PKG_MIR_LIBRARIES})
find_path(MIR_INCLUDE_DIR NAMES mir_toolkit/mir_client_library.h
PATHS ${PC_MIR_INCLUDE_DIRS})
endif ()
find_library(MIR_LIBRARY NAMES mirclient
PATHS ${PC_MIR_LIBRARIES} ${PC_MIR_LIBRARY_DIRS})
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (MIR
REQUIRED_VARS MIR_LIBRARY MIR_INCLUDE_DIR)
if (MIR_FOUND)
set(MIR_LIBRARIES ${MIR_LIBRARY})
set(MIR_INCLUDE_DIRS ${PC_MIR_INCLUDE_DIRS})
set(MIR_DEFINITIONS -DHAVE_MIR=1)
endif()
mark_as_advanced (MIR_LIBRARY MIR_INCLUDE_DIR)
endif()
+18
View File
@@ -0,0 +1,18 @@
# Try to find OSMesa on a Unix system
#
# This will define:
#
# OSMESA_LIBRARIES - Link these to use OSMesa
# OSMESA_INCLUDE_DIR - Include directory for OSMesa
#
# Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
if (NOT WIN32)
find_package (PkgConfig)
pkg_check_modules (PKG_OSMESA QUIET osmesa)
set (OSMESA_INCLUDE_DIR ${PKG_OSMESA_INCLUDE_DIRS})
set (OSMESA_LIBRARIES ${PKG_OSMESA_LIBRARIES})
endif ()
+19 -2
View File
@@ -8,15 +8,32 @@ if (WIN32)
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
"$ENV{VULKAN_SDK}/Include"
"$ENV{VK_SDK_PATH}/Include")
if (CMAKE_CL_64)
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS
"$ENV{VULKAN_SDK}/Lib"
"$ENV{VULKAN_SDK}/Bin"
"$ENV{VK_SDK_PATH}/Bin")
find_library(VULKAN_STATIC_LIBRARY NAMES vkstatic.1 HINTS
"$ENV{VULKAN_SDK}/Lib"
"$ENV{VULKAN_SDK}/Bin"
"$ENV{VK_SDK_PATH}/Bin")
else()
find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS
"$ENV{VULKAN_SDK}/Lib32"
"$ENV{VULKAN_SDK}/Bin32"
"$ENV{VK_SDK_PATH}/Bin32")
find_library(VULKAN_STATIC_LIBRARY NAMES vkstatic.1 HINTS
"$ENV{VULKAN_SDK}/Lib32"
"$ENV{VULKAN_SDK}/Bin32"
"$ENV{VK_SDK_PATH}/Bin32")
endif()
elseif (APPLE)
set(CMAKE_FIND_FRAMEWORK NEVER)
find_library(VULKAN_LIBRARY MoltenVK)
set(CMAKE_FIND_FRAMEWORK ONLY)
find_library(VULKAN_STATIC_LIBRARY MoltenVK)
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
"${VULKAN_LIBRARY}/Headers")
else()
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
"$ENV{VULKAN_SDK}/include")
@@ -27,5 +44,5 @@ endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Vulkan DEFAULT_MSG VULKAN_LIBRARY VULKAN_INCLUDE_DIR)
mark_as_advanced(VULKAN_INCLUDE_DIR VULKAN_LIBRARY)
mark_as_advanced(VULKAN_INCLUDE_DIR VULKAN_LIBRARY VULKAN_STATIC_LIBRARY)
+82 -63
View File
@@ -1,8 +1,8 @@
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
cmake_minimum_required(VERSION 2.8.12)
project(GLFW C)
cmake_minimum_required(VERSION 2.8.12)
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
if (NOT CMAKE_VERSION VERSION_LESS "3.0")
# Until all major package systems have moved to CMake 3,
@@ -10,8 +10,12 @@ if (NOT CMAKE_VERSION VERSION_LESS "3.0")
cmake_policy(SET CMP0042 OLD)
endif()
if (NOT CMAKE_VERSION VERSION_LESS "3.1")
cmake_policy(SET CMP0054 NEW)
endif()
set(GLFW_VERSION_MAJOR "3")
set(GLFW_VERSION_MINOR "2")
set(GLFW_VERSION_MINOR "3")
set(GLFW_VERSION_PATCH "0")
set(GLFW_VERSION_EXTRA "")
set(GLFW_VERSION "${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}")
@@ -25,18 +29,17 @@ option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" ON)
option(GLFW_BUILD_TESTS "Build the GLFW test programs" ON)
option(GLFW_BUILD_DOCS "Build the GLFW documentation" ON)
option(GLFW_INSTALL "Generate installation target" ON)
option(GLFW_VULKAN_STATIC "Use the Vulkan loader statically linked into application" OFF)
option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF)
if (UNIX)
option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" OFF)
endif()
if (WIN32)
option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF)
endif()
if (APPLE)
option(GLFW_USE_CHDIR "Make glfwInit chdir to Contents/Resources" ON)
option(GLFW_USE_MENUBAR "Populate the menu bar on first window creation" ON)
option(GLFW_USE_RETINA "Use the full resolution of Retina displays" ON)
endif()
if (UNIX AND NOT APPLE)
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
option(GLFW_USE_MIR "Use Mir for window creation" OFF)
@@ -57,7 +60,11 @@ else()
set(GLFW_LIB_NAME glfw3)
endif()
set(CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
if (GLFW_VULKAN_STATIC)
set(_GLFW_VULKAN_STATIC 1)
endif()
list(APPEND CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
find_package(Threads REQUIRED)
find_package(Vulkan)
@@ -71,6 +78,17 @@ endif()
# Set compiler specific flags
#--------------------------------------------------------------------
if (MSVC)
if (MSVC90)
# Workaround for VS 2008 not shipping with the DirectX 9 SDK
include(CheckIncludeFile)
check_include_file(dinput.h DINPUT_H_FOUND)
if (NOT DINPUT_H_FOUND)
message(FATAL_ERROR "DirectX 9 SDK not found")
endif()
# Workaround for VS 2008 not shipping with stdint.h
list(APPEND glfw_INCLUDE_DIRS "${GLFW_SOURCE_DIR}/deps/vs2008")
endif()
if (NOT USE_MSVC_RUNTIME_LIBRARY_DLL)
foreach (flag CMAKE_C_FLAGS
CMAKE_C_FLAGS_DEBUG
@@ -124,30 +142,58 @@ if (MINGW)
endif()
endif()
if (APPLE)
# Dependencies required by the MoltenVK static library
set(GLFW_VULKAN_DEPS
"-lc++"
"-framework Cocoa"
"-framework Metal"
"-framework QuartzCore")
endif()
#--------------------------------------------------------------------
# Detect and select backend APIs
#--------------------------------------------------------------------
if (WIN32)
if (GLFW_USE_WAYLAND)
set(_GLFW_WAYLAND 1)
message(STATUS "Using Wayland for window creation")
elseif (GLFW_USE_MIR)
set(_GLFW_MIR 1)
message(STATUS "Using Mir for window creation")
elseif (GLFW_USE_OSMESA)
set(_GLFW_OSMESA 1)
message(STATUS "Using OSMesa for headless context creation")
elseif (WIN32)
set(_GLFW_WIN32 1)
message(STATUS "Using Win32 for window creation")
elseif (APPLE)
set(_GLFW_COCOA 1)
message(STATUS "Using Cocoa for window creation")
elseif (UNIX)
if (GLFW_USE_WAYLAND)
set(_GLFW_WAYLAND 1)
message(STATUS "Using Wayland for window creation")
elseif (GLFW_USE_MIR)
set(_GLFW_MIR 1)
message(STATUS "Using Mir for window creation")
else()
set(_GLFW_X11 1)
message(STATUS "Using X11 for window creation")
endif()
set(_GLFW_X11 1)
message(STATUS "Using X11 for window creation")
else()
message(FATAL_ERROR "No supported platform was detected")
endif()
#--------------------------------------------------------------------
# Add Vulkan static library if requested
#--------------------------------------------------------------------
if (GLFW_VULKAN_STATIC)
if (VULKAN_FOUND AND VULKAN_STATIC_LIBRARY)
list(APPEND glfw_LIBRARIES ${VULKAN_STATIC_LIBRARY} ${GLFW_VULKAN_DEPS})
if (BUILD_SHARED_LIBS)
message(WARNING "Linking Vulkan loader static library into GLFW")
endif()
else()
if (BUILD_SHARED_LIBS OR GLFW_BUILD_EXAMPLES OR GLFW_BUILD_TESTS)
message(FATAL_ERROR "Vulkan loader static library not found")
else()
message(WARNING "Vulkan loader static library not found")
endif()
endif()
endif()
#--------------------------------------------------------------------
# Find and add Unix math and time libraries
#--------------------------------------------------------------------
@@ -215,21 +261,6 @@ if (_GLFW_X11)
list(APPEND glfw_LIBRARIES "${X11_Xinerama_LIB}")
list(APPEND glfw_PKG_DEPS "xinerama")
# Check for Xf86VidMode (fallback gamma control)
if (X11_xf86vmode_FOUND)
list(APPEND glfw_INCLUDE_DIRS "${X11_xf86vmode_INCLUDE_PATH}")
list(APPEND glfw_PKG_DEPS "xxf86vm")
if (X11_Xxf86vm_LIB)
list(APPEND glfw_LIBRARIES "${X11_Xxf86vm_LIB}")
else()
# Backwards compatibility (see CMake bug 0006976)
list(APPEND glfw_LIBRARIES Xxf86vm)
endif()
set(_GLFW_HAS_XF86VM TRUE)
endif()
# Check for Xkb (X keyboard extension)
if (NOT X11_Xkb_FOUND)
message(FATAL_ERROR "The X keyboard extension headers were not found")
@@ -253,7 +284,7 @@ endif()
#--------------------------------------------------------------------
if (_GLFW_WAYLAND)
find_package(ECM REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH})
list(APPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
find_package(Wayland REQUIRED)
find_package(WaylandScanner REQUIRED)
@@ -277,7 +308,7 @@ if (_GLFW_MIR)
find_package(Mir REQUIRED)
list(APPEND glfw_PKG_DEPS "mirclient")
list(APPEND glfw_INCLUDE_DIRS "${MIR_INCLUDE_DIR}")
list(APPEND glfw_INCLUDE_DIRS "${MIR_INCLUDE_DIRS}")
list(APPEND glfw_LIBRARIES "${MIR_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
find_package(XKBCommon REQUIRED)
@@ -286,36 +317,24 @@ if (_GLFW_MIR)
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
endif()
#--------------------------------------------------------------------
# Use OSMesa for offscreen context creation
#--------------------------------------------------------------------
if (_GLFW_OSMESA)
find_package(OSMesa REQUIRED)
list(APPEND glfw_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
endif()
#--------------------------------------------------------------------
# Use Cocoa for window creation and NSOpenGL for context creation
#--------------------------------------------------------------------
if (_GLFW_COCOA)
if (GLFW_USE_MENUBAR)
set(_GLFW_USE_MENUBAR 1)
endif()
if (GLFW_USE_CHDIR)
set(_GLFW_USE_CHDIR 1)
endif()
if (GLFW_USE_RETINA)
set(_GLFW_USE_RETINA 1)
endif()
# Set up library and include paths
find_library(COCOA_FRAMEWORK Cocoa)
find_library(IOKIT_FRAMEWORK IOKit)
find_library(CORE_FOUNDATION_FRAMEWORK CoreFoundation)
find_library(CORE_VIDEO_FRAMEWORK CoreVideo)
mark_as_advanced(COCOA_FRAMEWORK
IOKIT_FRAMEWORK
CORE_FOUNDATION_FRAMEWORK
CORE_VIDEO_FRAMEWORK)
list(APPEND glfw_LIBRARIES "${COCOA_FRAMEWORK}"
"${IOKIT_FRAMEWORK}"
"${CORE_FOUNDATION_FRAMEWORK}"
"${CORE_VIDEO_FRAMEWORK}")
list(APPEND glfw_LIBRARIES
"-framework Cocoa"
"-framework IOKit"
"-framework CoreFoundation"
"-framework CoreVideo")
set(glfw_PKG_DEPS "")
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework CoreVideo")
+2 -2
View File
@@ -1,5 +1,5 @@
Copyright (c) 2002-2006 Marcus Geelnard
Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
Copyright (c) 2002-2006 Marcus Geelnard
Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
+204 -108
View File
@@ -2,63 +2,94 @@
[![Build status](https://travis-ci.org/glfw/glfw.svg?branch=master)](https://travis-ci.org/glfw/glfw)
[![Build status](https://ci.appveyor.com/api/projects/status/0kf0ct9831i5l6sp/branch/master?svg=true)](https://ci.appveyor.com/project/elmindreda/glfw)
[![Coverity Scan](https://scan.coverity.com/projects/4884/badge.svg)](https://scan.coverity.com/projects/glfw-glfw)
## Introduction
GLFW is a free, Open Source, multi-platform library for OpenGL, OpenGL ES and
Vulkan application development. It provides a simple, platform-independent API
for creating windows, contexts and surfaces, reading input, handling events, etc.
GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan
application development. It provides a simple, platform-independent API for
creating windows, contexts and surfaces, reading input, handling events, etc.
Version 3.2 adds support for Vulkan surface creation, window mode switching,
window maximization, window input focus control, window size and aspect ratio
limits, human-readable key names, window icons, joystick connection events,
XInput and DirectInput joystick input, event waiting with timeout, 64-bit
integer raw timer, context-less window creation, error-less contexts via
`GL_KHR_no_error` (where available), run-time context creation API selection,
Windows 8.1 per-monitor DPI and the CMake config-file package system, adds
simpler build-time configuration, improved documentation and fixes for a large
number of bugs that together affect all supported platforms.
GLFW natively supports Windows, macOS and Linux and other Unix-like systems.
Experimental implementations for the Wayland protocol and the Mir display server
are available but not yet officially supported.
GLFW is licensed under the [zlib/libpng
license](http://www.glfw.org/license.html).
The latest stable release is version 3.2.1.
See the [downloads](http://www.glfw.org/download.html) page for details and
files, or fetch the `latest` branch, which always points to the latest stable
release. Each release starting with 3.0 also has a corresponding [annotated
tag](https://github.com/glfw/glfw/releases) with source and binary archives.
The [version history](http://www.glfw.org/changelog.html) lists all user-visible
changes for every release.
This is a development branch for version 3.3, which is _not yet described_.
Pre-release documentation is available [here](http://www.glfw.org/docs/3.3/).
The `master` branch is the stable integration branch and _should_ always compile
and run on all supported platforms, although details of newly added features may
change until they have been included in a release. New features and many bug
fixes live in [other branches](https://github.com/glfw/glfw/branches/all) until
they are stable enough to merge.
If you are new to GLFW, you may find the
[tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW
3 useful. If you have used GLFW 2 in the past, there is a
[transition guide](http://www.glfw.org/docs/latest/moving.html) for moving to
the GLFW 3 API.
[tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW 3 useful. If
you have used GLFW 2 in the past, there is a [transition
guide](http://www.glfw.org/docs/latest/moving.html) for moving to the GLFW
3 API.
## Compiling GLFW
See the [Compiling GLFW](http://www.glfw.org/docs/latest/compile.html) guide in
the GLFW documentation.
GLFW itself requires only the headers and libraries for your window system. It
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL) or
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
GLFW supports compilation on Windows with Visual C++ 2010 and later, MinGW and
MinGW-w64, on macOS with Clang and on Linux and other Unix-like systems with GCC
and Clang. It will likely compile in other environments as well, but this is
not regularly tested.
There are [pre-compiled Windows binaries](http://www.glfw.org/download.html)
available for all supported compilers.
See the [compilation guide](http://www.glfw.org/docs/latest/compile.html) for
more information about how to compile GLFW yourself.
## Using GLFW
See the
[Building programs that use GLFW](http://www.glfw.org/docs/latest/build.html)
guide in the GLFW documentation.
See the [documentation](http://www.glfw.org/docs/latest/) for tutorials, guides
and the API reference.
## Reporting bugs
## Contributing to GLFW
Bugs are reported to our [issue tracker](https://github.com/glfw/glfw/issues).
Please always include the name and version of the OS where the bug occurs and
the version of GLFW used. If you have cloned it, include the commit ID used.
See the [contribution
guide](https://github.com/glfw/glfw/blob/master/.github/CONTRIBUTING.md) for
more information.
If it's a build issue, please also include the build log and the name and
version of your development environment.
If it's a context creation issue, please also include the make and model of your
graphics card and the version of your driver.
## System requirements
This will help both us and other people experiencing the same bug.
GLFW supports Windows XP and later and macOS 10.7 and later. Linux and other
Unix-like systems running the X Window System are supported even without
a desktop environment or modern extensions, although some features require
a running window or clipboard manager. The OSMesa backend requires Mesa 6.3.
See the [compatibility guide](http://www.glfw.org/docs/latest/compat.html)
in the documentation for more information.
## Dependencies
GLFW itself needs only the headers and libraries for your window system. It
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL) or
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
GLFW itself depends only on the headers and libraries for your window system.
The (experimental) Wayland backend also depends on the `extra-cmake-modules`
package, which is used to generated Wayland protocol headers.
The examples and test programs depend on a number of tiny libraries. These are
located in the `deps/` directory.
@@ -71,100 +102,147 @@ located in the `deps/` directory.
[glad](https://github.com/Dav1dde/glad) for examples using modern OpenGL
- [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in
examples
- [Nuklear](https://github.com/vurtun/nuklear) for test and example UI
- [stb\_image\_write](https://github.com/nothings/stb) for writing images to disk
- [Vulkan headers](https://www.khronos.org/registry/vulkan/) for Vulkan tests
The Vulkan example additionally requires the Vulkan SDK to be installed, or it
will not be included in the build.
will not be included in the build. On macOS you need to provide the path to the
MoltenVK SDK manually as it has no standard installation location.
The documentation is generated with [Doxygen](http://doxygen.org/). If CMake
does not find Doxygen, the documentation will not be generated.
The documentation is generated with [Doxygen](http://doxygen.org/) if CMake can
find that tool.
## Reporting bugs
Bugs are reported to our [issue tracker](https://github.com/glfw/glfw/issues).
Please check the [contribution
guide](https://github.com/glfw/glfw/blob/master/.github/CONTRIBUTING.md) for
information on what to include when reporting a bug.
## Changelog
- Added `glfwVulkanSupported`, `glfwGetRequiredInstanceExtensions`,
`glfwGetInstanceProcAddress`, `glfwGetPhysicalDevicePresentationSupport` and
`glfwCreateWindowSurface` for platform independent Vulkan support
- Added `glfwSetWindowMonitor` for switching between windowed and full screen
modes and updating the monitor and desired video mode of full screen windows
- Added `glfwMaximizeWindow` and `GLFW_MAXIMIZED` for window maximization
- Added `glfwFocusWindow` for giving windows input focus
- Added `glfwSetWindowSizeLimits` and `glfwSetWindowAspectRatio` for setting
absolute and relative window size limits
- Added `glfwGetKeyName` for querying the layout-specific name of printable
keys
- Added `glfwWaitEventsTimeout` for waiting for events for a set amount of time
- Added `glfwSetWindowIcon` for setting the icon of a window
- Added `glfwGetTimerValue` and `glfwGetTimerFrequency` for raw timer access
- Added `glfwSetJoystickCallback` and `GLFWjoystickfun` for joystick connection
and disconnection events
- Added `GLFW_NO_API` for creating window without contexts
- Added `GLFW_INCLUDE_VULKAN` for including the Vulkan header
- Added `GLFW_CONTEXT_CREATION_API`, `GLFW_NATIVE_CONTEXT_API` and
`GLFW_EGL_CONTEXT_API` for run-time context creation API selection
- Added `GLFW_CONTEXT_NO_ERROR` context hint for `GL_KHR_no_error` support
- Added `GLFW_TRUE` and `GLFW_FALSE` as client API independent boolean values
- Added icons to examples on Windows and OS X
- Relaxed rules for native access header macros
- Removed dependency on external OpenGL or OpenGL ES headers
- Removed `_GLFW_USE_OPENGL`, `_GLFW_USE_GLESV1`, `_GLFW_USE_GLESV2`,
`_GLFW_WGL`, `_GLFW_NSGL`, `_GLFW_GLX` and `_GLFW_EGL` configuration macros
- [Win32] Added support for Windows 8.1 per-monitor DPI
- [Win32] Replaced winmm with XInput and DirectInput for joystick input
- [Win32] Bugfix: Window creation would segfault if video mode setting required
the system to be restarted
- [Win32] Bugfix: MinGW import library lacked the `lib` prefix
- [Win32] Bugfix: Monitor connection and disconnection events were not reported
when no windows existed
- [Win32] Bugfix: Activating or deactivating displays in software did not
trigger monitor callback
- [Win32] Bugfix: No monitors were listed on headless and VMware guest systems
- [Win32] Bugfix: Pressing Ctrl+Pause would report `GLFW_KEY_UNKNOWN`
- [Win32] Bugfix: Window size events would be reported in wrong order when
restoring a full screen window
- [Cocoa] Made joystick polling more efficient
- [Cocoa] Removed support for OS X 10.6
- [Cocoa] Bugfix: Full screen windows on secondary monitors were mispositioned
- [Cocoa] Bugfix: Connecting a joystick that reports no name would segfault
- [Cocoa] Bugfix: Modifier flags cache was not updated when window became key
- [Cocoa] Bugfix: Dead key character composition did not work
- [Cocoa] Bugfix: The CGL context was not released until the autorelease pool
was drained by another function
- [X11] Bugfix: Monitor connection and disconnection events were not reported
- [X11] Bugfix: Decoding of UTF-8 text from XIM could continue past the end
- [X11] Bugfix: An XKB structure was leaked during `glfwInit`
- [X11] Bugfix: XInput2 `XI_Motion` events interfered with the Steam overlay
- [POSIX] Bugfix: An unrelated TLS key could be deleted by `glfwTerminate`
- [Linux] Made joystick polling more efficient
- [WGL] Changed extension loading to only be performed once
- [WGL] Removed dependency on external WGL headers
- [GLX] Added `glfwGetGLXWindow` to query the `GLXWindow` of a window
- [GLX] Replaced legacy drawable with `GLXWindow`
- [GLX] Removed dependency on external GLX headers
- [GLX] Bugfix: NetBSD does not provide `libGL.so.1`
- [EGL] Added `_GLFW_USE_EGLPLATFORM_H` configuration macro for controlling
whether to use an existing `EGL/eglplatform.h` header
- [EGL] Added and documented test for if the context is current on the calling
thread during buffer swap
- [EGL] Removed dependency on external EGL headers
- Added `glfwGetError` function for querying the last error code and its
description (#970)
- Added `glfwUpdateGamepadMappings` function for importing gamepad mappings in
SDL\_GameControllerDB format (#900)
- Added `glfwJoystickIsGamepad` function for querying whether a joystick has
a gamepad mapping (#900)
- Added `glfwGetJoystickGUID` function for querying the SDL compatible GUID of
a joystick (#900)
- Added `glfwGetGamepadName` function for querying the name provided by the
gamepad mapping (#900)
- Added `glfwGetGamepadState` function, `GLFW_GAMEPAD_*` and `GLFWgamepadstate`
for retrieving gamepad input state (#900)
- Added `glfwRequestWindowAttention` function for requesting attention from the
user (#732,#988)
- Added `glfwDragWindow` function for starting a drag operation on a window
(#987)
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent
scancodes for keys (#830)
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
receiving window maximization events (#778)
- Added `glfwSetWindowAttrib` function for changing window attributes (#537)
- Added `glfwGetJoystickHats` function for querying joystick hats
(#889,#906,#934)
- Added `glfwInitHint` and `glfwInitHintString` for setting initialization hints
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
- Added definition of `GLAPIENTRY` to public header
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
(#749,#842)
- Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)
- Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint
- Added macOS specific `GLFW_COCOA_FRAME_AUTOSAVE` window hint (#195)
- Added macOS specific `GLFW_COCOA_GRAPHICS_SWITCHING` window hint (#377,#935)
- Added macOS specific `GLFW_COCOA_CHDIR_RESOURCES` init hint
- Added macOS specific `GLFW_COCOA_MENUBAR` init hint
- Added X11 specific `GLFW_X11_WM_CLASS_NAME` and `GLFW_X11_WM_CLASS_CLASS` init
hints (#893)
- Added `GLFW_INCLUDE_ES32` for including the OpenGL ES 3.2 header
- Added `GLFW_OSMESA_CONTEXT_API` for creating OpenGL contexts with
[OSMesa](https://www.mesa3d.org/osmesa.html) (#281)
- Removed `GLFW_USE_RETINA` compile-time option
- Removed `GLFW_USE_CHDIR` compile-time option
- Removed `GLFW_USE_MENUBAR` compile-time option
- Bugfix: Calling `glfwMaximizeWindow` on a full screen window was not ignored
- Bugfix: `GLFW_INCLUDE_VULKAN` could not be combined with the corresponding
OpenGL and OpenGL ES header macros
- Bugfix: `glfwGetInstanceProcAddress` returned `NULL` for
`vkGetInstanceProcAddr` when `_GLFW_VULKAN_STATIC` was enabled
- Bugfix: Invalid library paths were used in test and example CMake files (#930)
- Bugfix: The scancode for synthetic key release events was always zero
- [Win32] Added system error strings to relevant GLFW error descriptions (#733)
- [Win32] Moved to `WM_INPUT` for disabled cursor mode motion input (#125)
- [Win32] Bugfix: Undecorated windows could not be iconified by the user (#861)
- [Win32] Bugfix: Deadzone logic could underflow with some controllers (#910)
- [Win32] Bugfix: Bitness test in `FindVulkan.cmake` was VS specific (#928)
- [Win32] Bugfix: `glfwVulkanSupported` emitted an error on systems with
a loader but no ICD (#916)
- [Win32] Bugfix: Non-iconified full sreeen windows did not prevent screen
blanking or password enabled screensavers (#851)
- [Win32] Bugfix: Mouse capture logic lost secondary release messages (#954)
- [Win32] Bugfix: The 32-bit Vulkan loader library static was not searched for
- [Win32] Bugfix: Vulkan libraries have a new path as of SDK 1.0.42.0 (#956)
- [Win32] Bugfix: Monitors with no display devices were not enumerated (#960)
- [Win32] Bugfix: Monitor events were not emitted (#784)
- [Win32] Bugfix: The Cygwin DLL was installed to the wrong directory (#1035)
- [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125)
- [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading
- [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X
- [X11] Bugfix: Dynamic X11 library loading did not use full sonames (#941)
- [X11] Bugfix: Window creation on 64-bit would read past top of stack (#951)
- [X11] Bugfix: XDND support had multiple non-conformance issues (#968)
- [X11] Bugfix: The RandR monitor path was disabled despite working RandR (#972)
- [X11] Bugfix: IM-duplicated key events would leak at low polling rates (#747)
- [X11] Bugfix: Gamma ramp setting via RandR did not validate ramp size
- [X11] Bugfix: Key name string encoding depended on current locale (#981,#983)
- [Linux] Moved to evdev for joystick input (#906,#1005)
- [Linux] Bugfix: Event processing did not detect joystick disconnection (#932)
- [Linux] Bugfix: The joystick device path could be truncated (#1025)
- [Cocoa] Added support for Vulkan window surface creation via
[MoltenVK](https://moltengl.com/moltenvk/) (#870)
- [Cocoa] Added support for loading a `MainMenu.nib` when available
- [Cocoa] Bugfix: Disabling window aspect ratio would assert (#852)
- [Cocoa] Bugfix: Window creation failed to set first responder (#876,#883)
- [Cocoa] Bugfix: Removed use of deprecated `CGDisplayIOServicePort` function
(#165,#192,#508,#511)
- [Cocoa] Bugfix: Disabled use of deprecated `CGDisplayModeCopyPixelEncoding`
function on macOS 10.12+
- [Cocoa] Bugfix: Running in AppSandbox would emit warnings (#816,#882)
- [Cocoa] Bugfix: Windows created after the first were not cascaded (#195)
- [Cocoa] Bugfix: Leaving video mode with `glfwSetWindowMonitor` would set
incorrect position and size (#748)
- [Cocoa] Bugfix: Iconified full screen windows could not be restored (#848)
- [Cocoa] Bugfix: Value range was ignored for joystick hats and buttons (#888)
- [Cocoa] Bugfix: Full screen framebuffer was incorrectly sized for some video
modes (#682)
- [WGL] Added support for `WGL_EXT_colorspace` for OpenGL ES contexts
- [WGL] Added support for `WGL_ARB_create_context_no_error`
- [GLX] Added support for `GLX_ARB_create_context_no_error`
- [GLX] Bugfix: Context creation could segfault if no GLXFBConfigs were
available (#1040)
- [EGL] Added support for `EGL_KHR_get_all_proc_addresses` (#871)
- [EGL] Added support for `EGL_KHR_context_flush_control`
- [EGL] Bugfix: The test for `EGL_RGB_BUFFER` was invalid
## Contact
The official website for GLFW is [glfw.org](http://www.glfw.org/). There you
can find the latest version of GLFW, as well as news, documentation and other
information about the project.
On [glfw.org](http://www.glfw.org/) you can find the latest version of GLFW, as
well as news, documentation and other information about the project.
If you have questions related to the use of GLFW, we have a
[support forum](http://discourse.glfw.org/), and the IRC
channel `#glfw` on [Freenode](http://freenode.net/).
[forum](http://discourse.glfw.org/), and the `#glfw` IRC channel on
[Freenode](http://freenode.net/).
If you have a bug to report, a patch to submit or a feature you'd like to
request, please file it in the
[issue tracker](https://github.com/glfw/glfw/issues) on GitHub.
Finally, if you're interested in helping out with the development of GLFW or
porting it to your favorite platform, join us on GitHub or IRC.
porting it to your favorite platform, join us on the forum, GitHub or IRC.
## Acknowledgements
@@ -180,13 +258,18 @@ skills.
- John Bartholomew
- Niklas Behrens
- Niklas Bergström
- Denis Bernard
- Doug Binks
- blanco
- Kyle Brenneman
- Martin Capitanio
- David Carlier
- Chi-kwan Chan
- Michał Cichoń
- Lambert Clara
- Andrew Corrigan
- Noel Cower
- Jason Daly
- Jarrod Davis
- Olivier Delannoy
- Paul R. Deppe
@@ -196,8 +279,10 @@ skills.
- Jonathan Dummer
- Ralph Eastwood
- Siavash Eliasi
- Felipe Ferreira
- Michael Fogleman
- Gerald Franz
- Mário Freitas
- GeO4d
- Marcus Geelnard
- Eloi Marín Gratacós
@@ -207,14 +292,17 @@ skills.
- heromyth
- Lucas Hinderberger
- Paul Holden
- Warren Hu
- IntellectualKitty
- Aaron Jacobs
- Erik S. V. Jansson
- Toni Jovanoski
- Arseny Kapoulkine
- Osman Keskin
- Cameron King
- Peter Knut
- Christoph Kubisch
- Konstantin Käfer
- Eric Larson
- Robin Leffmann
- Glenn Lewis
@@ -230,6 +318,7 @@ skills.
- Bryce Mehring
- Jonathan Mercier
- Marcel Metz
- Liam Middlebrook
- Jonathan Miller
- Kenneth Miller
- Bruce Mitchener
@@ -244,10 +333,12 @@ skills.
- Peoro
- Braden Pellett
- Arturo J. Pérez
- Anthony Pesch
- Orson Peters
- Emmanuel Gil Peyrot
- Cyril Pichard
- Pieroman
- Philip Rideout
- Jorge Rodriguez
- Ed Ropple
- Aleksey Rybalkin
@@ -262,17 +353,21 @@ skills.
- Dmitri Shuralyov
- Daniel Skorupski
- Bradley Smith
- Patrick Snape
- Julian Squires
- Johannes Stein
- Michael Stocker
- Justin Stoecker
- Elviss Strazdins
- Nathan Sweet
- TTK-Bandit
- Sergey Tikhomirov
- A. Tombs
- Arthur Tombs
- Ioannis Tsakpinis
- Samuli Tuomola
- Matthew Turner
- urraka
- Elias Vanderstuyft
- Jari Vetoniemi
- Ricardo Vieira
- Nicholas Vitovitch
@@ -283,6 +378,7 @@ skills.
- Jay Weisskopf
- Frank Wille
- yuriks
- Ryogo Yoshimura
- Santi Zupancic
- Jonas Ådahl
- Lasse Öörni
Vendored
+137 -14
View File
@@ -1,3 +1,25 @@
/*
OpenGL loader generated by glad 0.1.12a0 on Fri Sep 23 13:36:15 2016.
Language/Generator: C/C++
Specification: gl
APIs: gl=3.2
Profile: compatibility
Extensions:
GL_ARB_multisample,
GL_ARB_robustness,
GL_KHR_debug
Loader: False
Local files: False
Omit khrplatform: False
Commandline:
--profile="compatibility" --api="gl=3.2" --generator="c" --spec="gl" --no-loader --extensions="GL_ARB_multisample,GL_ARB_robustness,GL_KHR_debug"
Online:
http://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&api=gl%3D3.2&extensions=GL_ARB_multisample&extensions=GL_ARB_robustness&extensions=GL_KHR_debug
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -5,14 +27,59 @@
struct gladGLversionStruct GLVersion;
#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
#define _GLAD_IS_SOME_NEW_VERSION 1
#endif
static int max_loaded_major;
static int max_loaded_minor;
static const char *exts = NULL;
static int num_exts_i = 0;
static const char **exts_i = NULL;
static int get_exts(void) {
#ifdef _GLAD_IS_SOME_NEW_VERSION
if(max_loaded_major < 3) {
#endif
exts = (const char *)glGetString(GL_EXTENSIONS);
#ifdef _GLAD_IS_SOME_NEW_VERSION
} else {
int index;
num_exts_i = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i);
if (num_exts_i > 0) {
exts_i = (const char **)realloc((void *)exts_i, num_exts_i * sizeof *exts_i);
}
if (exts_i == NULL) {
return 0;
}
for(index = 0; index < num_exts_i; index++) {
exts_i[index] = (const char*)glGetStringi(GL_EXTENSIONS, index);
}
}
#endif
return 1;
}
static void free_exts(void) {
if (exts_i != NULL) {
free((char **)exts_i);
exts_i = NULL;
}
}
static int has_ext(const char *ext) {
#if defined(GL_VERSION_3_0) || defined(GL_ES_VERSION_3_0)
if(GLVersion.major < 3 || glGetStringi == NULL) {
#ifdef _GLAD_IS_SOME_NEW_VERSION
if(max_loaded_major < 3) {
#endif
const char *extensions;
const char *loc;
const char *terminator;
extensions = (const char*) glGetString(GL_EXTENSIONS);
extensions = exts;
if(extensions == NULL || ext == NULL) {
return 0;
}
@@ -30,13 +97,14 @@ static int has_ext(const char *ext) {
}
extensions = terminator;
}
#if defined(GL_VERSION_3_0) || defined(GL_ES_VERSION_3_0)
#ifdef _GLAD_IS_SOME_NEW_VERSION
} else {
GLint num_exts, index;
int index;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts);
for(index = 0; index < num_exts; index++) {
if(strcmp((const char*) glGetStringi(GL_EXTENSIONS, index), ext) == 0) {
for(index = 0; index < num_exts_i; index++) {
const char *e = exts_i[index];
if(strcmp(e, ext) == 0) {
return 1;
}
}
@@ -316,7 +384,7 @@ PFNGLRASTERPOS3FPROC glad_glRasterPos3f;
PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
PFNGLTEXCOORD3FPROC glad_glTexCoord3f;
PFNGLDELETESYNCPROC glad_glDeleteSync;
PFNGLTEXCOORD3DPROC glad_glTexCoord3d;
PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
@@ -363,7 +431,7 @@ PFNGLVIEWPORTPROC glad_glViewport;
PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
PFNGLINDEXDVPROC glad_glIndexdv;
PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
PFNGLTEXCOORD3DPROC glad_glTexCoord3d;
PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv;
PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
PFNGLCLEARDEPTHPROC glad_glClearDepth;
@@ -722,9 +790,9 @@ PFNGLCOLORPOINTERPROC glad_glColorPointer;
PFNGLFRONTFACEPROC glad_glFrontFace;
PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
int GLAD_GL_KHR_debug;
int GLAD_GL_ARB_robustness;
int GLAD_GL_ARB_multisample;
int GLAD_GL_EXT_separate_specular_color;
PFNGLSAMPLECOVERAGEARBPROC glad_glSampleCoverageARB;
PFNGLGETGRAPHICSRESETSTATUSARBPROC glad_glGetGraphicsResetStatusARB;
PFNGLGETNTEXIMAGEARBPROC glad_glGetnTexImageARB;
@@ -746,6 +814,27 @@ PFNGLGETNCONVOLUTIONFILTERARBPROC glad_glGetnConvolutionFilterARB;
PFNGLGETNSEPARABLEFILTERARBPROC glad_glGetnSeparableFilterARB;
PFNGLGETNHISTOGRAMARBPROC glad_glGetnHistogramARB;
PFNGLGETNMINMAXARBPROC glad_glGetnMinmaxARB;
PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl;
PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert;
PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback;
PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog;
PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup;
PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup;
PFNGLOBJECTLABELPROC glad_glObjectLabel;
PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel;
PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel;
PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel;
PFNGLDEBUGMESSAGECONTROLKHRPROC glad_glDebugMessageControlKHR;
PFNGLDEBUGMESSAGEINSERTKHRPROC glad_glDebugMessageInsertKHR;
PFNGLDEBUGMESSAGECALLBACKKHRPROC glad_glDebugMessageCallbackKHR;
PFNGLGETDEBUGMESSAGELOGKHRPROC glad_glGetDebugMessageLogKHR;
PFNGLPUSHDEBUGGROUPKHRPROC glad_glPushDebugGroupKHR;
PFNGLPOPDEBUGGROUPKHRPROC glad_glPopDebugGroupKHR;
PFNGLOBJECTLABELKHRPROC glad_glObjectLabelKHR;
PFNGLGETOBJECTLABELKHRPROC glad_glGetObjectLabelKHR;
PFNGLOBJECTPTRLABELKHRPROC glad_glObjectPtrLabelKHR;
PFNGLGETOBJECTPTRLABELKHRPROC glad_glGetObjectPtrLabelKHR;
PFNGLGETPOINTERVKHRPROC glad_glGetPointervKHR;
static void load_GL_VERSION_1_0(GLADloadproc load) {
if(!GLAD_GL_VERSION_1_0) return;
glad_glCullFace = (PFNGLCULLFACEPROC)load("glCullFace");
@@ -1475,10 +1564,38 @@ static void load_GL_ARB_robustness(GLADloadproc load) {
glad_glGetnHistogramARB = (PFNGLGETNHISTOGRAMARBPROC)load("glGetnHistogramARB");
glad_glGetnMinmaxARB = (PFNGLGETNMINMAXARBPROC)load("glGetnMinmaxARB");
}
static void find_extensionsGL(void) {
GLAD_GL_EXT_separate_specular_color = has_ext("GL_EXT_separate_specular_color");
static void load_GL_KHR_debug(GLADloadproc load) {
if(!GLAD_GL_KHR_debug) return;
glad_glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC)load("glDebugMessageControl");
glad_glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC)load("glDebugMessageInsert");
glad_glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC)load("glDebugMessageCallback");
glad_glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC)load("glGetDebugMessageLog");
glad_glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC)load("glPushDebugGroup");
glad_glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC)load("glPopDebugGroup");
glad_glObjectLabel = (PFNGLOBJECTLABELPROC)load("glObjectLabel");
glad_glGetObjectLabel = (PFNGLGETOBJECTLABELPROC)load("glGetObjectLabel");
glad_glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC)load("glObjectPtrLabel");
glad_glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC)load("glGetObjectPtrLabel");
glad_glGetPointerv = (PFNGLGETPOINTERVPROC)load("glGetPointerv");
glad_glDebugMessageControlKHR = (PFNGLDEBUGMESSAGECONTROLKHRPROC)load("glDebugMessageControlKHR");
glad_glDebugMessageInsertKHR = (PFNGLDEBUGMESSAGEINSERTKHRPROC)load("glDebugMessageInsertKHR");
glad_glDebugMessageCallbackKHR = (PFNGLDEBUGMESSAGECALLBACKKHRPROC)load("glDebugMessageCallbackKHR");
glad_glGetDebugMessageLogKHR = (PFNGLGETDEBUGMESSAGELOGKHRPROC)load("glGetDebugMessageLogKHR");
glad_glPushDebugGroupKHR = (PFNGLPUSHDEBUGGROUPKHRPROC)load("glPushDebugGroupKHR");
glad_glPopDebugGroupKHR = (PFNGLPOPDEBUGGROUPKHRPROC)load("glPopDebugGroupKHR");
glad_glObjectLabelKHR = (PFNGLOBJECTLABELKHRPROC)load("glObjectLabelKHR");
glad_glGetObjectLabelKHR = (PFNGLGETOBJECTLABELKHRPROC)load("glGetObjectLabelKHR");
glad_glObjectPtrLabelKHR = (PFNGLOBJECTPTRLABELKHRPROC)load("glObjectPtrLabelKHR");
glad_glGetObjectPtrLabelKHR = (PFNGLGETOBJECTPTRLABELKHRPROC)load("glGetObjectPtrLabelKHR");
glad_glGetPointervKHR = (PFNGLGETPOINTERVKHRPROC)load("glGetPointervKHR");
}
static int find_extensionsGL(void) {
if (!get_exts()) return 0;
GLAD_GL_ARB_multisample = has_ext("GL_ARB_multisample");
GLAD_GL_ARB_robustness = has_ext("GL_ARB_robustness");
GLAD_GL_KHR_debug = has_ext("GL_KHR_debug");
free_exts();
return 1;
}
static void find_coreGL(void) {
@@ -1516,6 +1633,7 @@ static void find_coreGL(void) {
#endif
GLVersion.major = major; GLVersion.minor = minor;
max_loaded_major = major; max_loaded_minor = minor;
GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
@@ -1527,6 +1645,10 @@ static void find_coreGL(void) {
GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3;
GLAD_GL_VERSION_3_1 = (major == 3 && minor >= 1) || major > 3;
GLAD_GL_VERSION_3_2 = (major == 3 && minor >= 2) || major > 3;
if (GLVersion.major > 3 || (GLVersion.major >= 3 && GLVersion.minor >= 2)) {
max_loaded_major = 3;
max_loaded_minor = 2;
}
}
int gladLoadGLLoader(GLADloadproc load) {
@@ -1547,9 +1669,10 @@ int gladLoadGLLoader(GLADloadproc load) {
load_GL_VERSION_3_1(load);
load_GL_VERSION_3_2(load);
find_extensionsGL();
if (!find_extensionsGL()) return 0;
load_GL_ARB_multisample(load);
load_GL_ARB_robustness(load);
load_GL_KHR_debug(load);
return GLVersion.major != 0 || GLVersion.minor != 0;
}
+527 -367
View File
File diff suppressed because it is too large Load Diff
+27 -24
View File
@@ -3,7 +3,7 @@
#include <math.h>
#ifdef _MSC_VER
#ifdef _MSC_VER
#define inline __inline
#endif
@@ -192,19 +192,20 @@ static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z,
vec3 u = {x, y, z};
if(vec3_len(u) > 1e-4) {
mat4x4 T, C, S = {{0}};
vec3_norm(u, u);
mat4x4 T;
mat4x4_from_vec3_mul_outer(T, u, u);
mat4x4 S = {
{ 0, u[2], -u[1], 0},
{-u[2], 0, u[0], 0},
{ u[1], -u[0], 0, 0},
{ 0, 0, 0, 0}
};
S[1][2] = u[0];
S[2][1] = -u[0];
S[2][0] = u[1];
S[0][2] = -u[1];
S[0][1] = u[2];
S[1][0] = -u[2];
mat4x4_scale(S, S, s);
mat4x4 C;
mat4x4_identity(C);
mat4x4_sub(C, C, T);
@@ -213,7 +214,7 @@ static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z,
mat4x4_add(T, T, C);
mat4x4_add(T, T, S);
T[3][3] = 1.;
T[3][3] = 1.;
mat4x4_mul(R, M, T);
} else {
mat4x4_dup(R, M);
@@ -257,6 +258,7 @@ static inline void mat4x4_rotate_Z(mat4x4 Q, mat4x4 M, float angle)
}
static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
{
float idet;
float s[6];
float c[6];
s[0] = M[0][0]*M[1][1] - M[1][0]*M[0][1];
@@ -272,10 +274,10 @@ static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
c[3] = M[2][1]*M[3][2] - M[3][1]*M[2][2];
c[4] = M[2][1]*M[3][3] - M[3][1]*M[2][3];
c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3];
/* Assumes it is invertible */
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] );
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][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet;
T[0][2] = ( M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet;
@@ -298,12 +300,12 @@ static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
}
static inline void mat4x4_orthonormalize(mat4x4 R, mat4x4 M)
{
mat4x4_dup(R, M);
float s = 1.;
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);
@@ -324,7 +326,7 @@ static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t,
{
M[0][0] = 2.f*n/(r-l);
M[0][1] = M[0][2] = M[0][3] = 0.f;
M[1][1] = 2.f*n/(t-b);
M[1][0] = M[1][2] = M[1][3] = 0.f;
@@ -332,7 +334,7 @@ static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t,
M[2][1] = (t+b)/(t-b);
M[2][2] = -(f+n)/(f-n);
M[2][3] = -1.f;
M[3][2] = -2.f*(f*n)/(f-n);
M[3][0] = M[3][1] = M[3][3] = 0.f;
}
@@ -346,7 +348,7 @@ static inline void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, fl
M[2][2] = -2.f/(f-n);
M[2][0] = M[2][1] = M[2][3] = 0.f;
M[3][0] = -(r+l)/(r-l);
M[3][1] = -(t+b)/(t-b);
M[3][2] = -(f+n)/(f-n);
@@ -387,14 +389,15 @@ 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
* operands in the following cross products in the right way. */
vec3 f;
vec3_sub(f, center, eye);
vec3_norm(f, f);
vec3 s;
vec3 t;
vec3_sub(f, center, eye);
vec3_norm(f, f);
vec3_mul_cross(s, f, up);
vec3_norm(s, s);
vec3 t;
vec3_mul_cross(t, s, f);
m[0][0] = s[0];
@@ -470,9 +473,9 @@ static inline void quat_conj(quat r, quat q)
r[3] = q[3];
}
static inline void quat_rotate(quat r, float angle, vec3 axis) {
int i;
vec3 v;
vec3_scale(v, axis, sinf(angle / 2));
int i;
for(i=0; i<3; ++i)
r[i] = v[i];
r[3] = cosf(angle / 2);
@@ -507,7 +510,7 @@ static inline void mat4x4_from_quat(mat4x4 M, quat q)
float b2 = b*b;
float c2 = c*c;
float d2 = d*d;
M[0][0] = a2 + b2 - c2 - d2;
M[0][1] = 2.f*(b*c + a*d);
M[0][2] = 2.f*(b*d - a*c);
+23590
View File
File diff suppressed because it is too large Load Diff
+372
View File
@@ -0,0 +1,372 @@
/*
* Nuklear - v1.32.0 - public domain
* no warrenty implied; use at your own risk.
* authored from 2015-2017 by Micha Mettke
*/
/*
* ==============================================================
*
* API
*
* ===============================================================
*/
#ifndef NK_GLFW_GL2_H_
#define NK_GLFW_GL2_H_
#include <GLFW/glfw3.h>
enum nk_glfw_init_state{
NK_GLFW3_DEFAULT = 0,
NK_GLFW3_INSTALL_CALLBACKS
};
NK_API struct nk_context* nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state);
NK_API void nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas);
NK_API void nk_glfw3_font_stash_end(void);
NK_API void nk_glfw3_new_frame(void);
NK_API void nk_glfw3_render(enum nk_anti_aliasing);
NK_API void nk_glfw3_shutdown(void);
NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
#endif
/*
* ==============================================================
*
* IMPLEMENTATION
*
* ===============================================================
*/
#ifdef NK_GLFW_GL2_IMPLEMENTATION
#ifndef NK_GLFW_TEXT_MAX
#define NK_GLFW_TEXT_MAX 256
#endif
#ifndef NK_GLFW_DOUBLE_CLICK_LO
#define NK_GLFW_DOUBLE_CLICK_LO 0.02
#endif
#ifndef NK_GLFW_DOUBLE_CLICK_HI
#define NK_GLFW_DOUBLE_CLICK_HI 0.2
#endif
struct nk_glfw_device {
struct nk_buffer cmds;
struct nk_draw_null_texture null;
GLuint font_tex;
};
struct nk_glfw_vertex {
float position[2];
float uv[2];
nk_byte col[4];
};
static struct nk_glfw {
GLFWwindow *win;
int width, height;
int display_width, display_height;
struct nk_glfw_device ogl;
struct nk_context ctx;
struct nk_font_atlas atlas;
struct nk_vec2 fb_scale;
unsigned int text[NK_GLFW_TEXT_MAX];
int text_len;
struct nk_vec2 scroll;
double last_button_click;
} glfw;
NK_INTERN void
nk_glfw3_device_upload_atlas(const void *image, int width, int height)
{
struct nk_glfw_device *dev = &glfw.ogl;
glGenTextures(1, &dev->font_tex);
glBindTexture(GL_TEXTURE_2D, dev->font_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, image);
}
NK_API void
nk_glfw3_render(enum nk_anti_aliasing AA)
{
/* setup global state */
struct nk_glfw_device *dev = &glfw.ogl;
glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_TRANSFORM_BIT);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* setup viewport/project */
glViewport(0,0,(GLsizei)glfw.display_width,(GLsizei)glfw.display_height);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0f, glfw.width, glfw.height, 0.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
{
GLsizei vs = sizeof(struct nk_glfw_vertex);
size_t vp = offsetof(struct nk_glfw_vertex, position);
size_t vt = offsetof(struct nk_glfw_vertex, uv);
size_t vc = offsetof(struct nk_glfw_vertex, col);
/* convert from command queue into draw list and draw to screen */
const struct nk_draw_command *cmd;
const nk_draw_index *offset = NULL;
struct nk_buffer vbuf, ebuf;
/* fill convert configuration */
struct nk_convert_config config;
static const struct nk_draw_vertex_layout_element vertex_layout[] = {
{NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)},
{NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)},
{NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)},
{NK_VERTEX_LAYOUT_END}
};
NK_MEMSET(&config, 0, sizeof(config));
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_glfw_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex);
config.null = dev->null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
config.global_alpha = 1.0f;
config.shape_AA = AA;
config.line_AA = AA;
/* convert shapes into vertexes */
nk_buffer_init_default(&vbuf);
nk_buffer_init_default(&ebuf);
nk_convert(&glfw.ctx, &dev->cmds, &vbuf, &ebuf, &config);
/* setup vertex buffer pointer */
{const void *vertices = nk_buffer_memory_const(&vbuf);
glVertexPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vp));
glTexCoordPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vt));
glColorPointer(4, GL_UNSIGNED_BYTE, vs, (const void*)((const nk_byte*)vertices + vc));}
/* iterate over and execute each draw command */
offset = (const nk_draw_index*)nk_buffer_memory_const(&ebuf);
nk_draw_foreach(cmd, &glfw.ctx, &dev->cmds)
{
if (!cmd->elem_count) continue;
glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
glScissor(
(GLint)(cmd->clip_rect.x * glfw.fb_scale.x),
(GLint)((glfw.height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw.fb_scale.y),
(GLint)(cmd->clip_rect.w * glfw.fb_scale.x),
(GLint)(cmd->clip_rect.h * glfw.fb_scale.y));
glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
offset += cmd->elem_count;
}
nk_clear(&glfw.ctx);
nk_buffer_free(&vbuf);
nk_buffer_free(&ebuf);
}
/* default OpenGL state */
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
NK_API void
nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint)
{
(void)win;
if (glfw.text_len < NK_GLFW_TEXT_MAX)
glfw.text[glfw.text_len++] = codepoint;
}
NK_API void
nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
{
(void)win; (void)xoff;
glfw.scroll.x += (float)xoff;
glfw.scroll.y += (float)yoff;
}
NK_API void
nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
double x, y;
if (button != GLFW_MOUSE_BUTTON_LEFT) return;
glfwGetCursorPos(window, &x, &y);
if (action == GLFW_PRESS) {
double dt = glfwGetTime() - glfw.last_button_click;
if (dt > NK_GLFW_DOUBLE_CLICK_LO && dt < NK_GLFW_DOUBLE_CLICK_HI)
nk_input_button(&glfw.ctx, NK_BUTTON_DOUBLE, (int)x, (int)y, nk_true);
glfw.last_button_click = glfwGetTime();
} else nk_input_button(&glfw.ctx, NK_BUTTON_DOUBLE, (int)x, (int)y, nk_false);
}
NK_INTERN void
nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit)
{
const char *text = glfwGetClipboardString(glfw.win);
if (text) nk_textedit_paste(edit, text, nk_strlen(text));
(void)usr;
}
NK_INTERN void
nk_glfw3_clipbard_copy(nk_handle usr, const char *text, int len)
{
char *str = 0;
(void)usr;
if (!len) return;
str = (char*)malloc((size_t)len+1);
if (!str) return;
NK_MEMCPY(str, text, (size_t)len);
str[len] = '\0';
glfwSetClipboardString(glfw.win, str);
free(str);
}
NK_API struct nk_context*
nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state)
{
glfw.win = win;
if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
glfwSetCharCallback(win, nk_glfw3_char_callback);
glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback);
}
nk_init_default(&glfw.ctx, 0);
glfw.ctx.clip.copy = nk_glfw3_clipbard_copy;
glfw.ctx.clip.paste = nk_glfw3_clipbard_paste;
glfw.ctx.clip.userdata = nk_handle_ptr(0);
nk_buffer_init_default(&glfw.ogl.cmds);
return &glfw.ctx;
}
NK_API void
nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas)
{
nk_font_atlas_init_default(&glfw.atlas);
nk_font_atlas_begin(&glfw.atlas);
*atlas = &glfw.atlas;
}
NK_API void
nk_glfw3_font_stash_end(void)
{
const void *image; int w, h;
image = nk_font_atlas_bake(&glfw.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_glfw3_device_upload_atlas(image, w, h);
nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex), &glfw.ogl.null);
if (glfw.atlas.default_font)
nk_style_set_font(&glfw.ctx, &glfw.atlas.default_font->handle);
}
NK_API void
nk_glfw3_new_frame(void)
{
int i;
double x, y;
struct nk_context *ctx = &glfw.ctx;
struct GLFWwindow *win = glfw.win;
glfwGetWindowSize(win, &glfw.width, &glfw.height);
glfwGetFramebufferSize(win, &glfw.display_width, &glfw.display_height);
glfw.fb_scale.x = (float)glfw.display_width/(float)glfw.width;
glfw.fb_scale.y = (float)glfw.display_height/(float)glfw.height;
nk_input_begin(ctx);
for (i = 0; i < glfw.text_len; ++i)
nk_input_unicode(ctx, glfw.text[i]);
/* optional grabbing behavior */
if (ctx->input.mouse.grab)
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
else if (ctx->input.mouse.ungrab)
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_DOWN, glfwGetKey(win, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_UP, glfwGetKey(win, GLFW_KEY_PAGE_UP) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SHIFT, glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS||
glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS);
if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) {
nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_LINE_START, glfwGetKey(win, GLFW_KEY_B) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_LINE_END, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS);
} else {
nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_COPY, 0);
nk_input_key(ctx, NK_KEY_PASTE, 0);
nk_input_key(ctx, NK_KEY_CUT, 0);
nk_input_key(ctx, NK_KEY_SHIFT, 0);
}
glfwGetCursorPos(win, &x, &y);
nk_input_motion(ctx, (int)x, (int)y);
if (ctx->input.mouse.grabbed) {
glfwSetCursorPos(glfw.win, ctx->input.mouse.prev.x, ctx->input.mouse.prev.y);
ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
}
nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
nk_input_scroll(ctx, glfw.scroll);
nk_input_end(&glfw.ctx);
glfw.text_len = 0;
glfw.scroll = nk_vec2(0,0);
}
NK_API
void nk_glfw3_shutdown(void)
{
struct nk_glfw_device *dev = &glfw.ogl;
nk_font_atlas_clear(&glfw.atlas);
nk_free(&glfw.ctx);
glDeleteTextures(1, &dev->font_tex);
nk_buffer_free(&dev->cmds);
NK_MEMSET(&glfw, 0, sizeof(glfw));
}
#endif
+1048
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -21,7 +21,7 @@ freely, subject to the following restrictions:
distribution.
*/
/* 2013-01-06 Camilla Berglund <elmindreda@glfw.org>
/* 2013-01-06 Camilla Löwy <elmindreda@glfw.org>
*
* Added casts from time_t to DWORD to avoid warnings on VC++.
* Fixed time retrieval on POSIX systems.
+3 -1
View File
@@ -123,7 +123,9 @@ typedef int _tthread_clockid_t;
/* Emulate clock_gettime */
int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts);
#define clock_gettime _tthread_clock_gettime
#define CLOCK_REALTIME 0
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
#endif
#endif
+247
View File
@@ -0,0 +1,247 @@
// ISO C9x compliant stdint.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006-2008 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_STDINT_H_ // [
#define _MSC_STDINT_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include <limits.h>
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
// or compiler give many errors like this:
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
#ifdef __cplusplus
extern "C" {
#endif
# include <wchar.h>
#ifdef __cplusplus
}
#endif
// Define _W64 macros to mark types changing their size, like intptr_t.
#ifndef _W64
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
# define _W64 __w64
# else
# define _W64
# endif
#endif
// 7.18.1 Integer types
// 7.18.1.1 Exact-width integer types
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
// realize that, e.g. char has the same size as __int8
// so we give up on __intX for them.
#if (_MSC_VER < 1300)
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
#endif
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
// 7.18.1.2 Minimum-width integer types
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
typedef int64_t int_least64_t;
typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
// 7.18.1.3 Fastest minimum-width integer types
typedef int8_t int_fast8_t;
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
typedef int64_t int_fast64_t;
typedef uint8_t uint_fast8_t;
typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
typedef uint64_t uint_fast64_t;
// 7.18.1.4 Integer types capable of holding object pointers
#ifdef _WIN64 // [
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
#else // _WIN64 ][
typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t;
#endif // _WIN64 ]
// 7.18.1.5 Greatest-width integer types
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
// 7.18.2 Limits of specified-width integer types
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
// 7.18.2.1 Limits of exact-width integer types
#define INT8_MIN ((int8_t)_I8_MIN)
#define INT8_MAX _I8_MAX
#define INT16_MIN ((int16_t)_I16_MIN)
#define INT16_MAX _I16_MAX
#define INT32_MIN ((int32_t)_I32_MIN)
#define INT32_MAX _I32_MAX
#define INT64_MIN ((int64_t)_I64_MIN)
#define INT64_MAX _I64_MAX
#define UINT8_MAX _UI8_MAX
#define UINT16_MAX _UI16_MAX
#define UINT32_MAX _UI32_MAX
#define UINT64_MAX _UI64_MAX
// 7.18.2.2 Limits of minimum-width integer types
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MIN INT64_MIN
#define INT_LEAST64_MAX INT64_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
// 7.18.2.3 Limits of fastest minimum-width integer types
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MIN INT64_MIN
#define INT_FAST64_MAX INT64_MAX
#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
// 7.18.2.4 Limits of integer types capable of holding object pointers
#ifdef _WIN64 // [
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
#else // _WIN64 ][
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
#endif // _WIN64 ]
// 7.18.2.5 Limits of greatest-width integer types
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
// 7.18.3 Limits of other integer types
#ifdef _WIN64 // [
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
#else // _WIN64 ][
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
#endif // _WIN64 ]
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX // [
# ifdef _WIN64 // [
# define SIZE_MAX _UI64_MAX
# else // _WIN64 ][
# define SIZE_MAX _UI32_MAX
# endif // _WIN64 ]
#endif // SIZE_MAX ]
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
#ifndef WCHAR_MIN // [
# define WCHAR_MIN 0
#endif // WCHAR_MIN ]
#ifndef WCHAR_MAX // [
# define WCHAR_MAX _UI16_MAX
#endif // WCHAR_MAX ]
#define WINT_MIN 0
#define WINT_MAX _UI16_MAX
#endif // __STDC_LIMIT_MACROS ]
// 7.18.4 Limits of other integer types
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
// 7.18.4.1 Macros for minimum-width integer constants
#define INT8_C(val) val##i8
#define INT16_C(val) val##i16
#define INT32_C(val) val##i32
#define INT64_C(val) val##i64
#define UINT8_C(val) val##ui8
#define UINT16_C(val) val##ui16
#define UINT32_C(val) val##ui32
#define UINT64_C(val) val##ui64
// 7.18.4.2 Macros for greatest-width integer constants
#define INTMAX_C INT64_C
#define UINTMAX_C UINT64_C
#endif // __STDC_CONSTANT_MACROS ]
#endif // _MSC_STDINT_H_ ]
+7 -7
View File
@@ -51,13 +51,13 @@ extern "C"
#define VKAPI_ATTR
#define VKAPI_CALL __stdcall
#define VKAPI_PTR VKAPI_CALL
#elif defined(__ANDROID__) && defined(__ARM_EABI__) && !defined(__ARM_ARCH_7A__)
// Android does not support Vulkan in native code using the "armeabi" ABI.
#error "Vulkan requires the 'armeabi-v7a' or 'armeabi-v7a-hard' ABI on 32-bit ARM CPUs"
#elif defined(__ANDROID__) && defined(__ARM_ARCH_7A__)
// On Android/ARMv7a, Vulkan functions use the armeabi-v7a-hard calling
// convention, even if the application's native code is compiled with the
// armeabi-v7a calling convention.
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
#error "Vulkan isn't supported for the 'armeabi' NDK ABI"
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
// On Android 32-bit ARM targets, Vulkan functions use the "hardfloat"
// calling convention, i.e. float parameters are passed in registers. This
// is true even if the rest of the application passes floats on the stack,
// as it does by default when compiling for the armeabi-v7a NDK ABI.
#define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
#define VKAPI_CALL
#define VKAPI_PTR VKAPI_ATTR
+942 -14
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -17,7 +17,9 @@ set(glfw_DOCS_SOURCES
"${GLFW_SOURCE_DIR}/docs/compat.dox")
if (GLFW_DOCUMENT_INTERNALS)
list(APPEND glfw_DOCS_SOURCES "${GLFW_SOURCE_DIR}/src/internal.h")
list(APPEND glfw_DOCS_SOURCES
"${GLFW_SOURCE_DIR}/docs/internal.dox"
"${GLFW_SOURCE_DIR}/src/internal.h")
endif()
foreach(arg ${glfw_DOCS_SOURCES})
+5 -2
View File
@@ -202,8 +202,10 @@ ALIASES = "thread_safety=@par Thread safety\n" \
"errors=@par Errors\n" \
"glfw3=@par\n__GLFW 3:__" \
"x11=__X11:__" \
"wayland=__Wayland:__" \
"win32=__Windows:__" \
"osx=__OS X:__"
"macos=__macOS:__" \
"linux=__Linux:__"
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding
@@ -467,7 +469,7 @@ INLINE_INFO = YES
# alphabetically by member name. If set to NO the members will appear in
# declaration order.
SORT_MEMBER_DOCS = YES
SORT_MEMBER_DOCS = NO
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
# brief documentation of file, namespace and class members alphabetically
@@ -1576,6 +1578,7 @@ PREDEFINED = GLFWAPI= \
GLFW_EXPOSE_NATIVE_COCOA \
GLFW_EXPOSE_NATIVE_NSGL \
GLFW_EXPOSE_NATIVE_EGL \
GLFW_EXPOSE_NATIVE_OSMESA \
VK_VERSION_1_0
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+121 -58
View File
@@ -15,27 +15,27 @@ specific compiler of your chosen development environment. The compilation
and linking process should be explained in your C programming material and in
the documentation for your development environment.
@section build_include Including the GLFW header file
In the source files of your application where you use OpenGL or GLFW, you should
include the GLFW header file, i.e.:
You should include the GLFW header in the source files where you use OpenGL or
GLFW.
@code
#include <GLFW/glfw3.h>
@endcode
The GLFW header declares the GLFW API and by default also includes the OpenGL
header of your development environment, which in turn defines all the constants,
types and function prototypes of the OpenGL API.
This header declares the GLFW API and by default also includes the OpenGL header
from your development environment. See below for how to control this.
The GLFW header also defines everything necessary for your OpenGL header to
function. For example, under Windows you are normally required to include
`windows.h` before the OpenGL header, which would pollute your code namespace
with the entire Win32 API.
The GLFW header also defines any platform-specific macros needed by your OpenGL
header, so it can be included without needing any window system headers.
Instead, the GLFW header takes care of this for you, not by including
`windows.h`, but by duplicating only the very few necessary parts of it. It
does this only when needed, so if `windows.h` _is_ included, the GLFW header
For example, under Windows you are normally required to include `windows.h`
before the OpenGL header, which would bring in the whole Win32 API. The GLFW
header duplicates the small number of macros needed.
It does this only when needed, so if `windows.h` _is_ included, the GLFW header
does not try to redefine those symbols. The reverse is not true, i.e.
`windows.h` cannot cope if any of its symbols have already been defined.
@@ -49,8 +49,21 @@ In other words:
If you are using an OpenGL extension loading library such as
[glad](https://github.com/Dav1dde/glad), the extension loader header should
either be included _before_ the GLFW one, or the `GLFW_INCLUDE_NONE` macro
(described below) should be defined.
be included _before_ the GLFW one.
@code
#include <glad/glad.h>
#include <GLFW/glfw3.h>
@endcode
Alternatively the @ref GLFW_INCLUDE_NONE macro (described below) can be used to
prevent the GLFW header from including the OpenGL header.
@code
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <glad/glad.h>
@endcode
@subsection build_macros GLFW header option macros
@@ -58,52 +71,67 @@ either be included _before_ the GLFW one, or the `GLFW_INCLUDE_NONE` macro
These macros may be defined before the inclusion of the GLFW header and affect
its behavior.
`GLFW_DLL` is required on Windows when using the GLFW DLL, to tell the compiler
that the GLFW functions are defined in a DLL.
@anchor GLFW_DLL
__GLFW_DLL__ is required on Windows when using the GLFW DLL, to tell the
compiler that the GLFW functions are defined in a DLL.
The following macros control which OpenGL or OpenGL ES API header is included.
Only one of these may be defined at a time.
`GLFW_INCLUDE_GLCOREARB` makes the GLFW header include the modern
`GL/glcorearb.h` header (`OpenGL/gl3.h` on OS X) instead of the regular OpenGL
@anchor GLFW_INCLUDE_GLCOREARB
__GLFW_INCLUDE_GLCOREARB__ makes the GLFW header include the modern
`GL/glcorearb.h` header (`OpenGL/gl3.h` on macOS) instead of the regular OpenGL
header.
`GLFW_INCLUDE_ES1` makes the GLFW header include the OpenGL ES 1.x `GLES/gl.h`
@anchor GLFW_INCLUDE_ES1
__GLFW_INCLUDE_ES1__ makes the GLFW header include the OpenGL ES 1.x `GLES/gl.h`
header instead of the regular OpenGL header.
`GLFW_INCLUDE_ES2` makes the GLFW header include the OpenGL ES 2.0 `GLES2/gl2.h`
header instead of the regular OpenGL header.
@anchor GLFW_INCLUDE_ES2
__GLFW_INCLUDE_ES2__ makes the GLFW header include the OpenGL ES 2.0
`GLES2/gl2.h` header instead of the regular OpenGL header.
`GLFW_INCLUDE_ES3` makes the GLFW header include the OpenGL ES 3.0 `GLES3/gl3.h`
header instead of the regular OpenGL header.
@anchor GLFW_INCLUDE_ES3
__GLFW_INCLUDE_ES3__ makes the GLFW header include the OpenGL ES 3.0
`GLES3/gl3.h` header instead of the regular OpenGL header.
`GLFW_INCLUDE_ES31` makes the GLFW header include the OpenGL ES 3.1 `GLES3/gl31.h`
header instead of the regular OpenGL header.
@anchor GLFW_INCLUDE_ES31
__GLFW_INCLUDE_ES31__ makes the GLFW header include the OpenGL ES 3.1
`GLES3/gl31.h` header instead of the regular OpenGL header.
`GLFW_INCLUDE_VULKAN` makes the GLFW header include the Vulkan `vulkan/vulkan.h`
header instead of the regular OpenGL header.
@anchor GLFW_INCLUDE_ES32
__GLFW_INCLUDE_ES31__ makes the GLFW header include the OpenGL ES 3.2
`GLES3/gl32.h` header instead of the regular OpenGL header.
`GLFW_INCLUDE_NONE` makes the GLFW header not include any OpenGL or OpenGL ES API
header. This is useful in combination with an extension loading library.
@anchor GLFW_INCLUDE_NONE
__GLFW_INCLUDE_NONE__ makes the GLFW header not include any OpenGL or OpenGL ES
API header. This is useful in combination with an extension loading library.
If none of the above inclusion macros are defined, the standard OpenGL `GL/gl.h`
header (`OpenGL/gl.h` on OS X) is included.
header (`OpenGL/gl.h` on macOS) is included.
The following macros control the inclusion of additional API headers. Any
number of these may be defined simultaneously, and/or together with one of the
above macros.
`GLFW_INCLUDE_GLEXT` makes the GLFW header include the appropriate extension
@anchor GLFW_INCLUDE_VULKAN
__GLFW_INCLUDE_VULKAN__ makes the GLFW header include the Vulkan
`vulkan/vulkan.h` header in addition to any selected OpenGL or OpenGL ES header.
@anchor GLFW_INCLUDE_GLEXT
__GLFW_INCLUDE_GLEXT__ makes the GLFW header include the appropriate extension
header for the OpenGL or OpenGL ES header selected above after and in addition
to that header.
`GLFW_INCLUDE_GLU` makes the header include the GLU header in addition to the
@anchor GLFW_INCLUDE_GLU
__GLFW_INCLUDE_GLU__ makes the header include the GLU header in addition to the
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
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 or OpenGL ES SDK.
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.
If your build includes GLFW and you define any these in your build files, make
@@ -118,7 +146,7 @@ a shared library / dynamic library / DLL then it takes care of these links.
However, if you are using GLFW as a static library then your executable will
need to link against these libraries.
On Windows and OS X, the list of system libraries is static and can be
On Windows and macOS, the list of system libraries is static and can be
hard-coded into your build environment. See the section for your development
environment below. On Linux and other Unix-like operating systems, the list
varies but can be retrieved in various ways as described below.
@@ -140,9 +168,9 @@ set of default libraries along with other dependencies like `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
application that uses the DLL version of GLFW, you need to define the `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.
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
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 `opengl32` if your application
@@ -177,28 +205,43 @@ add_subdirectory(path/to/glfw)
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,
the include directory for the GLFW header and, when applicable, the
[GLFW_DLL](@ref build_macros) macro.
the include directory for the GLFW header and, when applicable, the @ref
GLFW_DLL macro.
@code{.cmake}
target_link_libraries(myapp glfw)
@endcode
Note that it does not include GLU, as GLFW does not use it. If your application
needs GLU, you can find it by requiring the OpenGL package.
Note that the dependencies do not include OpenGL or GLU, as GLFW loads any
OpenGL, OpenGL ES or Vulkan libraries it needs at runtime and does not use GLU.
If your application calls OpenGL directly, instead of using a modern
[extension loader library](@ref context_glext_auto) you can find it by requiring
the OpenGL package.
@code{.cmake}
find_package(OpenGL REQUIRED)
@endcode
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.
If OpenGL is found, the `OPENGL_FOUND` variable is true and the
`OPENGL_INCLUDE_DIR` and `OPENGL_gl_LIBRARY` cache variables can be used.
@code{.cmake}
target_include_directories(myapp ${OPENGL_INCLUDE_DIR})
target_link_libraries(myapp ${OPENGL_gl_LIBRARY})
@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
@@ -210,33 +253,48 @@ With just a few changes to your `CMakeLists.txt`, you can locate the package and
target files generated when GLFW is installed.
@code{.cmake}
find_package(glfw3 3.2 REQUIRED)
find_package(glfw3 3.3 REQUIRED)
@endcode
Once GLFW has been located, link against it with the `glfw` target. This adds
all link-time dependencies of GLFW as it is currently configured, the include
directory for the GLFW header and, when applicable, the
[GLFW_DLL](@ref build_macros) macro.
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,
the include directory for the GLFW header and, when applicable, the @ref
GLFW_DLL macro.
@code{.cmake}
target_link_libraries(myapp glfw)
@endcode
Note that it does not include GLU, as GLFW does not use it. If your application
needs GLU, you can find it by requiring the OpenGL package.
Note that the dependencies do not include OpenGL or GLU, as GLFW loads any
OpenGL, OpenGL ES or Vulkan libraries it needs at runtime and does not use GLU.
If your application calls OpenGL directly, instead of using a modern
[extension loader library](@ref context_glext_auto) you can find it by requiring
the OpenGL package.
@code{.cmake}
find_package(OpenGL REQUIRED)
@endcode
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.
If OpenGL is found, the `OPENGL_FOUND` variable is true and the
`OPENGL_INCLUDE_DIR` and `OPENGL_gl_LIBRARY` cache variables can be used.
@code{.cmake}
target_include_directories(myapp ${OPENGL_INCLUDE_DIR})
target_link_libraries(myapp ${OPENGL_gl_LIBRARY})
@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
@@ -268,8 +326,9 @@ You can also use the `glfw3.pc` file without installing it first, by using the
env PKG_CONFIG_PATH=path/to/glfw/src cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --libs glfw3`
@endcode
The dependencies do not include GLU, as GLFW does not use it. On OS X, GLU is
built into the OpenGL framework, so if you need GLU you don't need to do
The dependencies do not include OpenGL or GLU, as GLFW loads any OpenGL, OpenGL
ES or Vulkan libraries it needs at runtime and does not use GLU. On macOS, GLU
is built into the OpenGL framework, so if you need GLU you don't need to do
anything extra. If you need GLU and are using Linux or BSD, you should add the
`glu` pkg-config package.
@@ -277,6 +336,10 @@ anything extra. If you need GLU and are using Linux or BSD, you should add the
cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --libs glfw3 glu`
@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.
@@ -285,7 +348,7 @@ cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --static --lib
@endcode
@subsection build_link_xcode With Xcode on OS X
@subsection build_link_xcode With Xcode on macOS
If you are using the dynamic library version of GLFW, simply add it to the
project dependencies.
@@ -295,10 +358,10 @@ OpenGL, IOKit and CoreVideo frameworks to the project as dependencies. They can
all be found in `/System/Library/Frameworks`.
@subsection build_link_osx With command-line on OS X
@subsection build_link_osx With command-line on macOS
It is recommended that you use [pkg-config](@ref build_link_pkgconfig) when
building from the command line on OS X. That way you will get any new
building from the command line on macOS. That way you will get any new
dependencies added automatically. If you still wish to build manually, you need
to add the required frameworks and libraries to your command-line yourself using
the `-l` and `-framework` switches.
@@ -318,6 +381,6 @@ against it from the command-line.
The OpenGL framework contains both the OpenGL and GLU APIs, so there is nothing
special to do when using GLU. Also note that even though your machine may have
`libGL`-style OpenGL libraries, they are for use with the X Window System and
will _not_ work with the OS X native version of GLFW.
will _not_ work with the macOS native version of GLFW.
*/
+21 -14
View File
@@ -76,6 +76,10 @@ GLFW uses the Xkb extension and detectable auto-repeat to provide keyboard
input. If the running X server does not support this extension, a non-Xkb
fallback path is used.
GLFW uses the XInput2 extension to provide raw, non-accelerated mouse motion
when the cursor is disabled. If the running X server does not support this
extension, regular accelerated mouse motion will be used.
@section compat_glx GLX extensions
@@ -160,21 +164,21 @@ extensions to provide support for sRGB framebuffers. Where both of these
extension are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
@section compat_osx OpenGL 3.2 and later on OS X
@section compat_osx OpenGL on macOS
Support for OpenGL 3.2 and above was introduced with OS X 10.7 and even then
only forward-compatible, core profile contexts are supported. Support for
OpenGL 4.1 was introduced with OS X 10.9, also limited to forward-compatible,
core profile contexts. There is also still no mechanism for requesting debug
contexts. Versions of Mac OS X earlier than 10.7 support at most OpenGL
version 2.1.
contexts or no-error contexts. Versions of Mac OS X earlier than 10.7 support
at most OpenGL version 2.1.
Because of this, on OS X 10.7 and later, the `GLFW_CONTEXT_VERSION_MAJOR` and
`GLFW_CONTEXT_VERSION_MINOR` hints will cause @ref glfwCreateWindow to fail if
given version 3.0 or 3.1, the `GLFW_OPENGL_FORWARD_COMPAT` hint must be set to
given version 3.0 or 3.1. The `GLFW_OPENGL_FORWARD_COMPAT` hint must be set to
`GLFW_TRUE` and the `GLFW_OPENGL_PROFILE` hint must be set to
`GLFW_OPENGL_CORE_PROFILE` when creating OpenGL 3.2 and later contexts and the
`GLFW_OPENGL_DEBUG_CONTEXT` hint is ignored.
`GLFW_OPENGL_CORE_PROFILE` when creating OpenGL 3.2 and later contexts. The
`GLFW_OPENGL_DEBUG_CONTEXT` and `GLFW_CONTEXT_NO_ERROR` hints are ignored.
Also, on Mac OS X 10.6 and below, the `GLFW_CONTEXT_VERSION_MAJOR` and
`GLFW_CONTEXT_VERSION_MINOR` hints will fail if given a version above 2.1,
@@ -185,10 +189,12 @@ a non-default value will cause @ref glfwCreateWindow to fail and the
@section compat_vulkan Vulkan loader and API
GLFW uses the standard system-wside Vulkan loader to access the Vulkan API.
This should be installed by graphics drivers and Vulkan SDKs. If this is not
available, @ref glfwVulkanSupported will return `GLFW_FALSE` and all other
Vulkan-related functions will fail with an @ref GLFW_API_UNAVAILABLE error.
By default, GLFW uses the standard system-wide Vulkan loader to access the
Vulkan API on all platforms except macOS. This is installed by both graphics
drivers and Vulkan SDKs. If either the loader or at least one minimally
functional ICD is missing, @ref glfwVulkanSupported will return `GLFW_FALSE` and
all other Vulkan-related functions will fail with an @ref GLFW_API_UNAVAILABLE
error.
@section compat_wsi Vulkan WSI extensions
@@ -201,6 +207,11 @@ surfaces on Microsoft Windows. If any of these extensions are not available,
@ref glfwGetRequiredInstanceExtensions will return an empty list and window
surface creation will fail.
GLFW uses the `VK_KHR_surface` and `VK_MVK_macos_surface` extensions to create
surfaces on macOS. If any of these extensions are not available, @ref
glfwGetRequiredInstanceExtensions will return an empty list and window surface
creation will fail.
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`
or both `VK_KHR_xlib_surface` and `VK_KHR_xcb_surface` are not available, @ref
@@ -217,8 +228,4 @@ surfaces on Mir. If any of these extensions are not available, @ref
glfwGetRequiredInstanceExtensions will return an empty list and window surface
creation will fail.
GLFW does not support any extensions for window surface creation on OS X,
meaning@ref glfwGetRequiredInstanceExtensions will return an empty list and
window surface creation will fail.
*/
+49 -51
View File
@@ -14,7 +14,8 @@ GLFW uses [CMake](http://www.cmake.org/) to generate project files or makefiles
for a particular development environment. If you are on a Unix-like system such
as Linux or FreeBSD or have a package system like Fink, MacPorts, Cygwin or
Homebrew, you can simply install its CMake package. If not, you can download
installers for Windows and OS X from the [CMake website](http://www.cmake.org/).
installers for Windows and macOS from the
[CMake website](http://www.cmake.org/).
@note CMake only generates project files or makefiles. It does not compile the
actual GLFW library. To compile GLFW, first generate these files for your
@@ -76,11 +77,11 @@ the CMake wiki.
Once you have this set up, move on to @ref compile_generate.
@subsubsection compile_deps_xcode Dependencies for Xcode on OS X
@subsubsection compile_deps_xcode Dependencies for Xcode on macOS
Xcode comes with all necessary tools except for CMake. The required headers
and libraries are included in the core OS X frameworks. Xcode can be downloaded
from the Mac App Store or from the ADC Member Center.
and libraries are included in the core macOS frameworks. Xcode can be
downloaded from the Mac App Store or from the ADC Member Center.
Once you have Xcode installed, move on to @ref compile_generate.
@@ -96,6 +97,17 @@ Once you have installed the necessary packages, move on to @ref
compile_generate.
@subsection compile_deps_osmesa Dependencies for Linux and OSMesa
To compile GLFW for OSMesa, you need to install the OSMesa library and header
packages. For example, on Ubuntu and other distributions based on Debian
GNU/Linux, you need to install the `libosmesa6-dev` package. The OSMesa library
is required at runtime for context creation and is loaded on demand.
Once you have installed the necessary packages, move on to @ref
compile_generate.
@subsection compile_generate Generating build files with CMake
Once you have all necessary dependencies it is time to generate the project
@@ -181,44 +193,41 @@ cmake -DBUILD_SHARED_LIBS=ON .
@subsubsection compile_options_shared Shared CMake options
`BUILD_SHARED_LIBS` determines whether GLFW is built as a static
@anchor BUILD_SHARED_LIBS
__BUILD_SHARED_LIBS__ determines whether GLFW is built as a static
library or as a DLL / shared library / dynamic library.
`LIB_SUFFIX` affects where the GLFW shared /dynamic library is installed. If it
is empty, it is installed to `${CMAKE_INSTALL_PREFIX}/lib`. If it is set to
@anchor LIB_SUFFIX
__LIB_SUFFIX__ affects where the GLFW shared /dynamic library is installed. If
it is empty, it is installed to `${CMAKE_INSTALL_PREFIX}/lib`. If it is set to
`64`, it is installed to `${CMAKE_INSTALL_PREFIX}/lib64`.
`GLFW_BUILD_EXAMPLES` determines whether the GLFW examples are built
@anchor GLFW_BUILD_EXAMPLES
__GLFW_BUILD_EXAMPLES__ determines whether the GLFW examples are built
along with the library.
`GLFW_BUILD_TESTS` determines whether the GLFW test programs are
@anchor GLFW_BUILD_TESTS
__GLFW_BUILD_TESTS__ determines whether the GLFW test programs are
built along with the library.
`GLFW_BUILD_DOCS` determines whether the GLFW documentation is built along with
the library.
@anchor GLFW_BUILD_DOCS
__GLFW_BUILD_DOCS__ determines whether the GLFW documentation is built along
with the library.
@subsubsection compile_options_osx OS X specific CMake options
`GLFW_USE_CHDIR` determines whether `glfwInit` changes the current
directory of bundled applications to the `Contents/Resources` directory.
`GLFW_USE_MENUBAR` determines whether the first call to
`glfwCreateWindow` sets up a minimal menu bar.
`GLFW_USE_RETINA` determines whether windows will use the full resolution of
Retina displays.
@anchor GLFW_VULKAN_STATIC
__GLFW_VULKAN_STATIC__ determines whether to use the Vulkan loader linked
statically into the application.
@subsubsection compile_options_win32 Windows specific CMake options
`USE_MSVC_RUNTIME_LIBRARY_DLL` determines whether to use the DLL version or the
@anchor USE_MSVC_RUNTIME_LIBRARY_DLL
__USE_MSVC_RUNTIME_LIBRARY_DLL__ determines whether to use the DLL version or the
static library version of the Visual C++ runtime library. If set to `ON`, the
DLL version of the Visual C++ library is used. It is recommended to set this to
`ON`, as this keeps the executable smaller and benefits from security and bug
fix updates of the Visual C++ runtime.
DLL version of the Visual C++ library is used.
`GLFW_USE_HYBRID_HPG` determines whether to export the `NvOptimusEnablement` and
@anchor GLFW_USE_HYBRID_HPG
__GLFW_USE_HYBRID_HPG__ determines whether to export the `NvOptimusEnablement` and
`AmdPowerXpressRequestHighPerformance` symbols, which force the use of the
high-performance GPU on Nvidia Optimus and AMD PowerXpress systems. These symbols
need to be exported by the EXE to be detected by the driver, so the override
@@ -235,43 +244,32 @@ features.
When building with CMake, the `glfw_config.h` configuration header is generated
based on the current platform and CMake options. The GLFW CMake environment
defines `_GLFW_USE_CONFIG_H`, which causes this header to be included by
defines @b GLFW_USE_CONFIG_H, which causes this header to be included by
`internal.h`. Without this macro, GLFW will expect the necessary configuration
macros to be defined on the command-line.
The window creation API is used to create windows, handle input, monitors, gamma
ramps and clipboard. The options are:
- `_GLFW_COCOA` to use the Cocoa frameworks
- `_GLFW_WIN32` to use the Win32 API
- `_GLFW_X11` to use the X Window System
- `_GLFW_WAYLAND` to use the Wayland API (experimental and incomplete)
- `_GLFW_MIR` to use the Mir API (experimental and incomplete)
- @b _GLFW_COCOA to use the Cocoa frameworks
- @b _GLFW_WIN32 to use the Win32 API
- @b _GLFW_X11 to use the X Window System
- @b _GLFW_WAYLAND to use the Wayland API (experimental and incomplete)
- @b _GLFW_MIR to use the Mir API (experimental and incomplete)
- @b _GLFW_OSMESA to use the OSMesa API (headless and non-interactive)
If you are building GLFW as a shared library / dynamic library / DLL then you
must also define `_GLFW_BUILD_DLL`. Otherwise, you must not define it.
must also define @b _GLFW_BUILD_DLL. Otherwise, you must not define it.
If you are linking the Vulkan loader statically into your application then you
must also define @b _GLFW_VULKAN_STATIC. Otherwise, GLFW will attempt to use the
external version.
For the EGL context creation API, the following options are available:
- `_GLFW_USE_EGLPLATFORM_H` to use `EGL/eglplatform.h` for native handle
- @b _GLFW_USE_EGLPLATFORM_H to use `EGL/eglplatform.h` for native handle
definitions (fallback)
If you are using the X11 window creation API, support for the following X11
extensions can be enabled:
- `_GLFW_HAS_XF86VM` to use Xxf86vm as a fallback when RandR gamma is broken
(recommended)
If you are using the Cocoa window creation API, the following options are
available:
- `_GLFW_USE_CHDIR` to `chdir` to the `Resources` subdirectory of the
application bundle during @ref glfwInit (recommended)
- `_GLFW_USE_MENUBAR` to create and populate the menu bar when the first window
is created (recommended)
- `_GLFW_USE_RETINA` to have windows use the full resolution of Retina displays
(recommended)
@note None of the @ref build_macros may be defined during the compilation of
GLFW. If you define any of these in your build files, make sure they are not
applied to the GLFW sources.
+12 -14
View File
@@ -5,9 +5,8 @@
@tableofcontents
This guide introduces the OpenGL and OpenGL ES context related functions of
GLFW. For details on a specific function, see the
[reference documentation](@ref context). There are also guides for the other
areas of the GLFW API.
GLFW. For details on a specific function in this category, see the @ref
context. There are also guides for the other areas of the GLFW API.
- @ref intro_guide
- @ref window_guide
@@ -31,8 +30,8 @@ the `glfwinfo` test program.
@note Vulkan does not have a context and the Vulkan instance is created via the
Vulkan API itself. If you will be using Vulkan to render to a window, disable
context creation by setting the [GLFW_CLIENT_API](@ref window_hints_ctx) hint to
`GLFW_NO_API`. For more information, see the @ref vulkan_guide.
context creation by setting the [GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint)
hint to `GLFW_NO_API`. For more information, see the @ref vulkan_guide.
@subsection context_hints Context creation hints
@@ -69,7 +68,7 @@ GLFW comes with a simple object sharing test program called `sharing`.
GLFW doesn't support creating contexts without an associated window. However,
contexts with hidden windows can be created with the
[GLFW_VISIBLE](@ref window_hints_wnd) window hint.
[GLFW_VISIBLE](@ref GLFW_VISIBLE_hint) window hint.
@code
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
@@ -85,17 +84,16 @@ objects are recommended for rendering with such contexts.
You should still [process events](@ref events) as long as you have at least one
window, even if none of them are visible.
__OS X:__ The first time a window is created the menu bar is populated with
common commands like Hide, Quit and About. This is not desirable for example
when writing a command-line only application. The menu bar setup can be
disabled with a [compile-time option](@ref compile_options_osx).
@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
You can disable context creation by setting the
[GLFW_CLIENT_API](@ref window_hints_ctx) hint to `GLFW_NO_API`. Windows without
contexts must not be passed to @ref glfwMakeContextCurrent or @ref
[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_NO_API`. Windows
without contexts must not be passed to @ref glfwMakeContextCurrent or @ref
glfwSwapBuffers.
@@ -267,8 +265,8 @@ supports. These have names like `PFNGLGETDEBUGMESSAGELOGARBPROC` (for
`glGetDebugMessageLogARB`), i.e. the name is made uppercase and `PFN` (pointer
to function) and `PROC` (procedure) are added to the ends.
To include the extension header, define [GLFW_INCLUDE_GLEXT](@ref build_macros)
before including the GLFW header.
To include the extension header, define @ref GLFW_INCLUDE_GLEXT before including
the GLFW header.
@code
#define GLFW_INCLUDE_GLEXT
+1 -1
View File
File diff suppressed because one or more lines are too long
+27 -1
View File
@@ -76,8 +76,17 @@
border:2px solid desaturate(darken(@base-color, 10%), 20%);
}
.sm-dox,.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted,.sm-dox ul a:hover {
background:none;
text-shadow:none;
}
#navrow1,#navrow2,#navrow3,#navrow4,.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code {
.sm-dox ul a:hover {
background:@header-footer-link-color;
text-shadow:none;
}
#main-nav,#navrow1,#navrow2,#navrow3,#navrow4,.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code {
background:none;
}
@@ -183,6 +192,13 @@ address.footer {
background:@header-footer-link-color;
}
#main-nav {
max-width:960px;
min-width:800px;
margin:0 auto;
font-size:13px;
}
#navrow1,#navrow2,#navrow3,#navrow4 {
max-width:920px;
min-width:800px;
@@ -190,6 +206,15 @@ address.footer {
font-size:13px;
}
.memtitle {
display:none;
}
.memproto,.memname {
font-weight:bold;
text-shadow:none;
}
.tablist {
height:36px;
display:block;
@@ -222,6 +247,7 @@ table.doxtable th,dl.reflist dt {
background:linear-gradient(to bottom,@table-background-color2 0%,@table-background-color1 100%);
box-shadow:inset 0 0 32px @table-background-color1;
text-shadow:0 -1px 1px darken(@table-background-color1, 15%);
text-align:left;
color:@table-text-color;
}
+279 -47
View File
@@ -5,19 +5,19 @@
@tableofcontents
This guide introduces the input related functions of GLFW. For details on
a specific function, see the [reference documentation](@ref input). There are
also guides for the other areas of GLFW.
a specific function in this category, see the @ref input. There are also guides
for the other areas of GLFW.
- @ref intro_guide
- @ref window_guide
- @ref context_guide
- @ref vulkan_guide
- @ref monitor_guide
GLFW provides many kinds of input. While some can only be polled, like time, or
only received via callbacks, like scrolling, there are those that provide both
callbacks and polling. Where a callback is provided, that is the recommended
way to receive that kind of input. The more you can use callbacks the less time
your users' machines will need to spend polling.
only received via callbacks, like scrolling, many provide both callbacks and
polling. Callbacks are more work to use than polling but is less CPU intensive
and guarantees that you do not miss state changes.
All input callbacks receive a window handle. By using the
[window user pointer](@ref window_userptr), you can access non-global structures
@@ -31,14 +31,14 @@ information.
@section events Event processing
GLFW needs to communicate regularly with the window system both in order to
receive events and to show that the application hasn't locked up. Event
processing must be done regularly while you have any windows and is normally
done each frame after [buffer swapping](@ref buffer_swap). Even when you have
no windows, event polling needs to be done in order to receive monitor
connection events.
GLFW needs to poll the window system for events both to provide input to the
application and to prove to the window system that the application hasn't locked
up. Event processing is normally done each frame after
[buffer swapping](@ref buffer_swap). Even when you have no windows, event
polling needs to be done in order to receive monitor and joystick connection
events.
There are two functions for processing pending events. @ref glfwPollEvents,
There are three functions for processing pending events. @ref glfwPollEvents,
processes only those events that have already been received and then returns
immediately.
@@ -46,7 +46,7 @@ immediately.
glfwPollEvents();
@endcode
This is the best choice when rendering continually, like most games do.
This is the best choice when rendering continuously, like most games do.
If you only need to update the contents of the window when you receive new
input, @ref glfwWaitEvents is a better choice.
@@ -60,8 +60,8 @@ processes all received events. This saves a great deal of CPU cycles and is
useful for, for example, editing tools. There must be at least one GLFW window
for this function to sleep.
If you want to wait for events but have UI elements that need periodic updates,
call @ref glfwWaitEventsTimeout.
If you want to wait for events but have UI elements or other tasks that need
periodic updates, @ref glfwWaitEventsTimeout lets you specify a timeout.
@code
glfwWaitEventsTimeout(0.7);
@@ -79,10 +79,17 @@ glfwPostEmptyEvent.
glfwPostEmptyEvent();
@endcode
Do not assume that callbacks will _only_ be called through either of the above
functions. While it is necessary to process events in the event queue, some
window systems will send some events directly to the application, which in turn
causes callbacks to be called outside of regular event processing.
Do not assume that callbacks will _only_ be called in response to the above
functions. While it is necessary to process events in one or more of the ways
above, window systems that require GLFW to register callbacks of its own can
pass events to GLFW in response to many window system function calls. GLFW will
pass those events on to the application callbacks before returning.
For example, on Windows the system function that @ref glfwSetWindowSize is
implemented with will send window size events directly to the event callback
that every window has and that GLFW implements for its windows. If you have set
a [window size callback](@ref window_size) GLFW will call it in turn with the
new size before everything returns back out of the @ref glfwSetWindowSize call.
@section input_keyboard Keyboard input
@@ -124,21 +131,31 @@ _E-mail_ and _Play_ keys.
The scancode is unique for every key, regardless of whether it has a key token.
Scancodes are platform-specific but consistent over time, so keys will have
different scancodes depending on the platform but they are safe to save to disk.
You can query the scancode for any [named key](@ref keys) on the current
platform with @ref glfwGetKeyScancode.
Key states for [named keys](@ref keys) are also saved in per-window state arrays
that can be polled with @ref glfwGetKey.
@code
const int scancode = glfwGetKeyScancode(GLFW_KEY_X);
set_key_mapping(scancode, swap_weapons);
@endcode
The last reported state for every [named key](@ref keys) is also saved in
per-window state arrays that can be polled with @ref glfwGetKey.
@code
int state = glfwGetKey(window, GLFW_KEY_E);
if (state == GLFW_PRESS)
{
activate_airship();
}
@endcode
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
This function only returns cached key event state. It does not poll the
system for the current state of the key.
system for the current physical state of the key.
@anchor GLFW_STICKY_KEYS
Whenever you poll state, you risk missing the state change you are looking for.
If a pressed key is released again before you poll its state, you will have
missed the key press. The recommended solution for this is to use a
@@ -164,12 +181,10 @@ GLFW supports text input in the form of a stream of
operating system text input system. Unlike key input, text input obeys keyboard
layouts and modifier keys and supports composing characters using
[dead keys](https://en.wikipedia.org/wiki/Dead_key). Once received, you can
encode the code points into
[UTF-8](https://en.wikipedia.org/wiki/UTF-8) or any other encoding you prefer.
encode the code points into UTF-8 or any other encoding you prefer.
Because an `unsigned int` is 32 bits long on all platforms supported by GLFW,
you can treat the code point argument as native endian
[UTF-32](https://en.wikipedia.org/wiki/UTF-32).
you can treat the code point argument as native endian UTF-32.
There are two callbacks for receiving Unicode code points. If you wish to
offer regular text input, set a character callback.
@@ -257,8 +272,9 @@ glfwGetCursorPos(window, &xpos, &ypos);
@endcode
@subsection cursor_mode Cursor modes
@subsection cursor_mode Cursor mode
@anchor GLFW_CURSOR
The `GLFW_CURSOR` input mode provides several cursor modes for special forms of
mouse motion input. By default, the cursor mode is `GLFW_CURSOR_NORMAL`,
meaning the regular arrow cursor (or another cursor set with @ref glfwSetCursor)
@@ -328,8 +344,8 @@ If cursor creation fails, `NULL` will be returned, so it is necessary to check
the return value.
The image data is 32-bit, little-endian, non-premultiplied RGBA, i.e. eight bits
per channel. The pixels are arranged canonically as sequential rows, starting
from the top-left corner.
per channel with the red channel first. The pixels are arranged canonically as
sequential rows, starting from the top-left corner.
@subsubsection cursor_standard Standard cursor creation
@@ -353,8 +369,10 @@ When a cursor is no longer needed, destroy it with @ref glfwDestroyCursor.
glfwDestroyCursor(cursor);
@endcode
Cursor destruction always succeeds. All cursors remaining when @ref
glfwTerminate is called are destroyed as well.
Cursor destruction always succeeds. If the cursor is current for any window,
that window will revert to the default cursor. This does not affect the cursor
mode. All remaining cursors remaining are destroyed when @ref glfwTerminate is
called.
@subsubsection cursor_set Cursor setting
@@ -371,14 +389,14 @@ to `GLFW_CURSOR_NORMAL`.
A single cursor may be set for any number of windows.
To remove a cursor from a window, set the cursor of that window to `NULL`.
To revert to the default cursor, set the cursor of that window to `NULL`.
@code
glfwSetCursor(window, NULL);
@endcode
When a cursor is destroyed, it is removed from any window where it is set. This
does not affect the cursor modes of those windows.
When a cursor is destroyed, any window that has it set will revert to the
default cursor. This does not affect the cursor mode.
@subsection cursor_enter Cursor enter/leave events
@@ -435,7 +453,9 @@ per-window state arrays that can be polled with @ref glfwGetMouseButton.
@code
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
if (state == GLFW_PRESS)
{
upgrade_cow();
}
@endcode
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
@@ -443,6 +463,7 @@ The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
This function only returns cached mouse button event state. It does not poll
the system for the current state of the mouse button.
@anchor GLFW_STICKY_MOUSE_BUTTONS
Whenever you poll state, you risk missing the state change you are looking for.
If a pressed mouse button is released again before you poll its state, you will have
missed the button press. The recommended solution for this is to use a
@@ -487,21 +508,27 @@ A simple mouse wheel, being vertical, provides offsets along the Y-axis.
The joystick functions expose connected joysticks and controllers, with both
referred to as joysticks. It supports up to sixteen joysticks, ranging from
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to `GLFW_JOYSTICK_LAST`. You can test
whether a [joystick](@ref joysticks) is present with @ref glfwJoystickPresent.
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to and including `GLFW_JOYSTICK_16` or
`GLFW_JOYSTICK_LAST`. You can test whether a [joystick](@ref joysticks) is
present with @ref glfwJoystickPresent.
@code
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
@endcode
When GLFW is initialized, detected joysticks are added to to the beginning of
the array, starting with `GLFW_JOYSTICK_1`. Once a joystick is detected, it
keeps its assigned index until it is disconnected, so as joysticks are connected
and disconnected, they will become spread out.
the array. Once a joystick is detected, it keeps its assigned ID until it is
disconnected or the library is terminated, so as joysticks are connected and
disconnected, there may appear gaps in the IDs.
Joystick state is updated as needed when a joystick function is called and does
not require a window to be created or @ref glfwPollEvents or @ref glfwWaitEvents
to be called.
Joystick axis, button and hat state is updated when polled and does not require
a window to be created or events to be processed. However, if you want joystick
connection and disconnection events reliably delivered to the
[joystick callback](@ref joystick_event) then you must
[process events](@ref events).
To see all the properties of all connected joysticks in real-time, run the
`joysticks` test program.
@subsection joystick_axis Joystick axis states
@@ -512,7 +539,7 @@ returned array.
@code
int count;
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &count);
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_5, &count);
@endcode
Each element in the returned array is a value between -1.0 and 1.0.
@@ -526,11 +553,55 @@ returned array.
@code
int count;
const unsigned char* axes = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &count);
const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_3, &count);
@endcode
Each element in the returned array is either `GLFW_PRESS` or `GLFW_RELEASE`.
For backward compatibility with earlier versions that did not have @ref
glfwGetJoystickHats, the button array by default also includes all hats. See
the reference documentation for @ref glfwGetJoystickButtons for details.
@subsection joystick_hat Joystick hat states
The states of all hats are returned by @ref glfwGetJoystickHats. See the
reference documentation for the lifetime of the returned array.
@code
int count;
const unsigned char* hats = glfwGetJoystickHats(GLFW_JOYSTICK_7, &count);
@endcode
Each element in the returned array is one of the following:
Name | Value
--------------------- | --------------------------------
`GLFW_HAT_CENTERED` | 0
`GLFW_HAT_UP` | 1
`GLFW_HAT_RIGHT` | 2
`GLFW_HAT_DOWN` | 4
`GLFW_HAT_LEFT` | 8
`GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP`
`GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN`
`GLFW_HAT_LEFT_UP` | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP`
`GLFW_HAT_LEFT_DOWN` | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN`
The diagonal directions are bitwise combinations of the primary (up, right, down
and left) directions and you can test for these individually by ANDing it with
the corresponding direction.
@code
if (hats[2] & GLFW_HAT_RIGHT)
{
// State of hat 2 could be right-up, right or right-down
}
@endcode
For backward compatibility with earlier versions that did not have @ref
glfwGetJoystickHats, all hats are by default also included in the button array.
See the reference documentation for @ref glfwGetJoystickButtons for details.
@subsection joystick_name Joystick name
@@ -539,7 +610,7 @@ glfwGetJoystickName. See the reference documentation for the lifetime of the
returned string.
@code
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_1);
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_4);
@endcode
Joystick names are not guaranteed to be unique. Two joysticks of the same model
@@ -560,7 +631,7 @@ The callback function receives the ID of the joystick that has been connected
and disconnected and the event that occurred.
@code
void joystick_callback(int joy, int event)
void joystick_callback(int jid, int event)
{
if (event == GLFW_CONNECTED)
{
@@ -573,6 +644,165 @@ void joystick_callback(int joy, int event)
}
@endcode
For joystick connection and disconnection events to be delivered on all
platforms, you need to call one of the [event processing](@ref events)
functions. Joystick disconnection may also be detected and the callback
called by joystick functions. The function will then return whatever it
returns for a disconnected joystick.
@subsection gamepad Gamepad input
The joystick functions provide unlabeled axes, buttons and hats, with no
indication of where they are located on the device. Their order may also vary
between platforms even with the same device.
To solve this problem the SDL community crowdsourced the
[SDL_GameControllerDB](https://github.com/gabomdq/SDL_GameControllerDB) project,
a database of mappings from many different devices to an Xbox-like gamepad.
GLFW supports this mapping format and contains a copy of the mappings
available at the time of release. See @ref gamepad_mapping for how to update
this at runtime. Mappings will be assigned to joysticks automatically any time
a joystick is connected or the mappings are updated.
You can check whether a joystick is both present and has a gamepad mapping with
@ref glfwJoystickIsGamepad.
@code
if (glfwJoystickIsGamepad(GLFW_JOYSTICK_2))
{
// Use as gamepad
}
@endcode
If you are only interested in gamepad input you can use this function instead of
@ref glfwJoystickPresent.
You can query the human-readable name provided by the gamepad mapping with @ref
glfwGetGamepadName. This may or may not be the same as the
[joystick name](@ref joystick_name).
@code
const char* name = glfwGetGamepadName(GLFW_JOYSTICK_7);
@endcode
To retrieve the gamepad state of a joystick, call @ref glfwGetGamepadState.
@code
GLFWgamepadstate state;
if (glfwGetGamepadState(GLFW_JOYSTICK_3, &state))
{
if (state.buttons[GLFW_GAMEPAD_BUTTON_A])
{
input_jump();
}
input_speed(state.axes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER]);
}
@endcode
The @ref GLFWgamepadstate struct has two arrays; one for button states and one
for axis states. The values for each button and axis are the same as for the
@ref glfwGetJoystickButtons and @ref glfwGetJoystickAxes functions, i.e.
`GLFW_PRESS` or `GLFW_RELEASE` for buttons and -1.0 to 1.0 inclusive for axes.
The sizes of the arrays and the positions within each array are fixed.
The [button indices](@ref gamepad_buttons) are `GLFW_GAMEPAD_BUTTON_A`,
`GLFW_GAMEPAD_BUTTON_B`, `GLFW_GAMEPAD_BUTTON_X`, `GLFW_GAMEPAD_BUTTON_Y`,
`GLFW_GAMEPAD_BUTTON_LEFT_BUMPER`, `GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER`,
`GLFW_GAMEPAD_BUTTON_BACK`, `GLFW_GAMEPAD_BUTTON_START`,
`GLFW_GAMEPAD_BUTTON_GUIDE`, `GLFW_GAMEPAD_BUTTON_LEFT_THUMB`,
`GLFW_GAMEPAD_BUTTON_RIGHT_THUMB`, `GLFW_GAMEPAD_BUTTON_DPAD_UP`,
`GLFW_GAMEPAD_BUTTON_DPAD_RIGHT`, `GLFW_GAMEPAD_BUTTON_DPAD_DOWN` and
`GLFW_GAMEPAD_BUTTON_DPAD_LEFT`.
For those who prefer, there are also the `GLFW_GAMEPAD_BUTTON_CROSS`,
`GLFW_GAMEPAD_BUTTON_CIRCLE`, `GLFW_GAMEPAD_BUTTON_SQUARE` and
`GLFW_GAMEPAD_BUTTON_TRIANGLE` aliases for the A, B, X and Y button indices.
The [axis indices](@ref gamepad_axes) are `GLFW_GAMEPAD_AXIS_LEFT_X`,
`GLFW_GAMEPAD_AXIS_LEFT_Y`, `GLFW_GAMEPAD_AXIS_RIGHT_X`,
`GLFW_GAMEPAD_AXIS_RIGHT_Y`, `GLFW_GAMEPAD_AXIS_LEFT_TRIGGER` and
`GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER`.
The `GLFW_GAMEPAD_BUTTON_LAST` and `GLFW_GAMEPAD_AXIS_LAST` constants equal
the largest available index for each array.
@subsection gamepad_mapping Gamepad mappings
GLFW contains a copy of the mappings available in
[SDL_GameControllerDB](https://github.com/gabomdq/SDL_GameControllerDB) at the
time of release. Newer ones can be added at runtime with @ref
glfwUpdateGamepadMappings.
@code
const char* mappings = load_file_contents("gamecontrollerdb.txt");
glfwUpdateGamepadMappings(mappings);
@endcode
This function supports everything from single lines up to and including the
unmodified contents of the whole `gamecontrollerdb.txt` file.
Below is a description of the mapping format. Please keep in mind that __this
description is not authoritative__. The format is defined by the SDL and
SDL_GameControllerDB projects and their documentation and code takes precedence.
Each mapping is a single line of comma-separated values describing the GUID,
name and layout of the gamepad. Lines that do not begin with a hexadecimal
digit are ignored.
The first value is always the gamepad GUID, a 32 character long hexadecimal
string that typically identifies its make, model, revision and the type of
connection to the computer. When this information is not available, the GUID is
generated using the gamepad name. GLFW uses the SDL 2.0.5+ GUID format but can
convert from the older formats.
The second value is always the human-readable name of the gamepad.
All subsequent values are in the form `<field>:<value>` and describe the layout
of the mapping. These fields may not all be present and may occur in any order.
The button fields are `a`, `b`, `c`, `d`, `back`, `start`, `guide`, `dpup`,
`dpright`, `dpdown`, `dpleft`, `leftshoulder`, `rightshoulder`, `leftstick` and
`rightstick`.
The axis fields are `leftx`, `lefty`, `rightx`, `righty`, `lefttrigger` and
`righttrigger`.
The value of an axis or button field can be a joystick button, a joystick axis,
a hat bitmask or empty. Joystick buttons are specified as `bN`, for example
`b2` for the third button. Joystick axes are specified as `aN`, for example
`a7` for the eighth button. Joystick hat bit masks are specified as `hN.N`, for
example `h0.8` for left on the first hat. More than one bit may be set in the
mask.
The hat bit mask match the [hat states](@ref hat_state) in the joystick
functions.
There is also the special `platform` field that specifies which platform the
mapping is valid for. Possible values are `Windows`, `Mac OS X` and `Linux`.
Mappings without this field will always be considered valid.
Below is an example of what a gamepad mapping might look like. It is the
one built into GLFW for Xbox controllers accessed via the XInput API on Windows.
This example has been broken into several lines to fit on the page, but real
gamepad mappings must be a single line.
@code{.unparsed}
78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,
b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,
rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,
righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
@endcode
@note GLFW does not yet support the range and inversion modifiers `+`, `-` and
`~` that were recently added to SDL.
@section time Time input
@@ -619,7 +849,9 @@ reference documentation for the lifetime of the returned string.
@code
const char* text = glfwGetClipboardString(window);
if (text)
{
insert_text(text);
}
@endcode
If the clipboard is empty or if its contents could not be converted, `NULL` is
+1 -1
View File
@@ -111,6 +111,6 @@ which is generated from the `glfw_config.h.in` file by CMake.
Configuration macros the same style as tokens in the public interface, except
with a leading underscore.
Examples: `_GLFW_HAS_XF86VM`
Examples: `_GLFW_USE_HYBRID_HPG`
*/
+137 -43
View File
@@ -4,10 +4,10 @@
@tableofcontents
This guide introduces the basic concepts of GLFW and describes initialization reference
This guide introduces the basic concepts of GLFW and describes initialization,
error handling and API guarantees and limitations. For a broad but shallow
tutorial, see @ref quick_guide instead. For details on a specific function, see the
[reference documentation](@ref init).
tutorial, see @ref quick_guide instead. For details on a specific function in
this category, see the @ref init.
There are also guides for the other areas of GLFW.
@@ -30,12 +30,15 @@ successfully initialized, and only from the main thread.
- @ref glfwGetVersion
- @ref glfwGetVersionString
- @ref glfwGetError
- @ref glfwSetErrorCallback
- @ref glfwInitHint
- @ref glfwInitHintString
- @ref glfwInit
- @ref glfwTerminate
Calling any other function before that time will cause a @ref
GLFW_NOT_INITIALIZED error.
Calling any other function before successful initialization will cause a @ref
GLFW_NOT_INITIALIZED error.
@subsection intro_init_init Initializing GLFW
@@ -50,13 +53,72 @@ if (!glfwInit())
}
@endcode
If any part of initialization fails, all remaining bits are terminated as if
@ref glfwTerminate was called. The library only needs to be initialized once
and additional calls to an already initialized library will simply return
If any part of initialization fails, any parts that succeeded are terminated as
if @ref glfwTerminate had been called. The library only needs to be initialized
once and additional calls to an already initialized library will simply return
`GLFW_TRUE` immediately.
Once the library has been successfully initialized, it should be terminated
before the application exits.
before the application exits. Modern systems are very good at freeing resources
allocated by programs that simply exit, but GLFW sometimes has to change global
system settings and these might not be restored without termination.
@subsection init_hints Initialization hints
Initialization hints are set before @ref glfwInit and affect how the library
behaves until termination. Integer type hints are set with @ref glfwInitHint
and string type hints with @ref glfwInitHintString.
@code
glfwInitHint(GLFW_JOYSTICK_HAT_BUTTONS, GLFW_FALSE);
@endcode
The values you set hints to are never reset by GLFW, but they only take effect
during initialization. Once GLFW has been initialized, any values you set will
be ignored until the library is terminated and initialized again.
Some hints are platform specific. These may be set on any platform but they
will only affect their specific platform. Other platforms will simply ignore
them. Setting these hints requires no platform specific headers or functions.
@anchor GLFW_JOYSTICK_HAT_BUTTONS
__GLFW_JOYSTICK_HAT_BUTTONS__ specifies whether to also expose joystick hats as
buttons, for compatibility with earlier versions of GLFW that did not have @ref
glfwGetJoystickHats. Set this with @ref glfwInitHint.
@subsubsection init_hints_osx macOS specific init hints
@anchor GLFW_COCOA_CHDIR_RESOURCES
__GLFW_COCOA_CHDIR_RESOURCES__ specifies whether to set the current directory to
the application to the `Contents/Resources` subdirectory of the application's
bundle, if present. Set this with @ref glfwInitHint.
@anchor GLFW_COCOA_MENUBAR
__GLFW_COCOA_MENUBAR__ specifies whether to create a basic menu bar, either from
a nib or manually, when the first window is created, which is when AppKit is
initialized. Set this with @ref glfwInitHint.
@subsubsection init_hints_x11 X11 specific init hints
@anchor GLFW_X11_WM_CLASS_NAME
@anchor GLFW_X11_WM_CLASS_CLASS
__GLFW_X11_WM_CLASS_NAME__ and __GLFW_X11_WM_CLASS_CLASS__ specifies the desired
ASCII encoded name and class parts of the ICCCM `WM_CLASS` hint for all windows.
Set this with @ref glfwInitHintString.
@subsubsection init_hints_values Supported and default values
Init hint | Default value | Supported values
------------------------------- | ------------- | ----------------
@ref GLFW_JOYSTICK_HAT_BUTTONS | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_X11_WM_CLASS_NAME | `""` | An ASCII encoded `WM_CLASS` name
@ref GLFW_X11_WM_CLASS_CLASS | `""` | An ASCII encoded `WM_CLASS` class
@subsection intro_init_terminate Terminating GLFW
@@ -70,7 +132,7 @@ glfwTerminate();
This will destroy any remaining window, monitor and cursor objects, restore any
modified gamma ramps, re-enable the screensaver if it had been disabled and free
any resources allocated by GLFW.
any other resources allocated by GLFW.
Once the library is terminated, it is as if it had never been initialized and
you will need to initialize it again before being able to use GLFW. If the
@@ -81,41 +143,76 @@ immediately.
@section error_handling Error handling
Some GLFW functions have return values that indicate an error, but this is often
not very helpful when trying to figure out _why_ the error occurred. Some
functions also return otherwise valid values on error. Finally, far from all
GLFW functions have return values.
not very helpful when trying to figure out what happened or why it occurred.
Other functions have no return value reserved for errors, so error notification
needs a separate channel. Finally, far from all GLFW functions have return
values.
This is where the error callback comes in. This callback is called whenever an
error occurs. It is set with @ref glfwSetErrorCallback, a function that may be
called regardless of whether GLFW is initialized.
The last [error code](@ref errors) for the calling thread can be queried at any
time with @ref glfwGetError.
@code
glfwSetErrorCallback(error_callback);
int code = glfwGetError(NULL);
if (code != GLFW_NO_ERROR)
handle_error(code);
@endcode
The error callback receives a human-readable description of the error and (when
possible) its cause. The description encoded as UTF-8. The callback is also
provided with an [error code](@ref errors).
@code
void error_callback(int error, const char* description)
{
puts(description);
}
@endcode
If no error has occurred since the last call, @ref GLFW_NO_ERROR (zero) is
returned. The error is cleared before the function returns.
The error code indicates the general category of the error. Some error codes,
such as @ref GLFW_NOT_INITIALIZED has only a single meaning, whereas others like
@ref GLFW_PLATFORM_ERROR are used for many different errors.
The description string is only valid until the error callback returns, as it may
have been generated specifically for that error. This lets GLFW provide much
more specific error descriptions but means you must make a copy if you want to
keep the description string.
GLFW often has more information about an error than its general category. You
can retrieve a UTF-8 encoded human-readable description along with the error
code. If no error has occurred since the last call, the description is set to
`NULL`.
@note Relying on erroneous behavior is not forward compatible. In other words,
do not rely on a currently invalid call to generate a specific error, as that
same call may in future versions generate a different error or become valid.
@code
const char* description;
int code = glfwGetError(&description);
if (description)
display_error_message(code, description);
@endcode
The retrieved description string is only valid until the next error occurs.
This means you must make a copy of it if you want to keep it.
You can also set an error callback, which will be called each time an error
occurs. It is set with @ref glfwSetErrorCallback.
@code
glfwSetErrorCallback(error_callback);
@endcode
The error callback receives the same error code and human-readable description
returned by @ref glfwGetError.
@code
void error_callback(int code, const char* description)
{
display_error_message(code, description);
}
@endcode
The error callback is called after the error is stored, so calling @ref
glfwGetError from within the error callback returns the same values as the
callback argument.
The description string passed to the callback is only valid until the error
callback returns. This means you must make a copy of it if you want to keep it.
__Reported errors are never fatal.__ As long as GLFW was successfully
initialized, it will remain initialized and in a safe state until terminated
regardless of how many errors occur. If an error occurs during initialization
that causes @ref glfwInit to fail, any part of the library that was initialized
will be safely terminated.
Do not rely on a currently invalid call to generate a specific error, as in the
future that same call may generate a different error or become valid.
@section coordinate_systems Coordinate systems
@@ -186,14 +283,10 @@ releases.
@subsection reentrancy Reentrancy
GLFW event processing and object creation and destruction are not reentrant.
This means that the following functions must not be called from any callback
function:
GLFW event processing and object destruction are not reentrant. This means that
the following functions must not be called from any callback function:
- @ref glfwCreateWindow
- @ref glfwDestroyWindow
- @ref glfwCreateCursor
- @ref glfwCreateStandardCursor
- @ref glfwDestroyCursor
- @ref glfwPollEvents
- @ref glfwWaitEvents
@@ -282,9 +375,10 @@ allow calls from any thread in future releases.
@subsection compatibility Version compatibility
GLFW guarantees binary backward compatibility with earlier minor versions of the
API. This means that you can drop in a newer version of the GLFW DLL / shared
library / dynamic library and existing applications will continue to run.
GLFW guarantees source and binary backward compatibility with earlier minor
versions of the API. This means that you can drop in a newer version of the
library and existing programs will continue to compile and existing binaries
will continue to run.
Once a function or constant has been added, the signature of that function or
value of that constant will remain unchanged until the next major version of
+1 -1
View File
@@ -8,7 +8,7 @@ GLFW is a free, Open Source, multi-platform library for OpenGL, OpenGL ES and
Vulkan application development. It provides a simple, platform-independent API
for creating windows, contexts and surfaces, reading input, handling events, etc.
See @ref news_32 for release highlights or the
See @ref news_33 for highlights or the
[version history](http://www.glfw.org/changelog.html) for details.
@ref quick_guide is a guide for users new to GLFW. It takes you through how to
+13 -4
View File
@@ -5,12 +5,13 @@
@tableofcontents
This guide introduces the monitor related functions of GLFW. For details on
a specific function, see the [reference documentation](@ref monitor). There are
also guides for the other areas of GLFW.
a specific function in this category, see the @ref monitor. There are also
guides for the other areas of GLFW.
- @ref intro_guide
- @ref window_guide
- @ref context_guide
- @ref vulkan_guide
- @ref input_guide
@@ -194,8 +195,8 @@ glfwSetGammaRamp(monitor, &ramp);
The gamma ramp data is copied before the function returns, so there is no need
to keep it around once the ramp has been set.
@note It is recommended to use gamma ramps of size 256, as that is the size
supported by all graphics cards on all platforms.
It is recommended that your gamma ramp have the same size as the current gamma
ramp for that monitor.
The current gamma ramp for a monitor is returned by @ref glfwGetGammaRamp. See
the reference documentation for the lifetime of the returned structure.
@@ -212,4 +213,12 @@ glfwSetGammaRamp with the resulting ramp.
glfwSetGamma(monitor, 1.0);
@endcode
To experiment with gamma correction via the @ref glfwSetGamma function, run the
`gamma` test program.
@note The software controlled gamma ramp is applied _in addition_ to the
hardware gamma correction, which today is usually an approximation of sRGB
gamma. This means that setting a perfectly linear ramp, or gamma 1.0, will
produce the default (usually sRGB-like) behavior.
*/
+8 -1
View File
@@ -434,7 +434,7 @@ GLFW 3 does not by default include the GLU header and GLU itself has been
deprecated by [Khronos](https://en.wikipedia.org/wiki/Khronos_Group). __New
projects should not use GLU__, but if you need it for legacy code that
has been moved to GLFW 3, you can request that the GLFW header includes it by
defining `GLFW_INCLUDE_GLU` before the inclusion of the GLFW header.
defining @ref GLFW_INCLUDE_GLU before the inclusion of the GLFW header.
@par Old syntax
@code
@@ -447,6 +447,13 @@ defining `GLFW_INCLUDE_GLU` before the inclusion of the GLFW header.
#include <GLFW/glfw3.h>
@endcode
There are many libraries that offer replacements for the functionality offered
by GLU. For the matrix helper functions, see math libraries like
[GLM](https://github.com/g-truc/glm) (for C++),
[linmath.h](https://github.com/datenwolf/linmath.h) (for C) and others. For the
tessellation functions, see for example
[libtess2](https://github.com/memononen/libtess2).
@section moving_tables Name change tables
+161 -43
View File
@@ -1,8 +1,124 @@
/*!
@page news New features
@page news Release notes
@section news_32 New features in 3.2
@section news_33 Release notes for 3.3
@subsection news_33_geterror Error query
GLFW now supports querying the last error code for the calling thread and its
human-readable description with @ref glfwGetError.
@see @ref error_handling
@subsection news_33_gamepad SDL_GameControllerDB support and gamepad input
GLFW now supports remapping of gamepads and controllers to a 360-like controller
layout with @ref glfwJoystickIsGamepad, @ref glfwGetJoystickGUID, @ref
glfwGetGamepadName, @ref glfwGetGamepadState and @ref glfwUpdateGamepadMappings,
and the input state struct @ref GLFWgamepadstate.
@sa @ref gamepad
@subsection news_33_attention User attention request
GLFW now supports requesting user attention to a specific window (on macOS to
the application as a whole) with @ref glfwRequestWindowAttention.
@see @ref window_attention
@subsection news_33_maximize Window maximization callback
GLFW now supports notifying the application that the window has been maximized
@ref glfwSetWindowMaximizeCallback.
@see @ref window_maximize
@subsection news_33_keyscancode Platform-specific key scancode query
GLFW now supports querying the platform dependent scancode of any physical key
with @ref glfwGetKeyScancode.
@see @ref input_key
@subsection news_33_setwindowattrib Support for updating window attributes
GLFW now supports changing the [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
[GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
[GLFW_FLOATING](@ref GLFW_FLOATING_attrib) and
[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) attributes for existing
windows with @ref glfwSetWindowAttrib.
@see @ref window_attribs
@subsection news_33_inithint Support for initialization hints
GLFW now supports setting library initialization hints with @ref glfwInitHint
or @ref glfwInitHintString. These must be set before initialization to take
effect.
@see @ref init_hints
@subsection news_33_platformhints Support for platform specific hints
GLFW now supports platform specific init and window hints to control system
features that are only available on a single platform.
@see @ref init_hints_osx
@see @ref window_hints_osx
@subsection news_33_joyhats Support for joystick hats
GLFW now supports querying the hats (or POVs or D-pads) of a joystick with @ref
glfwGetJoystickHats. Hats are by default also exposed as buttons, but this can
be disabled with the @ref GLFW_JOYSTICK_HAT_BUTTONS init hint.
@see @ref joystick_hat
@subsection news_33_centercursor Cursor centering window hint
GLFW now supports controlling whether the cursor is centered over newly created
full screen windows with the [GLFW_CENTER_CURSOR](@ref GLFW_CENTER_CURSOR_hint)
window hint. It is enabled by default.
@subsection news_33_rawmotion Support for raw mouse motion
GLFW now uses raw (unscaled and unaccelerated) mouse motion in disabled cursor
mode on platforms where this is available, specifically Windows and X11.
@subsection news_33_moltenvk Support for Vulkan on macOS via MoltenVK
GLFW now supports the `VK_MVK_macos_surface` window surface creation extension
provided by [MoltenVK](https://moltengl.com/moltenvk/).
@see @ref vulkan_guide
@subsection news_33_osmesa OSMesa backend for headless software rendering
GLFW now supports creating offscreen OpenGL contexts using
[OSMesa](https://www.mesa3d.org/osmesa.html) by setting
[GLFW_CONTEXT_CREATION_API](@ref GLFW_CONTEXT_CREATION_API_hint) to
`GLFW_OSMESA_CONTEXT_API`.
There is also a new null backend that uses OSMesa as its native context
creation API, intended for automated testing. This backend does not provide
input.
@section news_32 Release notes for 3.2
@subsection news_32_vulkan Support for Vulkan
@@ -11,7 +127,7 @@ GLFW now supports basic integration with Vulkan with @ref glfwVulkanSupported,
@ref glfwGetRequiredInstanceExtensions, @ref glfwGetInstanceProcAddress, @ref
glfwGetPhysicalDevicePresentationSupport and @ref glfwCreateWindowSurface.
Vulkan header inclusion can be selected with
[GLFW_INCLUDE_VULKAN](@ref build_macros).
@ref GLFW_INCLUDE_VULKAN.
@subsection news_32_setwindowmonitor Window mode switching
@@ -24,7 +140,7 @@ the monitor and desired resolution and refresh rate of full screen windows with
@subsection news_32_maximize Window maxmimization support
GLFW now supports window maximization with @ref glfwMaximizeWindow and the
[GLFW_MAXIMIZED](@ref window_attribs_wnd) window hint and attribute.
@ref GLFW_MAXIMIZED window hint and attribute.
@subsection news_32_focus Window input focus control
@@ -69,21 +185,21 @@ with @ref glfwSetJoystickCallback.
@subsection news_32_noapi Context-less windows
GLFW now supports creating windows without a OpenGL or OpenGL ES context with
[GLFW_NO_API](@ref window_hints_ctx).
GLFW now supports creating windows without a OpenGL or OpenGL ES context by
setting the [GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_NO_API`.
@subsection news_32_contextapi Run-time context creation API selection
GLFW now supports selecting the context creation API at run-time with the
[GLFW_CONTEXT_CREATION_API](@ref window_hints_ctx) window hint value.
GLFW now supports selecting and querying the context creation API at run-time
with the @ref GLFW_CONTEXT_CREATION_API hint and attribute.
@subsection news_32_noerror Error-free context creation
GLFW now supports creating OpenGL and OpenGL ES contexts that do not emit errors
with the [GLFW_CONTEXT_NO_ERROR](@ref window_hints_ctx) window hint, provided
the machine supports the `GL_KHR_no_error` extension.
GLFW now supports creating and querying OpenGL and OpenGL ES contexts that do
not emit errors with the @ref GLFW_CONTEXT_NO_ERROR hint, provided the machine
supports the `GL_KHR_no_error` extension.
@subsection news_32_cmake CMake config-file package support
@@ -93,7 +209,7 @@ GLFW now supports being used as a
easy linking with the library and its dependencies.
@section news_31 New features in 3.1
@section news_31 Release notes for 3.1
These are the release highlights. For a full list of changes see the
[version history](http://www.glfw.org/changelog.html).
@@ -137,21 +253,21 @@ client area of a window, with @ref glfwGetWindowFrameSize.
@subsection news_31_autoiconify Simultaneous multi-monitor rendering
GLFW now supports disabling auto-iconification of full screen windows with
the [GLFW_AUTO_ICONIFY](@ref window_hints_wnd) window hint. This is intended
for people building multi-monitor installations, where you need windows to stay
in full screen despite losing input focus.
the [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_hint) window hint. This is
intended for people building multi-monitor installations, where you need windows
to stay in full screen despite losing input focus.
@subsection news_31_floating Floating windows
GLFW now supports floating windows, also called topmost or always on top, for
easier debugging with the [GLFW_FLOATING](@ref window_hints_wnd) window hint.
easier debugging with the @ref GLFW_FLOATING window hint and attribute.
@subsection news_31_focused Initially unfocused windows
GLFW now supports preventing a windowed mode window from gaining input focus on
creation, with the [GLFW_FOCUSED](@ref window_hints_wnd) window hint.
creation, with the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) window hint.
@subsection news_31_direct Direct access for window attributes and cursor position
@@ -172,24 +288,24 @@ being input, for example if the Control key is held down.
@subsection news_31_single Single buffered framebuffers
GLFW now supports the creation of single buffered windows, with the
[GLFW_DOUBLEBUFFER](@ref window_hints_fb) window hint.
GLFW now supports the creation of single buffered windows, with the @ref
GLFW_DOUBLEBUFFER hint.
@subsection news_31_glext Macro for including extension header
GLFW now includes the extension header appropriate for the chosen OpenGL or
OpenGL ES header when [GLFW_INCLUDE_GLEXT](@ref build_macros) is defined. GLFW
does not provide these headers. They must be provided by your development
environment or your OpenGL or OpenGL ES SDK.
OpenGL ES header when @ref GLFW_INCLUDE_GLEXT is defined. GLFW does not provide
these headers. They must be provided by your development environment or your
OpenGL or OpenGL ES SDK.
@subsection news_31_release Context release behaviors
GLFW now supports controlling whether the pipeline is flushed when a context is
made non-current, with the
[GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint, provided the
machine supports the `GL_KHR_context_flush_control` extension.
GLFW now supports controlling and querying whether the pipeline is flushed when
a context is made non-current, with the @ref GLFW_CONTEXT_RELEASE_BEHAVIOR hint
and attribute, provided the machine supports the `GL_KHR_context_flush_control`
extension.
@subsection news_31_wayland (Experimental) Wayland support
@@ -204,7 +320,7 @@ GLFW now has an _experimental_ Mir display server backend that can be selected
on Linux with a CMake option.
@section news_30 New features in 3.0
@section news_30 Release notes for 3.0
These are the release highlights. For a full list of changes see the
[version history](http://www.glfw.org/changelog.html).
@@ -264,11 +380,11 @@ glfwSetGamma, which generates a ramp from a gamma value and then sets it.
@subsection news_30_gles OpenGL ES support
GLFW now supports the creation of OpenGL ES contexts, by setting the
`GLFW_CLIENT_API` window hint to `GLFW_OPENGL_ES_API`, where creation of such
contexts are supported. Note that GLFW _does not implement_ OpenGL ES, so your
driver must provide support in a way usable by GLFW. Modern Nvidia and Intel
drivers support creation of OpenGL ES context using the GLX and WGL APIs, while
AMD provides an EGL implementation instead.
[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_OPENGL_ES_API`, where
creation of such contexts are supported. Note that GLFW _does not implement_
OpenGL ES, so your driver must provide support in a way usable by GLFW. Modern
Nvidia and Intel drivers support creation of OpenGL ES context using the GLX and
WGL APIs, while AMD provides an EGL implementation instead.
@subsection news_30_egl (Experimental) EGL support
@@ -279,11 +395,12 @@ through CMake options.
@subsection news_30_hidpi High-DPI support
GLFW now supports high-DPI monitors on both Windows and OS X, giving windows full
resolution framebuffers where other UI elements are scaled up. To achieve this,
@ref glfwGetFramebufferSize and @ref glfwSetFramebufferSizeCallback have been
added. These work with pixels, while the rest of the GLFW API works with screen
coordinates. This is important as OpenGL uses pixels, not screen coordinates.
GLFW now supports high-DPI monitors on both Windows and macOS, giving windows
full resolution framebuffers where other UI elements are scaled up. To achieve
this, @ref glfwGetFramebufferSize and @ref glfwSetFramebufferSizeCallback have
been added. These work with pixels, while the rest of the GLFW API works with
screen coordinates. This is important as OpenGL uses pixels, not screen
coordinates.
@subsection news_30_error Error callback
@@ -338,16 +455,17 @@ to @ref glfwCreateWindow.
@subsection news_30_hidden Hidden windows
Windows can now be hidden with @ref glfwHideWindow, shown using @ref
glfwShowWindow and created initially hidden with the `GLFW_VISIBLE` window hint.
This allows for off-screen rendering in a way compatible with most drivers, as
well as moving a window to a specific position before showing it.
glfwShowWindow and created initially hidden with the @ref GLFW_VISIBLE window
hint and attribute. This allows for off-screen rendering in a way compatible
with most drivers, as well as moving a window to a specific position before
showing it.
@subsection news_30_undecorated Undecorated windows
Windowed mode windows can now be created without decorations, i.e. things like
a frame, a title bar, with the `GLFW_DECORATED` window hint. This allows for
the creation of things like splash screens.
Windowed mode windows can now be created without decorations, e.g. things like
a frame, a title bar, with the @ref GLFW_DECORATED window hint and attribute.
This allows for the creation of things like splash screens.
@subsection news_30_keymods Modifier key bit masks
+1 -1
View File
@@ -340,7 +340,7 @@ The program above can be found in the
[source package](http://www.glfw.org/download.html) as `examples/simple.c`
and is compiled along with all other examples when you build GLFW. If you
built GLFW from the source package then already have this as `simple.exe` on
Windows, `simple` on Linux or `simple.app` on OS X.
Windows, `simple` on Linux or `simple.app` on macOS.
This tutorial used only a few of the many functions GLFW provides. There are
guides for each of the areas covered by GLFW. Each guide will introduce all the
+39 -15
View File
@@ -11,16 +11,22 @@ with Vulkan concepts like loaders, devices, queues and surfaces and leaves it to
the Vulkan documentation to explain the details of Vulkan functions.
To develop for Vulkan you should install an SDK for your platform, for example
the [LunarG Vulkan SDK](https://vulkan.lunarg.com/). Apart from the headers and
libraries, it also provides the validation layers necessary for development.
the [LunarG Vulkan SDK](https://vulkan.lunarg.com/) for Windows and Linux or
[MoltenVK](https://moltengl.com/moltenvk/) for macOS. Apart from headers and
link libraries, they should also provide the validation layers necessary for
development.
The GLFW library does not need the Vulkan SDK to enable support for Vulkan.
However, any Vulkan-specific test and example programs are built only if the
CMake files find a Vulkan SDK.
For details on a specific function, see the
[reference documentation](@ref vulkan). There are also guides for the other
areas of the GLFW API.
@macos Because MoltenVK is typically not installed system-wide, you will need to
point CMake to it using the `CMAKE_FRAMEWORK_PATH` variable when configuring the
GLFW source tree. Set this variable to the `MoltenVK/macOS` subdirectory of the
SDK, either on the command-line or in the CMake GUI.
For details on a specific function in this category, see the @ref vulkan. There
are also guides for the other areas of the GLFW API.
- @ref intro_guide
- @ref window_guide
@@ -29,18 +35,36 @@ areas of the GLFW API.
- @ref input_guide
@section vulkan_loader Linking against the Vulkan loader
By default, GLFW will look for the Vulkan loader on demand at runtime via its
standard name (`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other
Unix-like systems and `libMoltenVK.dylib` on macOS). This means that GLFW does
not need to be linked against the loader. However, it also means that if you
are using the static library form of the Vulkan loader GLFW will either fail to
find it or (worse) use the wrong one.
The @ref GLFW_VULKAN_STATIC CMake option makes GLFW link directly against the
static library form. Not linking against the Vulkan loader will then be
a compile-time error.
@macos When using the static library form of MoltenVK (i.e. `MetalVK.framework`
and not `libMoltenVK.dylib`) you must also link against its dependencies: the
`Cocoa`, `Metal` and `QuartzCore` system frameworks and the `libc++` library.
@section vulkan_include Including the Vulkan and GLFW header files
To include the Vulkan header, define [GLFW_INCLUDE_VULKAN](@ref build_macros)
before including the GLFW header.
To include the Vulkan header, define @ref GLFW_INCLUDE_VULKAN before including
the GLFW header.
@code
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
@endcode
If you want to include the Vulkan header from a custom location or use your own
custom Vulkan header then you need to include them before the GLFW header.
If you instead want to include the Vulkan header from a custom location or use
your own custom Vulkan header then do this before the GLFW header.
@code
#include <path/to/vulkan.h>
@@ -61,7 +85,7 @@ section. The canonical desktop loader library exports all Vulkan core and
Khronos extension functions, allowing them to be called directly.
If you are loading the Vulkan loader dynamically instead of linking directly
against it, you can check for the availability of a loader with @ref
against it, you can check for the availability of a loader and ICD with @ref
glfwVulkanSupported.
@code
@@ -71,11 +95,11 @@ if (glfwVulkanSupported())
}
@endcode
This function returns `GLFW_TRUE` if the Vulkan loader was found. This check is
performed by @ref glfwInit.
This function returns `GLFW_TRUE` if the Vulkan loader and any minimally
functional ICD was found.
If no loader was found, calling any other Vulkan related GLFW function will
generate a @ref GLFW_API_UNAVAILABLE error.
If if one or both were not found, calling any other Vulkan related GLFW function
will generate a @ref GLFW_API_UNAVAILABLE error.
@subsection vulkan_proc Querying Vulkan function pointers
@@ -182,7 +206,7 @@ an existing Vulkan surface.
Unless you will be using OpenGL or OpenGL ES with the same window as Vulkan,
there is no need to create a context. You can disable context creation with the
[GLFW_CLIENT_API](@ref window_hints_ctx) hint.
[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint.
@code
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+421 -180
View File
@@ -5,11 +5,12 @@
@tableofcontents
This guide introduces the window related functions of GLFW. For details on
a specific function, see the [reference documentation](@ref window). There are
also guides for the other areas of GLFW.
a specific function in this category, see the @ref window. There are also
guides for the other areas of GLFW.
- @ref intro_guide
- @ref context_guide
- @ref vulkan_guide
- @ref monitor_guide
- @ref input_guide
@@ -70,22 +71,26 @@ Video mode field | Corresponds to
----------------------- | ------------------------
GLFWvidmode.width | `width` parameter
GLFWvidmode.height | `height` parameter
GLFWvidmode.redBits | `GLFW_RED_BITS` hint
GLFWvidmode.greenBits | `GLFW_GREEN_BITS` hint
GLFWvidmode.blueBits | `GLFW_BLUE_BITS` hint
GLFWvidmode.refreshRate | `GLFW_REFRESH_RATE` hint
GLFWvidmode.redBits | @ref GLFW_RED_BITS hint
GLFWvidmode.greenBits | @ref GLFW_GREEN_BITS hint
GLFWvidmode.blueBits | @ref GLFW_BLUE_BITS hint
GLFWvidmode.refreshRate | @ref GLFW_REFRESH_RATE hint
Once you have a full screen window, you can change its resolution, refresh rate
and monitor with @ref glfwSetWindowMonitor. If you just need change its
resolution you can also call @ref glfwSetWindowSize. In all cases, the new
video mode will be selected the same way as the video mode chosen by @ref
glfwCreateWindow.
glfwCreateWindow. If the window has an OpenGL or OpenGL ES context, it will be
unaffected.
By default, the original video mode of the monitor will be restored and the
window iconified if it loses input focus, to allow the user to switch back to
the desktop. This behavior can be disabled with the `GLFW_AUTO_ICONIFY` window
hint, for example if you wish to simultaneously cover multiple windows with full
screen windows.
the desktop. This behavior can be disabled with the
[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_hint) window hint, for example if you
wish to simultaneously cover multiple windows with full screen windows.
If a monitor is disconnected, any window that is full screen on that monitor
will be forced into windowed mode. See @ref monitor_event for more information.
@subsubsection window_windowed_full_screen "Windowed full screen" windows
@@ -144,6 +149,11 @@ context. These hints are set to their default values each time the library is
initialized with @ref glfwInit, can be set individually with @ref glfwWindowHint
and reset all at once to their defaults with @ref glfwDefaultWindowHints.
Some hints are platform specific. These are always valid to set on any
platform but they will only affect their specific platform. Other platforms
will simply ignore them. Setting these hints requires no platform specific
headers or calls.
Note that hints need to be set _before_ the creation of the window and context
you wish to have the specified attributes.
@@ -156,128 +166,187 @@ that are not hard constraints are matched as closely as possible, but the
resulting context and framebuffer may differ from what these hints requested.
The following hints are always hard constraints:
- `GLFW_STEREO`
- `GLFW_DOUBLEBUFFER`
- `GLFW_CLIENT_API`
- `GLFW_CONTEXT_CREATION_API`
- @ref GLFW_STEREO
- @ref GLFW_DOUBLEBUFFER
- [GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint)
- [GLFW_CONTEXT_CREATION_API](@ref GLFW_CONTEXT_CREATION_API_hint)
The following additional hints are hard constraints when requesting an OpenGL
context, but are ignored when requesting an OpenGL ES context:
- `GLFW_OPENGL_FORWARD_COMPAT`
- `GLFW_OPENGL_PROFILE`
- [GLFW_OPENGL_FORWARD_COMPAT](@ref GLFW_OPENGL_FORWARD_COMPAT_hint)
- [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint)
@subsubsection window_hints_wnd Window related hints
`GLFW_RESIZABLE` specifies whether the windowed mode window will be resizable
@anchor GLFW_RESIZABLE_hint
__GLFW_RESIZABLE__ specifies whether the windowed mode window will be resizable
_by the user_. The window will still be resizable using the @ref
glfwSetWindowSize function. This hint is ignored for full screen windows.
glfwSetWindowSize function. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
This hint is ignored for full screen and undecorated windows.
`GLFW_VISIBLE` specifies whether the windowed mode window will be initially
visible. This hint is ignored for full screen windows.
`GLFW_DECORATED` specifies whether the windowed mode window will have window
decorations such as a border, a close widget, etc. An undecorated window may
still allow the user to generate close events on some platforms. This hint is
@anchor GLFW_VISIBLE_hint
__GLFW_VISIBLE__ specifies whether the windowed mode window will be initially
visible. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This hint is
ignored for full screen windows.
`GLFW_FOCUSED` specifies whether the windowed mode window will be given input
focus when created. This hint is ignored for full screen and initially hidden
windows.
@anchor GLFW_DECORATED_hint
__GLFW_DECORATED__ specifies whether the windowed mode window will have window
decorations such as a border, a close widget, etc. An undecorated window will
not be resizable by the user but will still allow the user to generate close
events on some platforms. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
This hint is ignored for full screen windows.
`GLFW_AUTO_ICONIFY` specifies whether the full screen window will
@anchor GLFW_FOCUSED_hint
__GLFW_FOCUSED__ specifies whether the windowed mode window will be given input
focus when created. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This
hint is ignored for full screen and initially hidden windows.
@anchor GLFW_AUTO_ICONIFY_hint
__GLFW_AUTO_ICONIFY__ specifies whether the full screen window will
automatically iconify and restore the previous video mode on input focus loss.
This hint is ignored for windowed mode windows.
Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This hint is ignored for
windowed mode windows.
`GLFW_FLOATING` specifies whether the windowed mode window will be floating
@anchor GLFW_FLOATING_hint
__GLFW_FLOATING__ specifies whether the windowed mode window will be floating
above other regular windows, also called topmost or always-on-top. This is
intended primarily for debugging purposes and cannot be used to implement proper
full screen windows. This hint is ignored for full screen windows.
full screen windows. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This
hint is ignored for full screen windows.
`GLFW_MAXIMIZED` specifies whether the windowed mode window will be maximized
when created. This hint is ignored for full screen windows.
@anchor GLFW_MAXIMIZED_hint
__GLFW_MAXIMIZED__ specifies whether the windowed mode window will be maximized
when created. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This hint is
ignored for full screen windows.
@anchor GLFW_CENTER_CURSOR_hint
__GLFW_CENTER_CURSOR__ specifies whether the cursor should be centered over
newly created full screen windows. Possible values are `GLFW_TRUE` and
`GLFW_FALSE`. This hint is ignored for windowed mode windows.
@subsubsection window_hints_fb Framebuffer related hints
`GLFW_RED_BITS`, `GLFW_GREEN_BITS`, `GLFW_BLUE_BITS`, `GLFW_ALPHA_BITS`,
`GLFW_DEPTH_BITS` and `GLFW_STENCIL_BITS` specify the desired bit depths of the
various components of the default framebuffer. `GLFW_DONT_CARE` means the
application has no preference.
@anchor GLFW_RED_BITS
@anchor GLFW_GREEN_BITS
@anchor GLFW_BLUE_BITS
@anchor GLFW_ALPHA_BITS
@anchor GLFW_DEPTH_BITS
@anchor GLFW_STENCIL_BITS
__GLFW_RED_BITS__, __GLFW_GREEN_BITS__, __GLFW_BLUE_BITS__, __GLFW_ALPHA_BITS__,
__GLFW_DEPTH_BITS__ and __GLFW_STENCIL_BITS__ specify the desired bit depths of
the various components of the default framebuffer. A value of `GLFW_DONT_CARE`
means the application has no preference.
`GLFW_ACCUM_RED_BITS`, `GLFW_ACCUM_GREEN_BITS`, `GLFW_ACCUM_BLUE_BITS` and
`GLFW_ACCUM_ALPHA_BITS` specify the desired bit depths of the various components
of the accumulation buffer. `GLFW_DONT_CARE` means the application has no
preference.
@anchor GLFW_ACCUM_RED_BITS
@anchor GLFW_ACCUM_GREEN_BITS
@anchor GLFW_ACCUM_BLUE_BITS
@anchor GLFW_ACCUM_ALPHA_BITS
__GLFW_ACCUM_RED_BITS__, __GLFW_ACCUM_GREEN_BITS__, __GLFW_ACCUM_BLUE_BITS__ and
__GLFW_ACCUM_ALPHA_BITS__ specify the desired bit depths of the various
components of the accumulation buffer. A value of `GLFW_DONT_CARE` means the
application has no preference.
@par
Accumulation buffers are a legacy OpenGL feature and should not be used in new
code.
`GLFW_AUX_BUFFERS` specifies the desired number of auxiliary buffers.
`GLFW_DONT_CARE` means the application has no preference.
@anchor GLFW_AUX_BUFFERS
__GLFW_AUX_BUFFERS__ specifies the desired number of auxiliary buffers. A value
of `GLFW_DONT_CARE` means the application has no preference.
@par
Auxiliary buffers are a legacy OpenGL feature and should not be used in new
code.
`GLFW_STEREO` specifies whether to use stereoscopic rendering. This is a hard
constraint.
@anchor GLFW_STEREO
__GLFW_STEREO__ specifies whether to use OpenGL stereoscopic rendering.
Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This is a hard constraint.
`GLFW_SAMPLES` specifies the desired number of samples to use for multisampling.
Zero disables multisampling. `GLFW_DONT_CARE` means the application has no
preference.
@anchor GLFW_SAMPLES
__GLFW_SAMPLES__ specifies the desired number of samples to use for
multisampling. Zero disables multisampling. A value of `GLFW_DONT_CARE` means
the application has no preference.
`GLFW_SRGB_CAPABLE` specifies whether the framebuffer should be sRGB capable.
If supported, a created OpenGL context will support the `GL_FRAMEBUFFER_SRGB`
enable, also called `GL_FRAMEBUFFER_SRGB_EXT`) for controlling sRGB rendering
and a created OpenGL ES context will always have sRGB rendering enabled.
@anchor GLFW_SRGB_CAPABLE
__GLFW_SRGB_CAPABLE__ specifies whether the framebuffer should be sRGB capable.
Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
`GLFW_DOUBLEBUFFER` specifies whether the framebuffer should be double buffered.
You nearly always want to use double buffering. This is a hard constraint.
@par
__OpenGL:__ If enabled and supported by the system, the `GL_FRAMEBUFFER_SRGB`
enable will control sRGB rendering. By default, sRGB rendering will be
disabled.
@par
__OpenGL ES:__ If enabled and supported by the system, the context will always
have sRGB rendering enabled.
@anchor GLFW_DOUBLEBUFFER
__GLFW_DOUBLEBUFFER__ specifies whether the framebuffer should be double
buffered. You nearly always want to use double buffering. This is a hard
constraint. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
@subsubsection window_hints_mtr Monitor related hints
`GLFW_REFRESH_RATE` specifies the desired refresh rate for full screen windows.
If set to `GLFW_DONT_CARE`, the highest available refresh rate will be used.
This hint is ignored for windowed mode windows.
@anchor GLFW_REFRESH_RATE
__GLFW_REFRESH_RATE__ specifies the desired refresh rate for full screen
windows. A value of `GLFW_DONT_CARE` means the highest available refresh rate
will be used. This hint is ignored for windowed mode windows.
@subsubsection window_hints_ctx Context related hints
`GLFW_CLIENT_API` specifies which client API to create the context for.
@anchor GLFW_CLIENT_API_hint
__GLFW_CLIENT_API__ specifies which client API to create the context for.
Possible values are `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` and `GLFW_NO_API`.
This is a hard constraint.
`GLFW_CONTEXT_CREATION_API` specifies which context creation API to use to
create the context. Possible values are `GLFW_NATIVE_CONTEXT_API` and
`GLFW_EGL_CONTEXT_API`. This is a hard constraint. If no client API is
requested, this hint is ignored.
@anchor GLFW_CONTEXT_CREATION_API_hint
__GLFW_CONTEXT_CREATION_API__ specifies which context creation API to use to
create the context. Possible values are `GLFW_NATIVE_CONTEXT_API`,
`GLFW_EGL_CONTEXT_API` and `GLFW_OSMESA_CONTEXT_API`. This is a hard
constraint. If no client API is requested, this hint is ignored.
@par
__OS X:__ The EGL API is not available on this platform and requests to use it
@macos The EGL API is not available on this platform and requests to use it
will fail.
@par
__Wayland, Mir:__ The EGL API _is_ the native context creation API, so this hint
will have no effect.
@par
__OSMesa:__ As its name implies, an OpenGL context created with OSMesa does not
update the window contents when its buffers are swapped. Use OpenGL functions
or the OSMesa native access functions @ref glfwGetOSMesaColorBuffer and @ref
glfwGetOSMesaDepthBuffer to retrieve the framebuffer contents.
@note An OpenGL extension loader library that assumes it knows which context
creation API is used on a given platform may fail if you change this hint. This
can be resolved by having it load via @ref glfwGetProcAddress, which always uses
the selected API.
`GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR` specify the client
API version that the created context must be compatible with. The exact
@bug On some Linux systems, creating contexts via both the native and EGL APIs
in a single process will cause the application to segfault. Stick to one API or
the other on Linux for now.
@anchor GLFW_CONTEXT_VERSION_MAJOR_hint
@anchor GLFW_CONTEXT_VERSION_MINOR_hint
__GLFW_CONTEXT_VERSION_MAJOR__ and __GLFW_CONTEXT_VERSION_MINOR__ specify the
client API version that the created context must be compatible with. The exact
behavior of these hints depend on the requested client API.
@note Do not confuse these hints with `GLFW_VERSION_MAJOR` and
`GLFW_VERSION_MINOR`, which provide the API version of the GLFW header.
@par
__OpenGL:__ `GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR` are
not hard constraints, but creation will fail if the OpenGL version of the
created context is less than the one requested. It is therefore perfectly safe
to use the default of version 1.0 for legacy code and you will still get
backwards-compatible contexts of version 3.0 and above when available.
__OpenGL:__ These hints are not hard constraints, but creation will fail if the
OpenGL version of the created context is less than the one requested. It is
therefore perfectly safe to use the default of version 1.0 for legacy code and
you will still get backwards-compatible contexts of version 3.0 and above when
available.
@par
While there is no way to ask the driver for a context of the highest supported
@@ -285,14 +354,21 @@ version, GLFW will attempt to provide this when you ask for a version 1.0
context, which is the default for these hints.
@par
__OpenGL ES:__ `GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR` are
not hard constraints, but creation will fail if the OpenGL ES version of the
created context is less than the one requested. Additionally, OpenGL ES 1.x
cannot be returned if 2.0 or later was requested, and vice versa. This is
because OpenGL ES 3.x is backward compatible with 2.0, but OpenGL ES 2.0 is not
backward compatible with 1.x.
__OpenGL ES:__ These hints are not hard constraints, but creation will fail if
the OpenGL ES version of the created context is less than the one requested.
Additionally, OpenGL ES 1.x cannot be returned if 2.0 or later was requested,
and vice versa. This is because OpenGL ES 3.x is backward compatible with 2.0,
but OpenGL ES 2.0 is not backward compatible with 1.x.
`GLFW_OPENGL_FORWARD_COMPAT` specifies whether the OpenGL context should be
@note @macos The OS only supports forward-compatible core profile contexts for
OpenGL versions 3.2 and later. Before creating an OpenGL context of version
3.2 or later you must set the
[GLFW_OPENGL_FORWARD_COMPAT](@ref GLFW_OPENGL_FORWARD_COMPAT_hint) and
[GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint) hints accordingly. OpenGL
3.0 and 3.1 contexts are not supported at all on macOS.
@anchor GLFW_OPENGL_FORWARD_COMPAT_hint
__GLFW_OPENGL_FORWARD_COMPAT__ specifies whether the OpenGL context should be
forward-compatible, i.e. one where all functionality deprecated in the requested
version of OpenGL is removed. This must only be used if the requested OpenGL
version is 3.0 or above. If OpenGL ES is requested, this hint is ignored.
@@ -301,27 +377,32 @@ version is 3.0 or above. If OpenGL ES is requested, this hint is ignored.
Forward-compatibility is described in detail in the
[OpenGL Reference Manual](https://www.opengl.org/registry/).
`GLFW_OPENGL_DEBUG_CONTEXT` specifies whether to create a debug OpenGL context,
which may have additional error and performance issue reporting functionality.
If OpenGL ES is requested, this hint is ignored.
@anchor GLFW_OPENGL_DEBUG_CONTEXT_hint
__GLFW_OPENGL_DEBUG_CONTEXT__ specifies whether to create a debug OpenGL
context, which may have additional error and performance issue reporting
functionality. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. If OpenGL ES
is requested, this hint is ignored.
`GLFW_OPENGL_PROFILE` specifies which OpenGL profile to create the context for.
Possible values are one of `GLFW_OPENGL_CORE_PROFILE` or
@anchor GLFW_OPENGL_PROFILE_hint
__GLFW_OPENGL_PROFILE__ specifies which OpenGL profile to create the context
for. Possible values are one of `GLFW_OPENGL_CORE_PROFILE` or
`GLFW_OPENGL_COMPAT_PROFILE`, or `GLFW_OPENGL_ANY_PROFILE` to not request
a specific profile. If requesting an OpenGL version below 3.2,
`GLFW_OPENGL_ANY_PROFILE` must be used. If OpenGL ES is requested,
this hint is ignored.
`GLFW_OPENGL_ANY_PROFILE` must be used. If OpenGL ES is requested, this hint
is ignored.
@par
OpenGL profiles are described in detail in the
[OpenGL Reference Manual](https://www.opengl.org/registry/).
`GLFW_CONTEXT_ROBUSTNESS` specifies the robustness strategy to be used by the
@anchor GLFW_CONTEXT_ROBUSTNESS_hint
__GLFW_CONTEXT_ROBUSTNESS__ specifies the robustness strategy to be used by the
context. This can be one of `GLFW_NO_RESET_NOTIFICATION` or
`GLFW_LOSE_CONTEXT_ON_RESET`, or `GLFW_NO_ROBUSTNESS` to not request
a robustness strategy.
`GLFW_CONTEXT_RELEASE_BEHAVIOR` specifies the release behavior to be
@anchor GLFW_CONTEXT_RELEASE_BEHAVIOR_hint
__GLFW_CONTEXT_RELEASE_BEHAVIOR__ specifies the release behavior to be
used by the context. Possible values are one of `GLFW_ANY_RELEASE_BEHAVIOR`,
`GLFW_RELEASE_BEHAVIOR_FLUSH` or `GLFW_RELEASE_BEHAVIOR_NONE`. If the
behavior is `GLFW_ANY_RELEASE_BEHAVIOR`, the default behavior of the context
@@ -335,60 +416,88 @@ Context release behaviors are described in detail by the
[GL_KHR_context_flush_control](https://www.opengl.org/registry/specs/KHR/context_flush_control.txt)
extension.
`GLFW_CONTEXT_NO_ERROR` specifies whether errors should be generated by the
context. If enabled, situations that would have generated errors instead cause
undefined behavior.
@anchor GLFW_CONTEXT_NO_ERROR_hint
__GLFW_CONTEXT_NO_ERROR__ specifies whether errors should be generated by the
context. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. If enabled,
situations that would have generated errors instead cause undefined behavior.
@par
The no error mode for OpenGL and OpenGL ES is described in detail by the
[GL_KHR_no_error](https://www.opengl.org/registry/specs/KHR/no_error.txt)
extension.
@note This hint is experimental in its current state. There are currently
(October 2015) no corresponding WGL or GLX extensions. That makes this hint
a [hard constraint](@ref window_hints_hard) for those backends, as creation will
fail if unsupported context flags are requested. Once the extensions are
available, they will be required and creation of `GL_KHR_no_error` contexts may
fail on early drivers where this flag is supported without those extensions
being listed.
@subsubsection window_hints_osx macOS specific window hints
@anchor GLFW_COCOA_RETINA_FRAMEBUFFER_hint
__GLFW_COCOA_RETINA_FRAMEBUFFER__ specifies whether to use full resolution
framebuffers on Retina displays. Possible values are `GLFW_TRUE` and
`GLFW_FALSE`. This is ignored on other platforms.
@anchor GLFW_COCOA_FRAME_AUTOSAVE_hint
__GLFW_COCOA_FRAME_AUTOSAVE__ specifies whether to activate frame autosaving
using the window title specified at window creation. Possible values are
`GLFW_TRUE` and `GLFW_FALSE`. This is ignored on other platforms.
@anchor GLFW_COCOA_GRAPHICS_SWITCHING_hint
__GLFW_COCOA_GRAPHICS_SWITCHING__ specifies whether to in Automatic Graphics
Switching, i.e. to allow the system to choose the integrated GPU for the OpenGL
context and move it between GPUs if necessary or whether to force it to always
run on the discrete GPU. This only affects systems with both integrated and
discrete GPUs. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This is
ignored on other platforms.
@par
Simpler programs and tools may want to enable this to save power, while games
and other applications performing advanced rendering will want to leave it
disabled.
@par
A bundled application that wishes to participate in Automatic Graphics Switching
should also declare this in its `Info.plist` by setting the
`NSSupportsAutomaticGraphicsSwitching` key to `true`.
@subsubsection window_hints_values Supported and default values
Window hint | Default value | Supported values
------------------------------- | --------------------------- | ----------------
`GLFW_RESIZABLE` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_VISIBLE` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_DECORATED` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_FOCUSED` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_AUTO_ICONIFY` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_FLOATING` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_MAXIMIZED` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_RED_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_GREEN_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_BLUE_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_ALPHA_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_DEPTH_BITS` | 24 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_STENCIL_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_ACCUM_RED_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_ACCUM_GREEN_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_ACCUM_BLUE_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_ACCUM_ALPHA_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_AUX_BUFFERS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_SAMPLES` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_REFRESH_RATE` | `GLFW_DONT_CARE` | 0 to `INT_MAX` or `GLFW_DONT_CARE`
`GLFW_STEREO` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_SRGB_CAPABLE` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_DOUBLEBUFFER` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_CLIENT_API` | `GLFW_OPENGL_API` | `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`
`GLFW_CONTEXT_CREATION_API` | `GLFW_NATIVE_CONTEXT_API` | `GLFW_NATIVE_CONTEXT_API` or `GLFW_EGL_CONTEXT_API`
`GLFW_CONTEXT_VERSION_MAJOR` | 1 | Any valid major version number of the chosen client API
`GLFW_CONTEXT_VERSION_MINOR` | 0 | Any valid minor version number of the chosen client API
`GLFW_CONTEXT_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS`, `GLFW_NO_RESET_NOTIFICATION` or `GLFW_LOSE_CONTEXT_ON_RESET`
`GLFW_CONTEXT_RELEASE_BEHAVIOR` | `GLFW_ANY_RELEASE_BEHAVIOR` | `GLFW_ANY_RELEASE_BEHAVIOR`, `GLFW_RELEASE_BEHAVIOR_FLUSH` or `GLFW_RELEASE_BEHAVIOR_NONE`
`GLFW_OPENGL_FORWARD_COMPAT` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_OPENGL_DEBUG_CONTEXT` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_OPENGL_PROFILE` | `GLFW_OPENGL_ANY_PROFILE` | `GLFW_OPENGL_ANY_PROFILE`, `GLFW_OPENGL_COMPAT_PROFILE` or `GLFW_OPENGL_CORE_PROFILE`
Window hint | Default value | Supported values
----------------------------- | --------------------------- | ----------------
GLFW_RESIZABLE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_VISIBLE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_DECORATED | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_FOCUSED | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_AUTO_ICONIFY | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_FLOATING | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_MAXIMIZED | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_CENTER_CURSOR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_RED_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_GREEN_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_BLUE_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_ALPHA_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_DEPTH_BITS | 24 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_STENCIL_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_ACCUM_RED_BITS | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_ACCUM_GREEN_BITS | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_ACCUM_BLUE_BITS | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_ACCUM_ALPHA_BITS | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_AUX_BUFFERS | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_SAMPLES | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_REFRESH_RATE | `GLFW_DONT_CARE` | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_STEREO | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_SRGB_CAPABLE | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_DOUBLEBUFFER | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_CLIENT_API | `GLFW_OPENGL_API` | `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`
GLFW_CONTEXT_CREATION_API | `GLFW_NATIVE_CONTEXT_API` | `GLFW_NATIVE_CONTEXT_API`, `GLFW_EGL_CONTEXT_API` or `GLFW_OSMESA_CONTEXT_API`
GLFW_CONTEXT_VERSION_MAJOR | 1 | Any valid major version number of the chosen client API
GLFW_CONTEXT_VERSION_MINOR | 0 | Any valid minor version number of the chosen client API
GLFW_CONTEXT_ROBUSTNESS | `GLFW_NO_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS`, `GLFW_NO_RESET_NOTIFICATION` or `GLFW_LOSE_CONTEXT_ON_RESET`
GLFW_CONTEXT_RELEASE_BEHAVIOR | `GLFW_ANY_RELEASE_BEHAVIOR` | `GLFW_ANY_RELEASE_BEHAVIOR`, `GLFW_RELEASE_BEHAVIOR_FLUSH` or `GLFW_RELEASE_BEHAVIOR_NONE`
GLFW_OPENGL_FORWARD_COMPAT | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_OPENGL_DEBUG_CONTEXT | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_OPENGL_PROFILE | `GLFW_OPENGL_ANY_PROFILE` | `GLFW_OPENGL_ANY_PROFILE`, `GLFW_OPENGL_COMPAT_PROFILE` or `GLFW_OPENGL_CORE_PROFILE`
GLFW_COCOA_RETINA_FRAMEBUFFER | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_COCOA_FRAME_AUTOSAVE | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_COCOA_GRAPHICS_SWITCHING | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
@section window_events Window event processing
@@ -645,7 +754,7 @@ As long as your source file is encoded as UTF-8, you can use any Unicode
characters directly in the source.
@code
glfwSetWindowTitle(window, "星を追う子ども");
glfwSetWindowTitle(window, "ラストエグザイル");
@endcode
If you are using C++11 or C11, you can use a UTF-8 string literal.
@@ -668,6 +777,10 @@ images[1] = load_icon("my_icon_small.png");
glfwSetWindowIcon(window, 2, images);
@endcode
The image data is 32-bit, little-endian, non-premultiplied RGBA, i.e. eight bits
per channel with the red channel first. The pixels are arranged canonically as
sequential rows, starting from the top-left corner.
To revert to the default window icon, pass in an empty image array.
@code
@@ -724,7 +837,8 @@ glfwIconifyWindow(window);
When a full screen window is iconified, the original video mode of its monitor
is restored until the user or application restores the window.
Iconified windows can be restored with @ref glfwRestoreWindow.
Iconified windows can be restored with @ref glfwRestoreWindow. This function
also restores windows from maximization.
@code
glfwRestoreWindow(window);
@@ -763,6 +877,62 @@ int iconified = glfwGetWindowAttrib(window, GLFW_ICONIFIED);
@endcode
@subsection window_maximize Window maximization
Windows can be maximized (i.e. zoomed) with @ref glfwMaximizeWindow.
@code
glfwMaximizeWindow(window);
@endcode
Full screen windows cannot be maximized and passing a full screen window to this
function does nothing.
Maximized windows can be restored with @ref glfwRestoreWindow. This function
also restores windows from iconification.
@code
glfwRestoreWindow(window);
@endcode
If you wish to be notified when a window is maximized or restored, whether by
the user, system or your own code, set a maximize callback.
@code
glfwSetWindowMaximizeCallback(window, window_maximize_callback);
@endcode
The callback function receives changes in the maximization state of the window.
@code
void window_maximize_callback(GLFWwindow* window, int maximized)
{
if (maximized)
{
// The window was maximized
}
else
{
// The window was restored
}
}
@endcode
You can also get the current maximization state with @ref glfwGetWindowAttrib.
@code
int maximized = glfwGetWindowAttrib(window, GLFW_MAXIMIZED);
@endcode
By default, newly created windows are not maximized. You can change this
behavior by setting the [GLFW_MAXIMIZED](@ref GLFW_MAXIMIZED_hint) window hint
before creating the window.
@code
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
@endcode
@subsection window_hide Window visibility
Windowed mode windows can be hidden with @ref glfwHideWindow.
@@ -781,11 +951,6 @@ Hidden windows can be shown with @ref glfwShowWindow.
glfwShowWindow(window);
@endcode
Windowed mode windows can be created initially hidden with the `GLFW_VISIBLE`
[window hint](@ref window_hints_wnd). Windows created hidden are completely
invisible to the user until shown. This can be useful if you need to set up
your window further before showing it, for example moving it to a specific
location.
You can also get the current visibility state with @ref glfwGetWindowAttrib.
@@ -793,6 +958,18 @@ You can also get the current visibility state with @ref glfwGetWindowAttrib.
int visible = glfwGetWindowAttrib(window, GLFW_VISIBLE);
@endcode
By default, newly created windows are visible. You can change this behavior by
setting the [GLFW_VISIBLE](@ref GLFW_VISIBLE_hint) window hint before creating
the window.
@code
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
@endcode
Windows created hidden are completely invisible to the user until shown. This
can be useful if you need to set up your window further before showing it, for
example moving it to a specific location.
@subsection window_focus Window input focus
@@ -803,6 +980,10 @@ glfwFocusWindow.
glfwFocusWindow(window);
@endcode
Keep in mind that it can be very disruptive to the user when a window is forced
to the top. For a less disruptive way of getting the user's attention, see
[attention requests](@ref window_attention).
If you wish to be notified when a window gains or loses input focus, whether by
the user, system or your own code, set a focus callback.
@@ -832,6 +1013,28 @@ You can also get the current input focus state with @ref glfwGetWindowAttrib.
int focused = glfwGetWindowAttrib(window, GLFW_FOCUSED);
@endcode
By default, newly created windows are given input focus. You can change this
behavior by setting the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) window hint
before creating the window.
@code
glfwWindowHint(GLFW_FOCUSED, GLFW_FALSE);
@endcode
@subsection window_attention Window attention request
If you wish to notify the user of an event without interrupting, you can request
attention with @ref glfwRequestWindowAttention.
@code
glfwRequestWindowAttention(window);
@endcode
The system will highlight the specified window, or on platforms where this is
not supported, the application as a whole. Once the user has given it
attention, the system will automatically end the request.
@subsection window_refresh Window damage and refresh
@@ -861,10 +1064,10 @@ the window or framebuffer is resized.
@subsection window_attribs Window attributes
Windows have a number of attributes that can be returned using @ref
glfwGetWindowAttrib. Some reflect state that may change during the lifetime of
the window, while others reflect the corresponding hints and are fixed at the
time of creation. Some are related to the actual window and others to its
context.
glfwGetWindowAttrib. Some reflect state that may change as a result of user
interaction, (e.g. whether it has input focus), while others reflect inherent
properties of the window (e.g. what kind of border it has). Some are related to
the window and others to its OpenGL or OpenGL ES context.
@code
if (glfwGetWindowAttrib(window, GLFW_FOCUSED))
@@ -873,65 +1076,103 @@ if (glfwGetWindowAttrib(window, GLFW_FOCUSED))
}
@endcode
The [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
[GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
[GLFW_FLOATING](@ref GLFW_FLOATING_attrib) and
[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) window attributes can be
changed with @ref glfwSetWindowAttrib.
@code
glfwSetWindowAttrib(window, GLFW_RESIZABLE, GLFW_FALSE);
@endcode
@subsubsection window_attribs_wnd Window related attributes
`GLFW_FOCUSED` indicates whether the specified window has input focus. Initial
input focus is controlled by the [window hint](@ref window_hints_wnd) with the
same name.
@anchor GLFW_FOCUSED_attrib
__GLFW_FOCUSED__ indicates whether the specified window has input focus. See
@ref window_focus for details.
`GLFW_ICONIFIED` indicates whether the specified window is iconified, whether by
the user or with @ref glfwIconifyWindow.
@anchor GLFW_ICONIFIED_attrib
__GLFW_ICONIFIED__ indicates whether the specified window is iconified.
See @ref window_iconify for details.
`GLFW_MAXIMIZED` indicates whether the specified window is maximized, whether by
the user or with @ref glfwMaximizeWindow.
@anchor GLFW_MAXIMIZED_attrib
__GLFW_MAXIMIZED__ indicates whether the specified window is maximized. See
@ref window_maximize for details.
`GLFW_VISIBLE` indicates whether the specified window is visible. Window
visibility can be controlled with @ref glfwShowWindow and @ref glfwHideWindow
and initial visibility is controlled by the [window hint](@ref window_hints_wnd)
with the same name.
@anchor GLFW_VISIBLE_attrib
__GLFW_VISIBLE__ indicates whether the specified window is visible. See @ref
window_hide for details.
`GLFW_RESIZABLE` indicates whether the specified window is resizable _by the
user_. This is set on creation with the [window hint](@ref window_hints_wnd)
with the same name.
@anchor GLFW_RESIZABLE_attrib
__GLFW_RESIZABLE__ indicates whether the specified window is resizable _by the
user_. This can be set before creation with the
[GLFW_RESIZABLE](@ref GLFW_RESIZABLE_hint) window hint or after with @ref
glfwSetWindowAttrib.
`GLFW_DECORATED` indicates whether the specified window has decorations such as
a border, a close widget, etc. This is set on creation with the
[window hint](@ref window_hints_wnd) with the same name.
@anchor GLFW_DECORATED_attrib
__GLFW_DECORATED__ indicates whether the specified window has decorations such
as a border, a close widget, etc. This can be set before creation with the
[GLFW_DECORATED](@ref GLFW_DECORATED_hint) window hint or after with @ref
glfwSetWindowAttrib.
`GLFW_FLOATING` indicates whether the specified window is floating, also called
topmost or always-on-top. This is controlled by the
[window hint](@ref window_hints_wnd) with the same name.
@anchor GLFW_AUTO_ICONIFY_attrib
__GLFW_AUTO_ICONIFY__ indicates whether the specified full screen window is
iconified on focus loss, a close widget, etc. This can be set before creation
with the [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_hint) window hint or after
with @ref glfwSetWindowAttrib.
@anchor GLFW_FLOATING_attrib
__GLFW_FLOATING__ indicates whether the specified window is floating, also
called topmost or always-on-top. This can be set before creation with the
[GLFW_FLOATING](@ref GLFW_FLOATING_hint) window hint or after with @ref
glfwSetWindowAttrib.
@subsubsection window_attribs_ctx Context related attributes
`GLFW_CLIENT_API` indicates the client API provided by the window's context;
@anchor GLFW_CLIENT_API_attrib
__GLFW_CLIENT_API__ indicates the client API provided by the window's context;
either `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`.
`GLFW_CONTEXT_CREATION_API` indicates the context creation API used to create
the window's context; either `GLFW_NATIVE_CONTEXT_API` or
`GLFW_EGL_CONTEXT_API`.
@anchor GLFW_CONTEXT_CREATION_API_attrib
__GLFW_CONTEXT_CREATION_API__ indicates the context creation API used to create
the window's context; either `GLFW_NATIVE_CONTEXT_API`, `GLFW_EGL_CONTEXT_API`
or `GLFW_OSMESA_CONTEXT_API`.
`GLFW_CONTEXT_VERSION_MAJOR`, `GLFW_CONTEXT_VERSION_MINOR` and
`GLFW_CONTEXT_REVISION` indicate the client API version of the window's context.
@anchor GLFW_CONTEXT_VERSION_MAJOR_attrib
@anchor GLFW_CONTEXT_VERSION_MINOR_attrib
@anchor GLFW_CONTEXT_REVISION_attrib
__GLFW_CONTEXT_VERSION_MAJOR__, __GLFW_CONTEXT_VERSION_MINOR__ and
__GLFW_CONTEXT_REVISION__ indicate the client API version of the window's
context.
`GLFW_OPENGL_FORWARD_COMPAT` is `GLFW_TRUE` if the window's context is an OpenGL
forward-compatible one, or `GLFW_FALSE` otherwise.
@note Do not confuse these attributes with `GLFW_VERSION_MAJOR`,
`GLFW_VERSION_MINOR` and `GLFW_VERSION_REVISION` which provide the API version
of the GLFW header.
`GLFW_OPENGL_DEBUG_CONTEXT` is `GLFW_TRUE` if the window's context is an OpenGL
debug context, or `GLFW_FALSE` otherwise.
@anchor GLFW_OPENGL_FORWARD_COMPAT_attrib
__GLFW_OPENGL_FORWARD_COMPAT__ is `GLFW_TRUE` if the window's context is an
OpenGL forward-compatible one, or `GLFW_FALSE` otherwise.
`GLFW_OPENGL_PROFILE` indicates the OpenGL profile used by the context. This is
`GLFW_OPENGL_CORE_PROFILE` or `GLFW_OPENGL_COMPAT_PROFILE` if the context uses
a known profile, or `GLFW_OPENGL_ANY_PROFILE` if the OpenGL profile is unknown
or the context is an OpenGL ES context. Note that the returned profile may not
match the profile bits of the context flags, as GLFW will try other means of
detecting the profile when no bits are set.
@anchor GLFW_OPENGL_DEBUG_CONTEXT_attrib
__GLFW_OPENGL_DEBUG_CONTEXT__ is `GLFW_TRUE` if the window's context is an
OpenGL debug context, or `GLFW_FALSE` otherwise.
`GLFW_CONTEXT_ROBUSTNESS` indicates the robustness strategy used by the context.
This is `GLFW_LOSE_CONTEXT_ON_RESET` or `GLFW_NO_RESET_NOTIFICATION` if the
window's context supports robustness, or `GLFW_NO_ROBUSTNESS` otherwise.
@anchor GLFW_OPENGL_PROFILE_attrib
__GLFW_OPENGL_PROFILE__ indicates the OpenGL profile used by the context. This
is `GLFW_OPENGL_CORE_PROFILE` or `GLFW_OPENGL_COMPAT_PROFILE` if the context
uses a known profile, or `GLFW_OPENGL_ANY_PROFILE` if the OpenGL profile is
unknown or the context is an OpenGL ES context. Note that the returned profile
may not match the profile bits of the context flags, as GLFW will try other
means of detecting the profile when no bits are set.
@anchor GLFW_CONTEXT_ROBUSTNESS_attrib
__GLFW_CONTEXT_ROBUSTNESS__ indicates the robustness strategy used by the
context. This is `GLFW_LOSE_CONTEXT_ON_RESET` or `GLFW_NO_RESET_NOTIFICATION`
if the window's context supports robustness, or `GLFW_NO_ROBUSTNESS` otherwise.
@subsubsection window_attribs_fb Framebuffer related attributes
+14 -6
View File
@@ -1,9 +1,9 @@
link_libraries(glfw)
include_directories(${glfw_INCLUDE_DIRS})
include_directories(${glfw_INCLUDE_DIRS} "${GLFW_SOURCE_DIR}/deps")
if (BUILD_SHARED_LIBS)
if (MATH_LIBRARY)
link_libraries("${MATH_LIBRARY}")
endif()
@@ -11,14 +11,16 @@ if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
include_directories("${GLFW_SOURCE_DIR}/deps")
if (GLFW_USE_OSMESA)
add_definitions(-DUSE_NATIVE_OSMESA)
endif()
if (WIN32)
set(ICON glfw.rc)
elseif (APPLE)
set(ICON glfw.icns)
set_source_files_properties(glfw.icns PROPERTIES
MAXOSX_PACKAGE_LOCATION "Resources")
MACOSX_PACKAGE_LOCATION "Resources")
endif()
set(GLAD "${GLFW_SOURCE_DIR}/deps/glad/glad.h"
@@ -31,16 +33,22 @@ set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
add_executable(boing WIN32 MACOSX_BUNDLE boing.c ${ICON} ${GLAD})
add_executable(gears WIN32 MACOSX_BUNDLE gears.c ${ICON} ${GLAD})
add_executable(heightmap WIN32 MACOSX_BUNDLE heightmap.c ${ICON} ${GLAD})
add_executable(offscreen offscreen.c ${ICON} ${GLAD})
add_executable(particles WIN32 MACOSX_BUNDLE particles.c ${ICON} ${TINYCTHREAD} ${GETOPT} ${GLAD})
add_executable(simple WIN32 MACOSX_BUNDLE simple.c ${ICON} ${GLAD})
add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD})
add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD})
target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}")
if (RT_LIBRARY)
target_link_libraries(particles "${RT_LIBRARY}")
endif()
set(WINDOWS_BINARIES boing gears heightmap particles simple splitview wave)
set(CONSOLE_BINARIES offscreen)
set_target_properties(${WINDOWS_BINARIES} PROPERTIES FOLDER "GLFW3/Examples")
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
FOLDER "GLFW3/Examples")
if (MSVC)
# Tell MSVC to use main instead of WinMain for Windows subsystem executables
+1 -1
View File
@@ -15,7 +15,7 @@
* - Slightly modified camera that should work better for stereo viewing
*
*
* Camilla Berglund:
* Camilla Löwy:
* - Removed FPS counter (this is not a benchmark)
* - Added a few comments
* - Enabled vsync
+175
View File
@@ -0,0 +1,175 @@
//========================================================================
// Offscreen rendering example
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#if USE_NATIVE_OSMESA
#define GLFW_EXPOSE_NATIVE_OSMESA
#include <GLFW/glfw3native.h>
#endif
#include "linmath.h"
#include <stdlib.h>
#include <stdio.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>
static const struct
{
float x, y;
float r, g, b;
} vertices[3] =
{
{ -0.6f, -0.4f, 1.f, 0.f, 0.f },
{ 0.6f, -0.4f, 0.f, 1.f, 0.f },
{ 0.f, 0.6f, 0.f, 0.f, 1.f }
};
static const char* vertex_shader_text =
"#version 110\n"
"uniform mat4 MVP;\n"
"attribute vec3 vCol;\n"
"attribute vec2 vPos;\n"
"varying vec3 color;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
" color = vCol;\n"
"}\n";
static const char* fragment_shader_text =
"#version 110\n"
"varying vec3 color;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(color, 1.0);\n"
"}\n";
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
int main(void)
{
GLFWwindow* window;
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
GLint mvp_location, vpos_location, vcol_location;
float ratio;
int width, height;
mat4x4 mvp;
char* buffer;
glfwSetErrorCallback(error_callback);
glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
// NOTE: OpenGL error checks have been omitted for brevity
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
mvp_location = glGetUniformLocation(program, "MVP");
vpos_location = glGetAttribLocation(program, "vPos");
vcol_location = glGetAttribLocation(program, "vCol");
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(vertices[0]), (void*) 0);
glEnableVertexAttribArray(vcol_location);
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
sizeof(vertices[0]), (void*) (sizeof(float) * 2));
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float) height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
mat4x4_ortho(mvp, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
glUseProgram(program);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glDrawArrays(GL_TRIANGLES, 0, 3);
#if USE_NATIVE_OSMESA
glfwGetOSMesaColorBuffer(window, &width, &height, NULL, (void**) &buffer);
#else
buffer = calloc(4, width * height);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
#endif
// Write image Y-flipped because OpenGL
stbi_write_png("offscreen.png",
width, height, 4,
buffer + (width * 4 * (height - 1)),
-width * 4);
#if USE_NATIVE_OSMESA
// Here is where there's nothing
#else
free(buffer);
#endif
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
+7 -3
View File
@@ -1,7 +1,7 @@
//========================================================================
// A simple particle engine with threaded physics
// Copyright (c) Marcus Geelnard
// Copyright (c) Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -457,7 +457,9 @@ static void draw_particles(GLFWwindow* window, double t, float dt)
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_nsec += 100000000;
ts.tv_nsec += 100 * 1000 * 1000;
ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
ts.tv_nsec %= 1000 * 1000 * 1000;
cnd_timedwait(&thread_sync.p_done, &thread_sync.particles_lock, &ts);
}
@@ -908,7 +910,9 @@ static int physics_thread_main(void* arg)
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_nsec += 100000000;
ts.tv_nsec += 100 * 1000 * 1000;
ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
ts.tv_nsec %= 1000 * 1000 * 1000;
cnd_timedwait(&thread_sync.d_done, &thread_sync.particles_lock, &ts);
}
+5 -3
View File
@@ -1,6 +1,6 @@
//========================================================================
// Simple GLFW example
// Copyright (c) Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -44,6 +44,7 @@ static const struct
};
static const char* vertex_shader_text =
"#version 110\n"
"uniform mat4 MVP;\n"
"attribute vec3 vCol;\n"
"attribute vec2 vPos;\n"
@@ -55,6 +56,7 @@ static const char* vertex_shader_text =
"}\n";
static const char* fragment_shader_text =
"#version 110\n"
"varying vec3 color;\n"
"void main()\n"
"{\n"
@@ -124,10 +126,10 @@ int main(void)
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(float) * 5, (void*) 0);
sizeof(vertices[0]), (void*) 0);
glEnableVertexAttribArray(vcol_location);
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
sizeof(float) * 5, (void*) (sizeof(float) * 2));
sizeof(vertices[0]), (void*) (sizeof(float) * 2));
while (!glfwWindowShouldClose(window))
{
+1 -1
View File
@@ -5,7 +5,7 @@
* Modified for GLFW by Sylvain Hellegouarch - sh@programmationworld.com
* Modified for variable frame rate by Marcus Geelnard
* 2003-Jan-31: Minor cleanups and speedups / MG
* 2010-10-24: Formatting and cleanup - Camilla Berglund
* 2010-10-24: Formatting and cleanup - Camilla Löwy
*****************************************************************************/
#if defined(_MSC_VER)
+1210 -237
View File
File diff suppressed because it is too large Load Diff
+69 -6
View File
@@ -1,9 +1,9 @@
/*************************************************************************
* GLFW 3.2 - www.glfw.org
* GLFW 3.3 - www.glfw.org
* A library for OpenGL, window and input
*------------------------------------------------------------------------
* Copyright (c) 2002-2006 Marcus Geelnard
* Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
* Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -45,12 +45,13 @@ extern "C" {
* more information.
*/
/*! @defgroup native Native access
* @brief Functions related to accessing native handles.
*
* **By using the native access functions you assert that you know what you're
* doing and how to fix problems caused by using them. If you don't, you
* shouldn't be using them.**
*
* Before the inclusion of @ref glfw3native.h, you may define exactly one
* Before the inclusion of @ref glfw3native.h, you may define zero or more
* window system API macro and zero or more context creation API macros.
*
* The chosen backends must match those the library was compiled for. Failure
@@ -68,6 +69,7 @@ extern "C" {
* * `GLFW_EXPOSE_NATIVE_NSGL`
* * `GLFW_EXPOSE_NATIVE_GLX`
* * `GLFW_EXPOSE_NATIVE_EGL`
* * `GLFW_EXPOSE_NATIVE_OSMESA`
*
* These macros select which of the native access functions that are declared
* and which platform-specific headers to include. It is then up your (by
@@ -114,6 +116,9 @@ extern "C" {
#if defined(GLFW_EXPOSE_NATIVE_EGL)
#include <EGL/egl.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
#include <GL/osmesa.h>
#endif
/*************************************************************************
@@ -389,9 +394,9 @@ GLFWAPI MirConnection* glfwGetMirDisplay(void);
*/
GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);
/*! @brief Returns the `MirSurface*` of the specified window.
/*! @brief Returns the `MirWindow*` of the specified window.
*
* @return The `MirSurface*` of the specified window, or `NULL` if an
* @return The `MirWindow*` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
@@ -401,7 +406,7 @@ GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);
*
* @ingroup native
*/
GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window);
GLFWAPI MirWindow* glfwGetMirWindow(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_EGL)
@@ -448,6 +453,64 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
/*! @brief Retrieves the color buffer associated with the specified window.
*
* @param[in] window The window whose color buffer to retrieve.
* @param[out] width Where to store the width of the color buffer, or `NULL`.
* @param[out] height Where to store the height of the color buffer, or `NULL`.
* @param[out] format Where to store the OSMesa pixel format of the color
* buffer, or `NULL`.
* @param[out] buffer Where to store the address of the color buffer, or
* `NULL`.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height, int* format, void** buffer);
/*! @brief Retrieves the depth buffer associated with the specified window.
*
* @param[in] window The window whose depth buffer to retrieve.
* @param[out] width Where to store the width of the depth buffer, or `NULL`.
* @param[out] height Where to store the height of the depth buffer, or `NULL`.
* @param[out] bytesPerValue Where to store the number of bytes per depth
* buffer element, or `NULL`.
* @param[out] buffer Where to store the address of the depth buffer, or
* `NULL`.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height, int* bytesPerValue, void** buffer);
/*! @brief Returns the `OSMesaContext` of the specified window.
*
* @return The `OSMesaContext` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window);
#endif
#ifdef __cplusplus
}
#endif
+37 -19
View File
@@ -1,5 +1,5 @@
set(common_HEADERS internal.h
set(common_HEADERS internal.h mappings.h
"${GLFW_BINARY_DIR}/src/glfw_config.h"
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h")
@@ -7,29 +7,37 @@ set(common_SOURCES context.c init.c input.c monitor.c vulkan.c window.c)
if (_GLFW_COCOA)
set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h
posix_tls.h nsgl_context.h)
posix_thread.h nsgl_context.h egl_context.h osmesa_context.c)
set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_tls.c
nsgl_context.m)
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_thread.c
nsgl_context.m egl_context.c osmesa_context.c)
elseif (_GLFW_WIN32)
set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h
wgl_context.h egl_context.h)
wgl_context.h egl_context.h osmesa_context.h)
set(glfw_SOURCES ${common_SOURCES} win32_init.c win32_joystick.c
win32_monitor.c win32_time.c win32_tls.c win32_window.c
wgl_context.c egl_context.c)
win32_monitor.c win32_time.c win32_thread.c win32_window.c
wgl_context.c egl_context.c osmesa_context.c)
elseif (_GLFW_X11)
set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h
linux_joystick.h posix_time.h posix_tls.h glx_context.h
egl_context.h)
set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h posix_time.h
posix_thread.h glx_context.h egl_context.h osmesa_context.h)
set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c
xkb_unicode.c linux_joystick.c posix_time.c posix_tls.c
glx_context.c egl_context.c)
xkb_unicode.c posix_time.c posix_thread.c glx_context.c
egl_context.c osmesa_context.c)
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(glfw_HEADERS ${glfw_HEADERS} linux_joystick.h)
set(glfw_SOURCES ${glfw_SOURCES} linux_joystick.c)
else()
set(glfw_HEADERS ${glfw_HEADERS} null_joystick.h)
set(glfw_SOURCES ${glfw_SOURCES} null_joystick.c)
endif()
elseif (_GLFW_WAYLAND)
set(glfw_HEADERS ${common_HEADERS} wl_platform.h linux_joystick.h
posix_time.h posix_tls.h xkb_unicode.h egl_context.h)
posix_time.h posix_thread.h xkb_unicode.h egl_context.h
osmesa_context.h)
set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
egl_context.c)
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
egl_context.c osmesa_context.c)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
@@ -41,10 +49,16 @@ elseif (_GLFW_WAYLAND)
BASENAME pointer-constraints-unstable-v1)
elseif (_GLFW_MIR)
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
posix_time.h posix_tls.h xkb_unicode.h egl_context.h)
posix_time.h posix_thread.h xkb_unicode.h egl_context.h
osmesa_context.h)
set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
egl_context.c)
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
egl_context.c osmesa_context.c)
elseif (_GLFW_OSMESA)
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
posix_time.h posix_thread.h osmesa_context.h)
set(glfw_SOURCES ${common_SOURCES} null_init.c null_monitor.c null_window.c
null_joystick.c posix_time.c posix_thread.c osmesa_context.c)
endif()
if (APPLE)
@@ -115,6 +129,10 @@ if (MSVC)
endif()
if (GLFW_INSTALL)
install(TARGETS glfw EXPORT glfwTargets DESTINATION lib${LIB_SUFFIX})
install(TARGETS glfw
EXPORT glfwTargets
RUNTIME DESTINATION "bin"
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
LIBRARY DESTINATION "lib${LIB_SUFFIX}")
endif()
+127 -151
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 OS X - www.glfw.org
// GLFW 3.3 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -28,8 +28,6 @@
#include <sys/param.h> // For MAXPATHLEN
#if defined(_GLFW_USE_CHDIR)
// Change to our application bundle's resources directory, if present
//
static void changeToResourcesDirectory(void)
@@ -66,137 +64,135 @@ static void changeToResourcesDirectory(void)
chdir(resourcesPath);
}
#endif /* _GLFW_USE_CHDIR */
// Create key code translation tables
//
static void createKeyTables(void)
{
int scancode;
memset(_glfw.ns.publicKeys, -1, sizeof(_glfw.ns.publicKeys));
memset(_glfw.ns.nativeKeys, -1, sizeof(_glfw.ns.nativeKeys));
memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
_glfw.ns.publicKeys[0x1D] = GLFW_KEY_0;
_glfw.ns.publicKeys[0x12] = GLFW_KEY_1;
_glfw.ns.publicKeys[0x13] = GLFW_KEY_2;
_glfw.ns.publicKeys[0x14] = GLFW_KEY_3;
_glfw.ns.publicKeys[0x15] = GLFW_KEY_4;
_glfw.ns.publicKeys[0x17] = GLFW_KEY_5;
_glfw.ns.publicKeys[0x16] = GLFW_KEY_6;
_glfw.ns.publicKeys[0x1A] = GLFW_KEY_7;
_glfw.ns.publicKeys[0x1C] = GLFW_KEY_8;
_glfw.ns.publicKeys[0x19] = GLFW_KEY_9;
_glfw.ns.publicKeys[0x00] = GLFW_KEY_A;
_glfw.ns.publicKeys[0x0B] = GLFW_KEY_B;
_glfw.ns.publicKeys[0x08] = GLFW_KEY_C;
_glfw.ns.publicKeys[0x02] = GLFW_KEY_D;
_glfw.ns.publicKeys[0x0E] = GLFW_KEY_E;
_glfw.ns.publicKeys[0x03] = GLFW_KEY_F;
_glfw.ns.publicKeys[0x05] = GLFW_KEY_G;
_glfw.ns.publicKeys[0x04] = GLFW_KEY_H;
_glfw.ns.publicKeys[0x22] = GLFW_KEY_I;
_glfw.ns.publicKeys[0x26] = GLFW_KEY_J;
_glfw.ns.publicKeys[0x28] = GLFW_KEY_K;
_glfw.ns.publicKeys[0x25] = GLFW_KEY_L;
_glfw.ns.publicKeys[0x2E] = GLFW_KEY_M;
_glfw.ns.publicKeys[0x2D] = GLFW_KEY_N;
_glfw.ns.publicKeys[0x1F] = GLFW_KEY_O;
_glfw.ns.publicKeys[0x23] = GLFW_KEY_P;
_glfw.ns.publicKeys[0x0C] = GLFW_KEY_Q;
_glfw.ns.publicKeys[0x0F] = GLFW_KEY_R;
_glfw.ns.publicKeys[0x01] = GLFW_KEY_S;
_glfw.ns.publicKeys[0x11] = GLFW_KEY_T;
_glfw.ns.publicKeys[0x20] = GLFW_KEY_U;
_glfw.ns.publicKeys[0x09] = GLFW_KEY_V;
_glfw.ns.publicKeys[0x0D] = GLFW_KEY_W;
_glfw.ns.publicKeys[0x07] = GLFW_KEY_X;
_glfw.ns.publicKeys[0x10] = GLFW_KEY_Y;
_glfw.ns.publicKeys[0x06] = GLFW_KEY_Z;
_glfw.ns.keycodes[0x1D] = GLFW_KEY_0;
_glfw.ns.keycodes[0x12] = GLFW_KEY_1;
_glfw.ns.keycodes[0x13] = GLFW_KEY_2;
_glfw.ns.keycodes[0x14] = GLFW_KEY_3;
_glfw.ns.keycodes[0x15] = GLFW_KEY_4;
_glfw.ns.keycodes[0x17] = GLFW_KEY_5;
_glfw.ns.keycodes[0x16] = GLFW_KEY_6;
_glfw.ns.keycodes[0x1A] = GLFW_KEY_7;
_glfw.ns.keycodes[0x1C] = GLFW_KEY_8;
_glfw.ns.keycodes[0x19] = GLFW_KEY_9;
_glfw.ns.keycodes[0x00] = GLFW_KEY_A;
_glfw.ns.keycodes[0x0B] = GLFW_KEY_B;
_glfw.ns.keycodes[0x08] = GLFW_KEY_C;
_glfw.ns.keycodes[0x02] = GLFW_KEY_D;
_glfw.ns.keycodes[0x0E] = GLFW_KEY_E;
_glfw.ns.keycodes[0x03] = GLFW_KEY_F;
_glfw.ns.keycodes[0x05] = GLFW_KEY_G;
_glfw.ns.keycodes[0x04] = GLFW_KEY_H;
_glfw.ns.keycodes[0x22] = GLFW_KEY_I;
_glfw.ns.keycodes[0x26] = GLFW_KEY_J;
_glfw.ns.keycodes[0x28] = GLFW_KEY_K;
_glfw.ns.keycodes[0x25] = GLFW_KEY_L;
_glfw.ns.keycodes[0x2E] = GLFW_KEY_M;
_glfw.ns.keycodes[0x2D] = GLFW_KEY_N;
_glfw.ns.keycodes[0x1F] = GLFW_KEY_O;
_glfw.ns.keycodes[0x23] = GLFW_KEY_P;
_glfw.ns.keycodes[0x0C] = GLFW_KEY_Q;
_glfw.ns.keycodes[0x0F] = GLFW_KEY_R;
_glfw.ns.keycodes[0x01] = GLFW_KEY_S;
_glfw.ns.keycodes[0x11] = GLFW_KEY_T;
_glfw.ns.keycodes[0x20] = GLFW_KEY_U;
_glfw.ns.keycodes[0x09] = GLFW_KEY_V;
_glfw.ns.keycodes[0x0D] = GLFW_KEY_W;
_glfw.ns.keycodes[0x07] = GLFW_KEY_X;
_glfw.ns.keycodes[0x10] = GLFW_KEY_Y;
_glfw.ns.keycodes[0x06] = GLFW_KEY_Z;
_glfw.ns.publicKeys[0x27] = GLFW_KEY_APOSTROPHE;
_glfw.ns.publicKeys[0x2A] = GLFW_KEY_BACKSLASH;
_glfw.ns.publicKeys[0x2B] = GLFW_KEY_COMMA;
_glfw.ns.publicKeys[0x18] = GLFW_KEY_EQUAL;
_glfw.ns.publicKeys[0x32] = GLFW_KEY_GRAVE_ACCENT;
_glfw.ns.publicKeys[0x21] = GLFW_KEY_LEFT_BRACKET;
_glfw.ns.publicKeys[0x1B] = GLFW_KEY_MINUS;
_glfw.ns.publicKeys[0x2F] = GLFW_KEY_PERIOD;
_glfw.ns.publicKeys[0x1E] = GLFW_KEY_RIGHT_BRACKET;
_glfw.ns.publicKeys[0x29] = GLFW_KEY_SEMICOLON;
_glfw.ns.publicKeys[0x2C] = GLFW_KEY_SLASH;
_glfw.ns.publicKeys[0x0A] = GLFW_KEY_WORLD_1;
_glfw.ns.keycodes[0x27] = GLFW_KEY_APOSTROPHE;
_glfw.ns.keycodes[0x2A] = GLFW_KEY_BACKSLASH;
_glfw.ns.keycodes[0x2B] = GLFW_KEY_COMMA;
_glfw.ns.keycodes[0x18] = GLFW_KEY_EQUAL;
_glfw.ns.keycodes[0x32] = GLFW_KEY_GRAVE_ACCENT;
_glfw.ns.keycodes[0x21] = GLFW_KEY_LEFT_BRACKET;
_glfw.ns.keycodes[0x1B] = GLFW_KEY_MINUS;
_glfw.ns.keycodes[0x2F] = GLFW_KEY_PERIOD;
_glfw.ns.keycodes[0x1E] = GLFW_KEY_RIGHT_BRACKET;
_glfw.ns.keycodes[0x29] = GLFW_KEY_SEMICOLON;
_glfw.ns.keycodes[0x2C] = GLFW_KEY_SLASH;
_glfw.ns.keycodes[0x0A] = GLFW_KEY_WORLD_1;
_glfw.ns.publicKeys[0x33] = GLFW_KEY_BACKSPACE;
_glfw.ns.publicKeys[0x39] = GLFW_KEY_CAPS_LOCK;
_glfw.ns.publicKeys[0x75] = GLFW_KEY_DELETE;
_glfw.ns.publicKeys[0x7D] = GLFW_KEY_DOWN;
_glfw.ns.publicKeys[0x77] = GLFW_KEY_END;
_glfw.ns.publicKeys[0x24] = GLFW_KEY_ENTER;
_glfw.ns.publicKeys[0x35] = GLFW_KEY_ESCAPE;
_glfw.ns.publicKeys[0x7A] = GLFW_KEY_F1;
_glfw.ns.publicKeys[0x78] = GLFW_KEY_F2;
_glfw.ns.publicKeys[0x63] = GLFW_KEY_F3;
_glfw.ns.publicKeys[0x76] = GLFW_KEY_F4;
_glfw.ns.publicKeys[0x60] = GLFW_KEY_F5;
_glfw.ns.publicKeys[0x61] = GLFW_KEY_F6;
_glfw.ns.publicKeys[0x62] = GLFW_KEY_F7;
_glfw.ns.publicKeys[0x64] = GLFW_KEY_F8;
_glfw.ns.publicKeys[0x65] = GLFW_KEY_F9;
_glfw.ns.publicKeys[0x6D] = GLFW_KEY_F10;
_glfw.ns.publicKeys[0x67] = GLFW_KEY_F11;
_glfw.ns.publicKeys[0x6F] = GLFW_KEY_F12;
_glfw.ns.publicKeys[0x69] = GLFW_KEY_F13;
_glfw.ns.publicKeys[0x6B] = GLFW_KEY_F14;
_glfw.ns.publicKeys[0x71] = GLFW_KEY_F15;
_glfw.ns.publicKeys[0x6A] = GLFW_KEY_F16;
_glfw.ns.publicKeys[0x40] = GLFW_KEY_F17;
_glfw.ns.publicKeys[0x4F] = GLFW_KEY_F18;
_glfw.ns.publicKeys[0x50] = GLFW_KEY_F19;
_glfw.ns.publicKeys[0x5A] = GLFW_KEY_F20;
_glfw.ns.publicKeys[0x73] = GLFW_KEY_HOME;
_glfw.ns.publicKeys[0x72] = GLFW_KEY_INSERT;
_glfw.ns.publicKeys[0x7B] = GLFW_KEY_LEFT;
_glfw.ns.publicKeys[0x3A] = GLFW_KEY_LEFT_ALT;
_glfw.ns.publicKeys[0x3B] = GLFW_KEY_LEFT_CONTROL;
_glfw.ns.publicKeys[0x38] = GLFW_KEY_LEFT_SHIFT;
_glfw.ns.publicKeys[0x37] = GLFW_KEY_LEFT_SUPER;
_glfw.ns.publicKeys[0x6E] = GLFW_KEY_MENU;
_glfw.ns.publicKeys[0x47] = GLFW_KEY_NUM_LOCK;
_glfw.ns.publicKeys[0x79] = GLFW_KEY_PAGE_DOWN;
_glfw.ns.publicKeys[0x74] = GLFW_KEY_PAGE_UP;
_glfw.ns.publicKeys[0x7C] = GLFW_KEY_RIGHT;
_glfw.ns.publicKeys[0x3D] = GLFW_KEY_RIGHT_ALT;
_glfw.ns.publicKeys[0x3E] = GLFW_KEY_RIGHT_CONTROL;
_glfw.ns.publicKeys[0x3C] = GLFW_KEY_RIGHT_SHIFT;
_glfw.ns.publicKeys[0x36] = GLFW_KEY_RIGHT_SUPER;
_glfw.ns.publicKeys[0x31] = GLFW_KEY_SPACE;
_glfw.ns.publicKeys[0x30] = GLFW_KEY_TAB;
_glfw.ns.publicKeys[0x7E] = GLFW_KEY_UP;
_glfw.ns.keycodes[0x33] = GLFW_KEY_BACKSPACE;
_glfw.ns.keycodes[0x39] = GLFW_KEY_CAPS_LOCK;
_glfw.ns.keycodes[0x75] = GLFW_KEY_DELETE;
_glfw.ns.keycodes[0x7D] = GLFW_KEY_DOWN;
_glfw.ns.keycodes[0x77] = GLFW_KEY_END;
_glfw.ns.keycodes[0x24] = GLFW_KEY_ENTER;
_glfw.ns.keycodes[0x35] = GLFW_KEY_ESCAPE;
_glfw.ns.keycodes[0x7A] = GLFW_KEY_F1;
_glfw.ns.keycodes[0x78] = GLFW_KEY_F2;
_glfw.ns.keycodes[0x63] = GLFW_KEY_F3;
_glfw.ns.keycodes[0x76] = GLFW_KEY_F4;
_glfw.ns.keycodes[0x60] = GLFW_KEY_F5;
_glfw.ns.keycodes[0x61] = GLFW_KEY_F6;
_glfw.ns.keycodes[0x62] = GLFW_KEY_F7;
_glfw.ns.keycodes[0x64] = GLFW_KEY_F8;
_glfw.ns.keycodes[0x65] = GLFW_KEY_F9;
_glfw.ns.keycodes[0x6D] = GLFW_KEY_F10;
_glfw.ns.keycodes[0x67] = GLFW_KEY_F11;
_glfw.ns.keycodes[0x6F] = GLFW_KEY_F12;
_glfw.ns.keycodes[0x69] = GLFW_KEY_F13;
_glfw.ns.keycodes[0x6B] = GLFW_KEY_F14;
_glfw.ns.keycodes[0x71] = GLFW_KEY_F15;
_glfw.ns.keycodes[0x6A] = GLFW_KEY_F16;
_glfw.ns.keycodes[0x40] = GLFW_KEY_F17;
_glfw.ns.keycodes[0x4F] = GLFW_KEY_F18;
_glfw.ns.keycodes[0x50] = GLFW_KEY_F19;
_glfw.ns.keycodes[0x5A] = GLFW_KEY_F20;
_glfw.ns.keycodes[0x73] = GLFW_KEY_HOME;
_glfw.ns.keycodes[0x72] = GLFW_KEY_INSERT;
_glfw.ns.keycodes[0x7B] = GLFW_KEY_LEFT;
_glfw.ns.keycodes[0x3A] = GLFW_KEY_LEFT_ALT;
_glfw.ns.keycodes[0x3B] = GLFW_KEY_LEFT_CONTROL;
_glfw.ns.keycodes[0x38] = GLFW_KEY_LEFT_SHIFT;
_glfw.ns.keycodes[0x37] = GLFW_KEY_LEFT_SUPER;
_glfw.ns.keycodes[0x6E] = GLFW_KEY_MENU;
_glfw.ns.keycodes[0x47] = GLFW_KEY_NUM_LOCK;
_glfw.ns.keycodes[0x79] = GLFW_KEY_PAGE_DOWN;
_glfw.ns.keycodes[0x74] = GLFW_KEY_PAGE_UP;
_glfw.ns.keycodes[0x7C] = GLFW_KEY_RIGHT;
_glfw.ns.keycodes[0x3D] = GLFW_KEY_RIGHT_ALT;
_glfw.ns.keycodes[0x3E] = GLFW_KEY_RIGHT_CONTROL;
_glfw.ns.keycodes[0x3C] = GLFW_KEY_RIGHT_SHIFT;
_glfw.ns.keycodes[0x36] = GLFW_KEY_RIGHT_SUPER;
_glfw.ns.keycodes[0x31] = GLFW_KEY_SPACE;
_glfw.ns.keycodes[0x30] = GLFW_KEY_TAB;
_glfw.ns.keycodes[0x7E] = GLFW_KEY_UP;
_glfw.ns.publicKeys[0x52] = GLFW_KEY_KP_0;
_glfw.ns.publicKeys[0x53] = GLFW_KEY_KP_1;
_glfw.ns.publicKeys[0x54] = GLFW_KEY_KP_2;
_glfw.ns.publicKeys[0x55] = GLFW_KEY_KP_3;
_glfw.ns.publicKeys[0x56] = GLFW_KEY_KP_4;
_glfw.ns.publicKeys[0x57] = GLFW_KEY_KP_5;
_glfw.ns.publicKeys[0x58] = GLFW_KEY_KP_6;
_glfw.ns.publicKeys[0x59] = GLFW_KEY_KP_7;
_glfw.ns.publicKeys[0x5B] = GLFW_KEY_KP_8;
_glfw.ns.publicKeys[0x5C] = GLFW_KEY_KP_9;
_glfw.ns.publicKeys[0x45] = GLFW_KEY_KP_ADD;
_glfw.ns.publicKeys[0x41] = GLFW_KEY_KP_DECIMAL;
_glfw.ns.publicKeys[0x4B] = GLFW_KEY_KP_DIVIDE;
_glfw.ns.publicKeys[0x4C] = GLFW_KEY_KP_ENTER;
_glfw.ns.publicKeys[0x51] = GLFW_KEY_KP_EQUAL;
_glfw.ns.publicKeys[0x43] = GLFW_KEY_KP_MULTIPLY;
_glfw.ns.publicKeys[0x4E] = GLFW_KEY_KP_SUBTRACT;
_glfw.ns.keycodes[0x52] = GLFW_KEY_KP_0;
_glfw.ns.keycodes[0x53] = GLFW_KEY_KP_1;
_glfw.ns.keycodes[0x54] = GLFW_KEY_KP_2;
_glfw.ns.keycodes[0x55] = GLFW_KEY_KP_3;
_glfw.ns.keycodes[0x56] = GLFW_KEY_KP_4;
_glfw.ns.keycodes[0x57] = GLFW_KEY_KP_5;
_glfw.ns.keycodes[0x58] = GLFW_KEY_KP_6;
_glfw.ns.keycodes[0x59] = GLFW_KEY_KP_7;
_glfw.ns.keycodes[0x5B] = GLFW_KEY_KP_8;
_glfw.ns.keycodes[0x5C] = GLFW_KEY_KP_9;
_glfw.ns.keycodes[0x45] = GLFW_KEY_KP_ADD;
_glfw.ns.keycodes[0x41] = GLFW_KEY_KP_DECIMAL;
_glfw.ns.keycodes[0x4B] = GLFW_KEY_KP_DIVIDE;
_glfw.ns.keycodes[0x4C] = GLFW_KEY_KP_ENTER;
_glfw.ns.keycodes[0x51] = GLFW_KEY_KP_EQUAL;
_glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY;
_glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT;
for (scancode = 0; scancode < 256; scancode++)
{
// Store the reverse translation for faster key name lookup
if (_glfw.ns.publicKeys[scancode] >= 0)
_glfw.ns.nativeKeys[_glfw.ns.publicKeys[scancode]] = scancode;
if (_glfw.ns.keycodes[scancode] >= 0)
_glfw.ns.scancodes[_glfw.ns.keycodes[scancode]] = scancode;
}
}
@@ -247,9 +243,6 @@ static GLFWbool initializeTIS(void)
CFStringRef* kPropertyUnicodeKeyLayoutData =
CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
CFSTR("kTISPropertyUnicodeKeyLayoutData"));
CFStringRef* kNotifySelectedKeyboardInputSourceChanged =
CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
CFSTR("kTISNotifySelectedKeyboardInputSourceChanged"));
_glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource =
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
@@ -261,7 +254,6 @@ static GLFWbool initializeTIS(void)
CFSTR("LMGetKbdType"));
if (!kPropertyUnicodeKeyLayoutData ||
!kNotifySelectedKeyboardInputSourceChanged ||
!TISCopyCurrentKeyboardLayoutInputSource ||
!TISGetInputSourceProperty ||
!LMGetKbdType)
@@ -273,8 +265,6 @@ static GLFWbool initializeTIS(void)
_glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
*kPropertyUnicodeKeyLayoutData;
_glfw.ns.tis.kNotifySelectedKeyboardInputSourceChanged =
*kNotifySelectedKeyboardInputSourceChanged;
return updateUnicodeDataNS();
}
@@ -300,17 +290,16 @@ int _glfwPlatformInit(void)
{
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
if (_glfw.hints.init.ns.chdir)
changeToResourcesDirectory();
_glfw.ns.listener = [[GLFWLayoutListener alloc] init];
[[NSDistributedNotificationCenter defaultCenter]
[[NSNotificationCenter defaultCenter]
addObserver:_glfw.ns.listener
selector:@selector(selectedKeyboardInputSourceChanged:)
name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged
name:NSTextInputContextKeyboardSelectionDidChangeNotification
object:nil];
#if defined(_GLFW_USE_CHDIR)
changeToResourcesDirectory();
#endif
createKeyTables();
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
@@ -322,15 +311,10 @@ int _glfwPlatformInit(void)
if (!initializeTIS())
return GLFW_FALSE;
if (!_glfwInitThreadLocalStoragePOSIX())
return GLFW_FALSE;
if (!_glfwInitNSGL())
return GLFW_FALSE;
_glfwInitTimerNS();
_glfwInitJoysticksNS();
_glfwPollMonitorsNS();
return GLFW_TRUE;
}
@@ -358,10 +342,12 @@ void _glfwPlatformTerminate(void)
if (_glfw.ns.listener)
{
[[NSDistributedNotificationCenter defaultCenter]
[[NSNotificationCenter defaultCenter]
removeObserver:_glfw.ns.listener
name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged
name:NSTextInputContextKeyboardSelectionDidChangeNotification
object:nil];
[[NSNotificationCenter defaultCenter]
removeObserver:_glfw.ns.listener];
[_glfw.ns.listener release];
_glfw.ns.listener = nil;
}
@@ -373,7 +359,6 @@ void _glfwPlatformTerminate(void)
_glfwTerminateNSGL();
_glfwTerminateJoysticksNS();
_glfwTerminateThreadLocalStoragePOSIX();
[_glfw.ns.autoreleasePool release];
_glfw.ns.autoreleasePool = nil;
@@ -382,15 +367,6 @@ void _glfwPlatformTerminate(void)
const char* _glfwPlatformGetVersionString(void)
{
return _GLFW_VERSION_NUMBER " Cocoa NSGL"
#if defined(_GLFW_USE_CHDIR)
" chdir"
#endif
#if defined(_GLFW_USE_MENUBAR)
" menubar"
#endif
#if defined(_GLFW_USE_RETINA)
" retina"
#endif
#if defined(_GLFW_BUILD_DLL)
" dynamic"
#endif
+10 -27
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 Cocoa - www.glfw.org
// GLFW 3.3 Cocoa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -24,44 +24,27 @@
//
//========================================================================
#ifndef _glfw3_cocoa_joystick_h_
#define _glfw3_cocoa_joystick_h_
#include <IOKit/IOKitLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/hid/IOHIDLib.h>
#include <IOKit/hid/IOHIDKeys.h>
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWjoystickNS ns_js
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickNS ns
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
#define _GLFW_PLATFORM_MAPPING_NAME "Mac OS X"
// Cocoa-specific per-joystick data
//
typedef struct _GLFWjoydeviceNS
{
GLFWbool present;
char name[256];
IOHIDDeviceRef deviceRef;
CFMutableArrayRef axisElements;
CFMutableArrayRef buttonElements;
CFMutableArrayRef hatElements;
float* axes;
unsigned char* buttons;
} _GLFWjoydeviceNS;
// Cocoa-specific joystick API data
//
typedef struct _GLFWjoystickNS
{
_GLFWjoydeviceNS js[GLFW_JOYSTICK_LAST + 1];
IOHIDManagerRef managerRef;
IOHIDDeviceRef device;
CFMutableArrayRef axes;
CFMutableArrayRef buttons;
CFMutableArrayRef hats;
} _GLFWjoystickNS;
void _glfwInitJoysticksNS(void);
void _glfwTerminateJoysticksNS(void);
#endif // _glfw3_cocoa_joystick_h_
+321 -373
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 Cocoa - www.glfw.org
// GLFW 3.3 Cocoa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
//
// This software is provided 'as-is', without any express or implied
@@ -42,42 +42,164 @@
//
typedef struct _GLFWjoyelementNS
{
IOHIDElementRef elementRef;
long min;
long max;
long minReport;
long maxReport;
IOHIDElementRef native;
uint32_t usage;
int index;
long minimum;
long maximum;
} _GLFWjoyelementNS;
static void getElementsCFArrayHandler(const void* value, void* parameter);
// Adds an element to the specified joystick
// Returns the value of the specified element of the specified joystick
//
static void addJoystickElement(_GLFWjoydeviceNS* js,
IOHIDElementRef elementRef)
static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
{
IOHIDElementType elementType;
long usagePage, usage;
CFMutableArrayRef elementsArray = NULL;
IOHIDValueRef valueRef;
long value = 0;
elementType = IOHIDElementGetType(elementRef);
usagePage = IOHIDElementGetUsagePage(elementRef);
usage = IOHIDElementGetUsage(elementRef);
if ((elementType != kIOHIDElementTypeInput_Axis) &&
(elementType != kIOHIDElementTypeInput_Button) &&
(elementType != kIOHIDElementTypeInput_Misc))
if (js->ns.device)
{
return;
if (IOHIDDeviceGetValue(js->ns.device,
element->native,
&valueRef) == kIOReturnSuccess)
{
value = IOHIDValueGetIntegerValue(valueRef);
}
}
switch (usagePage)
return value;
}
// Comparison function for matching the SDL element order
//
static CFComparisonResult compareElements(const void* fp, const void* sp, void* user)
{
const _GLFWjoyelementNS* fe = fp;
const _GLFWjoyelementNS* se = sp;
if (fe->usage < se->usage)
return kCFCompareLessThan;
if (fe->usage > se->usage)
return kCFCompareGreaterThan;
if (fe->index < se->index)
return kCFCompareLessThan;
if (fe->index > se->index)
return kCFCompareGreaterThan;
return kCFCompareEqualTo;
}
// Removes the specified joystick
//
static void closeJoystick(_GLFWjoystick* js)
{
int i;
if (!js->present)
return;
for (i = 0; i < CFArrayGetCount(js->ns.axes); i++)
free((void*) CFArrayGetValueAtIndex(js->ns.axes, i));
CFRelease(js->ns.axes);
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
free((void*) CFArrayGetValueAtIndex(js->ns.buttons, i));
CFRelease(js->ns.buttons);
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
free((void*) CFArrayGetValueAtIndex(js->ns.hats, i));
CFRelease(js->ns.hats);
_glfwFreeJoystick(js);
_glfwInputJoystick(js, GLFW_DISCONNECTED);
}
// Callback for user-initiated joystick addition
//
static void matchCallback(void* context,
IOReturn result,
void* sender,
IOHIDDeviceRef device)
{
int jid;
char name[256];
char guid[33];
CFIndex i;
CFTypeRef property;
uint32_t vendor = 0, product = 0, version = 0;
_GLFWjoystick* js;
CFMutableArrayRef axes, buttons, hats;
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
case kHIDPage_GenericDesktop:
if (_glfw.joysticks[jid].ns.device == device)
return;
}
axes = CFArrayCreateMutable(NULL, 0, NULL);
buttons = CFArrayCreateMutable(NULL, 0, NULL);
hats = CFArrayCreateMutable(NULL, 0, NULL);
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
if (property)
{
CFStringGetCString(property,
name,
sizeof(name),
kCFStringEncodingUTF8);
}
else
strncpy(name, "Unknown", sizeof(name));
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey));
if (property)
CFNumberGetValue(property, kCFNumberSInt32Type, &vendor);
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey));
if (property)
CFNumberGetValue(property, kCFNumberSInt32Type, &product);
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVersionNumberKey));
if (property)
CFNumberGetValue(property, kCFNumberSInt32Type, &version);
// Generate a joystick GUID that matches the SDL 2.0.5+ one
if (vendor && product)
{
sprintf(guid, "03000000%02x%02x0000%02x%02x0000%02x%02x0000",
(uint8_t) vendor, (uint8_t) (vendor >> 8),
(uint8_t) product, (uint8_t) (product >> 8),
(uint8_t) version, (uint8_t) (version >> 8));
}
else
{
sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
name[0], name[1], name[2], name[3],
name[4], name[5], name[6], name[7],
name[8], name[9], name[10]);
}
CFArrayRef elements =
IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
for (i = 0; i < CFArrayGetCount(elements); i++)
{
IOHIDElementRef native = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i);
if (CFGetTypeID(native) != IOHIDElementGetTypeID())
continue;
const IOHIDElementType type = IOHIDElementGetType(native);
if ((type != kIOHIDElementTypeInput_Axis) &&
(type != kIOHIDElementTypeInput_Button) &&
(type != kIOHIDElementTypeInput_Misc))
{
continue;
}
CFMutableArrayRef target = NULL;
const uint32_t usage = IOHIDElementGetUsage(native);
const uint32_t page = IOHIDElementGetUsagePage(native);
if (page == kHIDPage_GenericDesktop)
{
switch (usage)
{
@@ -90,241 +212,48 @@ static void addJoystickElement(_GLFWjoydeviceNS* js,
case kHIDUsage_GD_Slider:
case kHIDUsage_GD_Dial:
case kHIDUsage_GD_Wheel:
elementsArray = js->axisElements;
target = axes;
break;
case kHIDUsage_GD_Hatswitch:
elementsArray = js->hatElements;
target = hats;
break;
}
break;
}
else if (page == kHIDPage_Button)
target = buttons;
case kHIDPage_Button:
elementsArray = js->buttonElements;
break;
default:
break;
}
if (elementsArray)
{
_GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
CFArrayAppendValue(elementsArray, element);
element->elementRef = elementRef;
element->minReport = IOHIDElementGetLogicalMin(elementRef);
element->maxReport = IOHIDElementGetLogicalMax(elementRef);
}
}
// Adds an element to the specified joystick
//
static void getElementsCFArrayHandler(const void* value, void* parameter)
{
if (CFGetTypeID(value) == IOHIDElementGetTypeID())
{
addJoystickElement((_GLFWjoydeviceNS*) parameter,
(IOHIDElementRef) value);
}
}
// Returns the value of the specified element of the specified joystick
//
static long getElementValue(_GLFWjoydeviceNS* js, _GLFWjoyelementNS* element)
{
IOReturn result = kIOReturnSuccess;
IOHIDValueRef valueRef;
long value = 0;
if (js && element && js->deviceRef)
{
result = IOHIDDeviceGetValue(js->deviceRef,
element->elementRef,
&valueRef);
if (kIOReturnSuccess == result)
if (target)
{
value = IOHIDValueGetIntegerValue(valueRef);
// Record min and max for auto calibration
if (value < element->minReport)
element->minReport = value;
if (value > element->maxReport)
element->maxReport = value;
_GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
element->native = native;
element->usage = usage;
element->index = (int) CFArrayGetCount(target);
element->minimum = IOHIDElementGetLogicalMin(native);
element->maximum = IOHIDElementGetLogicalMax(native);
CFArrayAppendValue(target, element);
}
}
// Auto user scale
return value;
}
CFRelease(elements);
// Removes the specified joystick
//
static void removeJoystick(_GLFWjoydeviceNS* js)
{
int i;
CFArraySortValues(axes, CFRangeMake(0, CFArrayGetCount(axes)),
compareElements, NULL);
CFArraySortValues(buttons, CFRangeMake(0, CFArrayGetCount(buttons)),
compareElements, NULL);
CFArraySortValues(hats, CFRangeMake(0, CFArrayGetCount(hats)),
compareElements, NULL);
if (!js->present)
return;
js = _glfwAllocJoystick(name, guid,
CFArrayGetCount(axes),
CFArrayGetCount(buttons),
CFArrayGetCount(hats));
for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
free((void*) CFArrayGetValueAtIndex(js->axisElements, i));
CFArrayRemoveAllValues(js->axisElements);
CFRelease(js->axisElements);
js->ns.device = device;
js->ns.axes = axes;
js->ns.buttons = buttons;
js->ns.hats = hats;
for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
free((void*) CFArrayGetValueAtIndex(js->buttonElements, i));
CFArrayRemoveAllValues(js->buttonElements);
CFRelease(js->buttonElements);
for (i = 0; i < CFArrayGetCount(js->hatElements); i++)
free((void*) CFArrayGetValueAtIndex(js->hatElements, i));
CFArrayRemoveAllValues(js->hatElements);
CFRelease(js->hatElements);
free(js->axes);
free(js->buttons);
memset(js, 0, sizeof(_GLFWjoydeviceNS));
_glfwInputJoystickChange(js - _glfw.ns_js.js, GLFW_DISCONNECTED);
}
// Polls for joystick axis events and updates GLFW state
//
static GLFWbool pollJoystickAxisEvents(_GLFWjoydeviceNS* js)
{
CFIndex i;
if (!js->present)
return GLFW_FALSE;
for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
{
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(js->axisElements, i);
long value = getElementValue(js, axis);
long readScale = axis->maxReport - axis->minReport;
if (readScale == 0)
js->axes[i] = value;
else
js->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;
}
return GLFW_TRUE;
}
// Polls for joystick button events and updates GLFW state
//
static GLFWbool pollJoystickButtonEvents(_GLFWjoydeviceNS* js)
{
CFIndex i;
int buttonIndex = 0;
if (!js->present)
return GLFW_FALSE;
for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
{
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(js->buttonElements, i);
if (getElementValue(js, button))
js->buttons[buttonIndex++] = GLFW_PRESS;
else
js->buttons[buttonIndex++] = GLFW_RELEASE;
}
for (i = 0; i < CFArrayGetCount(js->hatElements); i++)
{
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(js->hatElements, i);
// Bit fields of button presses for each direction, including nil
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
long j, value = getElementValue(js, hat);
if (value < 0 || value > 8)
value = 8;
for (j = 0; j < 4; j++)
{
if (directions[value] & (1 << j))
js->buttons[buttonIndex++] = GLFW_PRESS;
else
js->buttons[buttonIndex++] = GLFW_RELEASE;
}
}
return GLFW_TRUE;
}
// Callback for user-initiated joystick addition
//
static void matchCallback(void* context,
IOReturn result,
void* sender,
IOHIDDeviceRef deviceRef)
{
_GLFWjoydeviceNS* js;
int joy;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
if (_glfw.ns_js.js[joy].present && _glfw.ns_js.js[joy].deviceRef == deviceRef)
return;
}
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
if (!_glfw.ns_js.js[joy].present)
break;
}
if (joy > GLFW_JOYSTICK_LAST)
return;
js = _glfw.ns_js.js + joy;
js->present = GLFW_TRUE;
js->deviceRef = deviceRef;
CFStringRef name = IOHIDDeviceGetProperty(deviceRef,
CFSTR(kIOHIDProductKey));
if (name)
{
CFStringGetCString(name,
js->name,
sizeof(js->name),
kCFStringEncodingUTF8);
}
else
strncpy(js->name, "Unknown", sizeof(js->name));
js->axisElements = CFArrayCreateMutable(NULL, 0, NULL);
js->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);
js->hatElements = CFArrayCreateMutable(NULL, 0, NULL);
CFArrayRef arrayRef = IOHIDDeviceCopyMatchingElements(deviceRef,
NULL,
kIOHIDOptionsTypeNone);
CFRange range = { 0, CFArrayGetCount(arrayRef) };
CFArrayApplyFunction(arrayRef,
range,
getElementsCFArrayHandler,
(void*) js);
CFRelease(arrayRef);
js->axes = calloc(CFArrayGetCount(js->axisElements), sizeof(float));
js->buttons = calloc(CFArrayGetCount(js->buttonElements) +
CFArrayGetCount(js->hatElements) * 4, 1);
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
_glfwInputJoystick(js, GLFW_CONNECTED);
}
// Callback for user-initiated joystick removal
@@ -332,60 +261,20 @@ static void matchCallback(void* context,
static void removeCallback(void* context,
IOReturn result,
void* sender,
IOHIDDeviceRef deviceRef)
IOHIDDeviceRef device)
{
int joy;
int jid;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (_glfw.ns_js.js[joy].deviceRef == deviceRef)
if (_glfw.joysticks[jid].ns.device == device)
{
removeJoystick(_glfw.ns_js.js + joy);
closeJoystick(_glfw.joysticks + jid);
break;
}
}
}
// Creates a dictionary to match against devices with the specified usage page
// and usage
//
static CFMutableDictionaryRef createMatchingDictionary(long usagePage,
long usage)
{
CFMutableDictionaryRef result =
CFDictionaryCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (result)
{
CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
kCFNumberLongType,
&usagePage);
if (pageRef)
{
CFDictionarySetValue(result,
CFSTR(kIOHIDDeviceUsagePageKey),
pageRef);
CFRelease(pageRef);
CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
kCFNumberLongType,
&usage);
if (usageRef)
{
CFDictionarySetValue(result,
CFSTR(kIOHIDDeviceUsageKey),
usageRef);
CFRelease(usageRef);
}
}
}
return result;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
@@ -395,57 +284,74 @@ static CFMutableDictionaryRef createMatchingDictionary(long usagePage,
//
void _glfwInitJoysticksNS(void)
{
CFMutableArrayRef matchingCFArrayRef;
_glfw.ns_js.managerRef = IOHIDManagerCreate(kCFAllocatorDefault,
kIOHIDOptionsTypeNone);
matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
if (matchingCFArrayRef)
CFMutableArrayRef matching;
const long usages[] =
{
CFDictionaryRef matchingCFDictRef =
createMatchingDictionary(kHIDPage_GenericDesktop,
kHIDUsage_GD_Joystick);
if (matchingCFDictRef)
{
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
CFRelease(matchingCFDictRef);
}
kHIDUsage_GD_Joystick,
kHIDUsage_GD_GamePad,
kHIDUsage_GD_MultiAxisController
};
matchingCFDictRef = createMatchingDictionary(kHIDPage_GenericDesktop,
kHIDUsage_GD_GamePad);
if (matchingCFDictRef)
{
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
CFRelease(matchingCFDictRef);
}
_glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
kIOHIDOptionsTypeNone);
matchingCFDictRef =
createMatchingDictionary(kHIDPage_GenericDesktop,
kHIDUsage_GD_MultiAxisController);
if (matchingCFDictRef)
{
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
CFRelease(matchingCFDictRef);
}
IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns_js.managerRef,
matchingCFArrayRef);
CFRelease(matchingCFArrayRef);
matching = CFArrayCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
if (!matching)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create array");
return;
}
IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns_js.managerRef,
&matchCallback, NULL);
IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns_js.managerRef,
&removeCallback, NULL);
for (int i = 0; i < sizeof(usages) / sizeof(long); i++)
{
const long page = kHIDPage_GenericDesktop;
IOHIDManagerScheduleWithRunLoop(_glfw.ns_js.managerRef,
CFMutableDictionaryRef dict =
CFDictionaryCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (!dict)
continue;
CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
kCFNumberLongType,
&page);
CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
kCFNumberLongType,
&usages[i]);
if (pageRef && usageRef)
{
CFDictionarySetValue(dict,
CFSTR(kIOHIDDeviceUsagePageKey),
pageRef);
CFDictionarySetValue(dict,
CFSTR(kIOHIDDeviceUsageKey),
usageRef);
CFArrayAppendValue(matching, dict);
}
if (pageRef)
CFRelease(pageRef);
if (usageRef)
CFRelease(usageRef);
CFRelease(dict);
}
IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager, matching);
CFRelease(matching);
IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns.hidManager,
&matchCallback, NULL);
IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns.hidManager,
&removeCallback, NULL);
IOHIDManagerScheduleWithRunLoop(_glfw.ns.hidManager,
CFRunLoopGetMain(),
kCFRunLoopDefaultMode);
IOHIDManagerOpen(_glfw.ns_js.managerRef, kIOHIDOptionsTypeNone);
IOHIDManagerOpen(_glfw.ns.hidManager, kIOHIDOptionsTypeNone);
// Execute the run loop once in order to register any initially-attached
// joysticks
@@ -456,16 +362,13 @@ void _glfwInitJoysticksNS(void)
//
void _glfwTerminateJoysticksNS(void)
{
int joy;
int jid;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
_GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
removeJoystick(js);
}
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
closeJoystick(_glfw.joysticks + jid);
CFRelease(_glfw.ns_js.managerRef);
_glfw.ns_js.managerRef = NULL;
CFRelease(_glfw.ns.hidManager);
_glfw.ns.hidManager = NULL;
}
@@ -473,39 +376,84 @@ void _glfwTerminateJoysticksNS(void)
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformJoystickPresent(int joy)
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
{
_GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
if (mode & _GLFW_POLL_AXES)
{
CFIndex i;
for (i = 0; i < CFArrayGetCount(js->ns.axes); i++)
{
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(js->ns.axes, i);
const long raw = getElementValue(js, axis);
// Perform auto calibration
if (raw < axis->minimum)
axis->minimum = raw;
if (raw > axis->maximum)
axis->maximum = raw;
const long delta = axis->maximum - axis->minimum;
if (delta == 0)
_glfwInputJoystickAxis(js, i, 0.f);
else
{
const float value = (2.f * (raw - axis->minimum) / delta) - 1.f;
_glfwInputJoystickAxis(js, i, value);
}
}
}
if (mode & _GLFW_POLL_BUTTONS)
{
CFIndex i;
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
{
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(js->ns.buttons, i);
const char value = getElementValue(js, button) - button->minimum;
_glfwInputJoystickButton(js, i, value);
}
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
{
const int states[9] =
{
GLFW_HAT_UP,
GLFW_HAT_RIGHT_UP,
GLFW_HAT_RIGHT,
GLFW_HAT_RIGHT_DOWN,
GLFW_HAT_DOWN,
GLFW_HAT_LEFT_DOWN,
GLFW_HAT_LEFT,
GLFW_HAT_LEFT_UP,
GLFW_HAT_CENTERED
};
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(js->ns.hats, i);
long state = getElementValue(js, hat) - hat->minimum;
if (state < 0 || state > 8)
state = 8;
_glfwInputJoystickHat(js, i, states[state]);
}
}
return js->present;
}
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
void _glfwPlatformUpdateGamepadGUID(char* guid)
{
_GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
if (!pollJoystickAxisEvents(js))
return NULL;
*count = (int) CFArrayGetCount(js->axisElements);
return js->axes;
}
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
{
_GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
if (!pollJoystickButtonEvents(js))
return NULL;
*count = (int) CFArrayGetCount(js->buttonElements) +
(int) CFArrayGetCount(js->hatElements) * 4;
return js->buttons;
}
const char* _glfwPlatformGetJoystickName(int joy)
{
_GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
if (!js->present)
return NULL;
return js->name;
if ((strncmp(guid + 4, "000000000000", 12) == 0) &&
(strncmp(guid + 20, "000000000000", 12) == 0))
{
char original[33];
strcpy(original, guid);
sprintf(guid, "03000000%.4s0000%.4s000000000000",
original, original + 16);
}
}
+137 -77
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 OS X - www.glfw.org
// GLFW 3.3 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -27,50 +27,88 @@
#include "internal.h"
#include <stdlib.h>
#include <stdlib.h>
#include <limits.h>
#include <IOKit/graphics/IOGraphicsLib.h>
#include <IOKit/graphics/IOGraphicsLib.h>
#include <CoreVideo/CVBase.h>
#include <CoreVideo/CVDisplayLink.h>
#include <ApplicationServices/ApplicationServices.h>
// Get the name of the specified display
// Get the name of the specified display, or NULL
//
static char* getDisplayName(CGDirectDisplayID displayID)
{
char* name;
CFDictionaryRef info, names;
CFStringRef value;
CFIndex size;
io_iterator_t it;
io_service_t service;
CFDictionaryRef info;
// NOTE: This uses a deprecated function because Apple has
// (as of January 2015) not provided any alternative
info = IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID),
kIODisplayOnlyPreferredName);
names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"),
(const void**) &value))
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
IOServiceMatching("IODisplayConnect"),
&it) != 0)
{
// This may happen if a desktop Mac is running headless
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to retrieve display name");
CFRelease(info);
return strdup("Unknown");
return NULL;
}
size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value),
kCFStringEncodingUTF8);
name = calloc(size + 1, sizeof(char));
CFStringGetCString(value, name, size, kCFStringEncodingUTF8);
while ((service = IOIteratorNext(it)) != 0)
{
info = IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName);
CFNumberRef vendorIDRef =
CFDictionaryGetValue(info, CFSTR(kDisplayVendorID));
CFNumberRef productIDRef =
CFDictionaryGetValue(info, CFSTR(kDisplayProductID));
if (!vendorIDRef || !productIDRef)
{
CFRelease(info);
continue;
}
unsigned int vendorID, productID;
CFNumberGetValue(vendorIDRef, kCFNumberIntType, &vendorID);
CFNumberGetValue(productIDRef, kCFNumberIntType, &productID);
if (CGDisplayVendorNumber(displayID) == vendorID &&
CGDisplayModelNumber(displayID) == productID)
{
// Info dictionary is used and freed below
break;
}
CFRelease(info);
}
IOObjectRelease(it);
if (!service)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to find service port for display");
return NULL;
}
CFDictionaryRef names =
CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
CFStringRef nameRef;
if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"),
(const void**) &nameRef))
{
// This may happen if a desktop Mac is running headless
CFRelease(info);
return NULL;
}
const CFIndex size =
CFStringGetMaximumSizeForEncoding(CFStringGetLength(nameRef),
kCFStringEncodingUTF8);
char* name = calloc(size + 1, 1);
CFStringGetCString(nameRef, name, size, kCFStringEncodingUTF8);
CFRelease(info);
return name;
}
@@ -79,15 +117,15 @@ static char* getDisplayName(CGDirectDisplayID displayID)
static GLFWbool modeIsGood(CGDisplayModeRef mode)
{
uint32_t flags = CGDisplayModeGetIOFlags(mode);
if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag))
return GLFW_FALSE;
if (flags & kDisplayModeInterlacedFlag)
return GLFW_FALSE;
if (flags & kDisplayModeStretchedFlag)
return GLFW_FALSE;
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
@@ -97,6 +135,7 @@ static GLFWbool modeIsGood(CGDisplayModeRef mode)
}
CFRelease(format);
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
return GLFW_TRUE;
}
@@ -117,8 +156,8 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
result.refreshRate = (int) (time.timeScale / (double) time.timeValue);
}
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
{
result.redBits = 5;
@@ -126,13 +165,16 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
result.blueBits = 5;
}
else
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
{
result.redBits = 8;
result.greenBits = 8;
result.blueBits = 8;
}
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
CFRelease(format);
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
return result;
}
@@ -164,6 +206,71 @@ static void endFadeReservation(CGDisplayFadeReservationToken token)
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Poll for changes in the set of connected monitors
//
void _glfwPollMonitorsNS(void)
{
uint32_t i, j, displayCount, disconnectedCount;
CGDirectDisplayID* displays;
_GLFWmonitor** disconnected = NULL;
CGGetOnlineDisplayList(0, NULL, &displayCount);
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
disconnectedCount = _glfw.monitorCount;
if (disconnectedCount)
{
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
memcpy(disconnected,
_glfw.monitors,
_glfw.monitorCount * sizeof(_GLFWmonitor*));
}
for (i = 0; i < displayCount; i++)
{
_GLFWmonitor* monitor;
const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
if (CGDisplayIsAsleep(displays[i]))
continue;
for (j = 0; j < disconnectedCount; j++)
{
// HACK: Compare unit numbers instead of display IDs to work around
// display replacement on machines with automatic graphics
// switching
if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
{
disconnected[j] = NULL;
break;
}
}
const CGSize size = CGDisplayScreenSize(displays[i]);
char* name = getDisplayName(displays[i]);
if (!name)
name = strdup("Unknown");
monitor = _glfwAllocMonitor(name, size.width, size.height);
monitor->ns.displayID = displays[i];
monitor->ns.unitNumber = unitNumber;
free(name);
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
}
for (i = 0; i < disconnectedCount; i++)
{
if (disconnected[i])
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
}
free(disconnected);
free(displays);
}
// Change the current video mode
//
GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
@@ -243,53 +350,6 @@ void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor)
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
{
uint32_t i, found = 0, displayCount;
_GLFWmonitor** monitors;
CGDirectDisplayID* displays;
*count = 0;
CGGetOnlineDisplayList(0, NULL, &displayCount);
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
monitors = calloc(displayCount, sizeof(_GLFWmonitor*));
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
for (i = 0; i < displayCount; i++)
{
_GLFWmonitor* monitor;
if (CGDisplayIsAsleep(displays[i]))
continue;
const CGSize size = CGDisplayScreenSize(displays[i]);
char* name = getDisplayName(displays[i]);
monitor = _glfwAllocMonitor(name, size.width, size.height);
monitor->ns.displayID = displays[i];
monitor->ns.unitNumber = CGDisplayUnitNumber(displays[i]);
free(name);
found++;
monitors[found - 1] = monitor;
}
free(displays);
*count = found;
return monitors;
}
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
{
// HACK: Compare unit numbers instead of display IDs to work around display
// replacement on machines with automatic graphics switching
return first->ns.unitNumber == second->ns.unitNumber;
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{
const CGRect bounds = CGDisplayBounds(monitor->ns.displayID);
+31 -21
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 OS X - www.glfw.org
// GLFW 3.3 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -24,9 +24,6 @@
//
//========================================================================
#ifndef _glfw3_cocoa_platform_h_
#define _glfw3_cocoa_platform_h_
#include <stdint.h>
#include <dlfcn.h>
@@ -39,26 +36,39 @@
typedef void* id;
#endif
#include "posix_tls.h"
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
typedef struct VkMacOSSurfaceCreateInfoMVK
{
VkStructureType sType;
const void* pNext;
VkMacOSSurfaceCreateFlagsMVK flags;
const void* pView;
} VkMacOSSurfaceCreateInfoMVK;
typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
#include "posix_thread.h"
#include "cocoa_joystick.h"
#include "nsgl_context.h"
#include "egl_context.h"
#include "osmesa_context.h"
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
#define _glfw_dlsym(handle, name) dlsym(handle, name)
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->ns.view)
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeNS ns_time
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerNS ns
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns
#define _GLFW_EGL_CONTEXT_STATE
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
// HIToolbox.framework pointer typedefs
#define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData
#define kTISNotifySelectedKeyboardInputSourceChanged _glfw.ns.tis.kNotifySelectedKeyboardInputSourceChanged
typedef TISInputSourceRef (*PFN_TISCopyCurrentKeyboardLayoutInputSource)(void);
#define TISCopyCurrentKeyboardLayoutInputSource _glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource
typedef void* (*PFN_TISGetInputSourceProperty)(TISInputSourceRef,CFStringRef);
@@ -74,6 +84,9 @@ typedef struct _GLFWwindowNS
id object;
id delegate;
id view;
id layer;
GLFWbool maximized;
// The total sum of the distances the cursor has been warped
// since the last cursor motion event was processed
@@ -82,7 +95,6 @@ typedef struct _GLFWwindowNS
} _GLFWwindowNS;
// Cocoa-specific global data
//
typedef struct _GLFWlibraryNS
@@ -92,13 +104,15 @@ typedef struct _GLFWlibraryNS
id autoreleasePool;
id cursor;
TISInputSourceRef inputSource;
IOHIDManagerRef hidManager;
id unicodeData;
id listener;
char keyName[64];
short int publicKeys[256];
short int nativeKeys[GLFW_KEY_LAST + 1];
short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1];
char* clipboardString;
CGPoint cascadePoint;
// Where to place the cursor when re-enabled
double restoreCursorPosX, restoreCursorPosY;
// The window whose disabled cursor mode is active
@@ -110,12 +124,10 @@ typedef struct _GLFWlibraryNS
PFN_TISGetInputSourceProperty GetInputSourceProperty;
PFN_LMGetKbdType GetKbdType;
CFStringRef kPropertyUnicodeKeyLayoutData;
CFStringRef kNotifySelectedKeyboardInputSourceChanged;
} tis;
} _GLFWlibraryNS;
// Cocoa-specific per-monitor data
//
typedef struct _GLFWmonitorNS
@@ -126,7 +138,6 @@ typedef struct _GLFWmonitorNS
} _GLFWmonitorNS;
// Cocoa-specific per-cursor data
//
typedef struct _GLFWcursorNS
@@ -135,19 +146,18 @@ typedef struct _GLFWcursorNS
} _GLFWcursorNS;
// Cocoa-specific global timer data
//
typedef struct _GLFWtimeNS
typedef struct _GLFWtimerNS
{
uint64_t frequency;
} _GLFWtimeNS;
} _GLFWtimerNS;
void _glfwInitTimerNS(void);
void _glfwPollMonitorsNS(void);
GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
#endif // _glfw3_cocoa_platform_h_
+4 -4
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 OS X - www.glfw.org
// GLFW 3.3 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -40,7 +40,7 @@ void _glfwInitTimerNS(void)
mach_timebase_info_data_t info;
mach_timebase_info(&info);
_glfw.ns_time.frequency = (info.denom * 1e9) / info.numer;
_glfw.timer.ns.frequency = (info.denom * 1e9) / info.numer;
}
@@ -55,6 +55,6 @@ uint64_t _glfwPlatformGetTimerValue(void)
uint64_t _glfwPlatformGetTimerFrequency(void)
{
return _glfw.ns_time.frequency;
return _glfw.timer.ns.frequency;
}
+279 -117
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 OS X - www.glfw.org
// GLFW 3.3 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -32,29 +32,23 @@
// Needed for _NSGetProgname
#include <crt_externs.h>
// HACK: The 10.12 SDK adds new symbols and immediately deprecates the old ones
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
#define NSWindowStyleMaskBorderless NSBorderlessWindowMask
#define NSWindowStyleMaskClosable NSClosableWindowMask
#define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask
#define NSWindowStyleMaskResizable NSResizableWindowMask
#define NSWindowStyleMaskTitled NSTitledWindowMask
#define NSEventModifierFlagCommand NSCommandKeyMask
#define NSEventModifierFlagControl NSControlKeyMask
#define NSEventModifierFlagOption NSAlternateKeyMask
#define NSEventModifierFlagShift NSShiftKeyMask
#define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
#define NSEventMaskAny NSAnyEventMask
#define NSEventTypeApplicationDefined NSApplicationDefined
#define NSEventTypeKeyUp NSKeyUp
#endif
// Returns the specified standard cursor
//
static NSCursor* getStandardCursor(int shape)
{
switch (shape)
{
case GLFW_ARROW_CURSOR:
return [NSCursor arrowCursor];
case GLFW_IBEAM_CURSOR:
return [NSCursor IBeamCursor];
case GLFW_CROSSHAIR_CURSOR:
return [NSCursor crosshairCursor];
case GLFW_HAND_CURSOR:
return [NSCursor pointingHandCursor];
case GLFW_HRESIZE_CURSOR:
return [NSCursor resizeLeftRightCursor];
case GLFW_VRESIZE_CURSOR:
return [NSCursor resizeUpDownCursor];
}
return nil;
}
// Returns the style mask corresponding to the window settings
//
@@ -63,14 +57,15 @@ static NSUInteger getStyleMask(_GLFWwindow* window)
NSUInteger styleMask = 0;
if (window->monitor || !window->decorated)
styleMask |= NSBorderlessWindowMask;
styleMask |= NSWindowStyleMaskBorderless;
else
{
styleMask |= NSTitledWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask;
styleMask |= NSWindowStyleMaskTitled |
NSWindowStyleMaskClosable |
NSWindowStyleMaskMiniaturizable;
if (window->resizable)
styleMask |= NSResizableWindowMask;
styleMask |= NSWindowStyleMaskResizable;
}
return styleMask;
@@ -129,7 +124,7 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
[window->ns.object setFrame:frame display:YES];
_glfwInputMonitorWindowChange(window->monitor, window);
_glfwInputMonitorWindow(window->monitor, window);
return status;
}
@@ -140,36 +135,36 @@ static void releaseMonitor(_GLFWwindow* window)
if (window->monitor->window != window)
return;
_glfwInputMonitorWindowChange(window->monitor, NULL);
_glfwInputMonitorWindow(window->monitor, NULL);
_glfwRestoreVideoModeNS(window->monitor);
}
// Translates OS X key modifiers into GLFW ones
// Translates macOS key modifiers into GLFW ones
//
static int translateFlags(NSUInteger flags)
{
int mods = 0;
if (flags & NSShiftKeyMask)
if (flags & NSEventModifierFlagShift)
mods |= GLFW_MOD_SHIFT;
if (flags & NSControlKeyMask)
if (flags & NSEventModifierFlagControl)
mods |= GLFW_MOD_CONTROL;
if (flags & NSAlternateKeyMask)
if (flags & NSEventModifierFlagOption)
mods |= GLFW_MOD_ALT;
if (flags & NSCommandKeyMask)
if (flags & NSEventModifierFlagCommand)
mods |= GLFW_MOD_SUPER;
return mods;
}
// Translates a OS X keycode to a GLFW keycode
// Translates a macOS keycode to a GLFW keycode
//
static int translateKey(unsigned int key)
{
if (key >= sizeof(_glfw.ns.publicKeys) / sizeof(_glfw.ns.publicKeys[0]))
if (key >= sizeof(_glfw.ns.keycodes) / sizeof(_glfw.ns.keycodes[0]))
return GLFW_KEY_UNKNOWN;
return _glfw.ns.publicKeys[key];
return _glfw.ns.keycodes[key];
}
// Translate a GLFW keycode to a Cocoa modifier flag
@@ -180,16 +175,16 @@ static NSUInteger translateKeyToModifierFlag(int key)
{
case GLFW_KEY_LEFT_SHIFT:
case GLFW_KEY_RIGHT_SHIFT:
return NSShiftKeyMask;
return NSEventModifierFlagShift;
case GLFW_KEY_LEFT_CONTROL:
case GLFW_KEY_RIGHT_CONTROL:
return NSControlKeyMask;
return NSEventModifierFlagControl;
case GLFW_KEY_LEFT_ALT:
case GLFW_KEY_RIGHT_ALT:
return NSAlternateKeyMask;
return NSEventModifierFlagOption;
case GLFW_KEY_LEFT_SUPER:
case GLFW_KEY_RIGHT_SUPER:
return NSCommandKeyMask;
return NSEventModifierFlagCommand;
}
return 0;
@@ -238,6 +233,13 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
if (_glfw.ns.disabledCursorWindow == window)
centerCursor(window);
const int maximized = [window->ns.object isZoomed];
if (window->ns.maximized != maximized)
{
window->ns.maximized = maximized;
_glfwInputWindowMaximize(window, maximized);
}
const NSRect contentRect = [window->ns.view frame];
const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
@@ -315,7 +317,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
{
_glfwInputMonitorChange();
_GLFWwindow* window;
for (window = _glfw.windowListHead; window; window = window->next)
{
if (window->context.client != GLFW_NO_API)
[window->context.nsgl.object update];
}
_glfwPollMonitorsNS();
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification
@@ -406,6 +416,19 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
return YES;
}
- (BOOL)wantsUpdateLayer
{
return YES;
}
- (id)makeBackingLayer
{
if (window->ns.layer)
return window->ns.layer;
return [super makeBackingLayer];
}
- (void)cursorUpdate:(NSEvent *)event
{
updateCursorImage(window);
@@ -558,7 +581,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
{
int action;
const unsigned int modifierFlags =
[event modifierFlags] & NSDeviceIndependentModifierFlagsMask;
[event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
const int key = translateKey([event keyCode]);
const int mods = translateFlags(modifierFlags);
const NSUInteger keyFlag = translateKeyToModifierFlag(key);
@@ -753,7 +776,12 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (BOOL)canBecomeKeyWindow
{
// Required for NSBorderlessWindowMask windows
// Required for NSWindowStyleMaskBorderless windows
return YES;
}
- (BOOL)canBecomeMainWindow
{
return YES;
}
@@ -765,6 +793,10 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
//------------------------------------------------------------------------
@interface GLFWApplication : NSApplication
{
NSArray* nibObjects;
}
@end
@implementation GLFWApplication
@@ -774,8 +806,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
// down the command key don't get sent to the key window.
- (void)sendEvent:(NSEvent *)event
{
if ([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask))
if ([event type] == NSEventTypeKeyUp &&
([event modifierFlags] & NSEventModifierFlagCommand))
{
[[self keyWindow] sendEvent:event];
}
else
[super sendEvent:event];
}
@@ -786,53 +821,58 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)doNothing:(id)object
{
}
- (void)loadMainMenu
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 100800
[[NSBundle mainBundle] loadNibNamed:@"MainMenu"
owner:NSApp
topLevelObjects:&nibObjects];
#else
[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp];
#endif
}
@end
#if defined(_GLFW_USE_MENUBAR)
// Try to figure out what the calling application is called
// Set up the menu bar (manually)
// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
// could go away at any moment, lots of stuff that really should be
// localize(d|able), etc. Add a nib to save us this horror.
//
static NSString* findAppName(void)
static void createMenuBar(void)
{
size_t i;
NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
// Keys to search for as potential application names
NSString* GLFWNameKeys[] =
NSString* appName = nil;
NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
NSString* nameKeys[] =
{
@"CFBundleDisplayName",
@"CFBundleName",
@"CFBundleExecutable",
};
for (i = 0; i < sizeof(GLFWNameKeys) / sizeof(GLFWNameKeys[0]); i++)
// Try to figure out what the calling application is called
for (i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++)
{
id name = [infoDictionary objectForKey:GLFWNameKeys[i]];
id name = [bundleInfo objectForKey:nameKeys[i]];
if (name &&
[name isKindOfClass:[NSString class]] &&
![name isEqualToString:@""])
{
return name;
appName = name;
break;
}
}
char** progname = _NSGetProgname();
if (progname && *progname)
return [NSString stringWithUTF8String:*progname];
// Really shouldn't get here
return @"GLFW Application";
}
// Set up the menu bar (manually)
// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
// could go away at any moment, lots of stuff that really should be
// localize(d|able), etc. Loading a nib would save us this horror, but that
// doesn't seem like a good thing to require of GLFW users.
//
static void createMenuBar(void)
{
NSString* appName = findAppName();
if (!appName)
{
char** progname = _NSGetProgname();
if (progname && *progname)
appName = [NSString stringWithUTF8String:*progname];
else
appName = @"GLFW Application";
}
NSMenu* bar = [[NSMenu alloc] init];
[NSApp setMainMenu:bar];
@@ -859,7 +899,7 @@ static void createMenuBar(void)
[[appMenu addItemWithTitle:@"Hide Others"
action:@selector(hideOtherApplications:)
keyEquivalent:@"h"]
setKeyEquivalentModifierMask:NSAlternateKeyMask | NSCommandKeyMask];
setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
[appMenu addItemWithTitle:@"Show All"
action:@selector(unhideAllApplications:)
keyEquivalent:@""];
@@ -891,7 +931,7 @@ static void createMenuBar(void)
[[windowMenu addItemWithTitle:@"Enter Full Screen"
action:@selector(toggleFullScreen:)
keyEquivalent:@"f"]
setKeyEquivalentModifierMask:NSControlKeyMask | NSCommandKeyMask];
setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
// Prior to Snow Leopard, we need to use this oddly-named semi-private API
// to get the application menu working properly.
@@ -899,8 +939,6 @@ static void createMenuBar(void)
[NSApp performSelector:setAppleMenuSelector withObject:appMenu];
}
#endif /* _GLFW_USE_MENUBAR */
// Initialize the Cocoa Application Kit
//
static GLFWbool initializeAppKit(void)
@@ -916,15 +954,20 @@ static GLFWbool initializeAppKit(void)
toTarget:NSApp
withObject:nil];
// In case we are unbundled, make us a proper UI application
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
if (_glfw.hints.init.ns.menubar)
{
// In case we are unbundled, make us a proper UI application
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
#if defined(_GLFW_USE_MENUBAR)
// Menu bar setup must go between sharedApplication above and
// finishLaunching below, in order to properly emulate the behavior
// of NSApplicationMain
createMenuBar();
#endif
// Menu bar setup must go between sharedApplication above and
// finishLaunching below, in order to properly emulate the behavior
// of NSApplicationMain
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
[NSApp loadMainMenu];
else
createMenuBar();
}
// There can only be one application delegate, but we allocate it the
// first time a window is created to keep all window code in this file
@@ -944,8 +987,8 @@ static GLFWbool initializeAppKit(void)
// Create the Cocoa window
//
static GLFWbool createWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig)
static GLFWbool createNativeWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig)
{
window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window];
if (window->ns.delegate == nil)
@@ -987,9 +1030,17 @@ static GLFWbool createWindow(_GLFWwindow* window,
else
{
[window->ns.object center];
_glfw.ns.cascadePoint =
NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint:
NSPointFromCGPoint(_glfw.ns.cascadePoint)]);
if (wndconfig->resizable)
[window->ns.object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
{
const NSWindowCollectionBehavior behavior =
NSWindowCollectionBehaviorFullScreenPrimary |
NSWindowCollectionBehaviorManaged;
[window->ns.object setCollectionBehavior:behavior];
}
if (wndconfig->floating)
[window->ns.object setLevel:NSFloatingWindowLevel];
@@ -998,17 +1049,19 @@ static GLFWbool createWindow(_GLFWwindow* window,
[window->ns.object zoom:nil];
}
if (wndconfig->ns.frame)
[window->ns.object setFrameAutosaveName:[NSString stringWithUTF8String:wndconfig->title]];
window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
#if defined(_GLFW_USE_RETINA)
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
#endif /*_GLFW_USE_RETINA*/
if (wndconfig->ns.retina)
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
[window->ns.object setContentView:window->ns.view];
[window->ns.object makeFirstResponder:window->ns.view];
[window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
[window->ns.object setDelegate:window->ns.delegate];
[window->ns.object setAcceptsMouseMovedEvents:YES];
[window->ns.object setContentView:window->ns.view];
[window->ns.object setRestorable:NO];
return GLFW_TRUE;
@@ -1027,20 +1080,31 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!initializeAppKit())
return GLFW_FALSE;
if (!createWindow(window, wndconfig))
if (!createNativeWindow(window, wndconfig))
return GLFW_FALSE;
if (ctxconfig->client != GLFW_NO_API)
{
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
{
if (!_glfwInitNSGL())
return GLFW_FALSE;
if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "Cocoa: EGL not available");
return GLFW_FALSE;
if (!_glfwInitEGL())
return GLFW_FALSE;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{
if (!_glfwInitOSMesa())
return GLFW_FALSE;
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
}
@@ -1051,7 +1115,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!acquireMonitor(window))
return GLFW_FALSE;
centerCursor(window);
if (wndconfig->centerCursor)
centerCursor(window);
}
return GLFW_TRUE;
@@ -1067,7 +1132,7 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
if (window->monitor)
releaseMonitor(window);
if (window->context.client != GLFW_NO_API)
if (window->context.destroy)
window->context.destroy(window);
[window->ns.object setDelegate:nil];
@@ -1153,7 +1218,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
{
if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
[window->ns.object setContentAspectRatio:NSMakeSize(0, 0)];
[window->ns.object setResizeIncrements:NSMakeSize(1.0, 1.0)];
else
[window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)];
}
@@ -1217,6 +1282,11 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
[window->ns.object orderOut:nil];
}
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
{
[NSApp requestUserAttention:NSInformationalRequest];
}
void _glfwPlatformFocusWindow(_GLFWwindow* window)
{
// Make us the active application
@@ -1228,6 +1298,11 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
[window->ns.object makeKeyAndOrderFront:nil];
}
void _glfwPlatformDragWindow(_GLFWwindow* window)
{
[window->ns.object performWindowDragWithEvent:[NSApp currentEvent]];
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
@@ -1260,6 +1335,10 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_glfwInputWindowMonitorChange(window, monitor);
// HACK: Allow the state cached in Cocoa to catch up to reality
// TODO: Solve this in a less terrible way
_glfwPlatformPollEvents();
const NSUInteger styleMask = getStyleMask(window);
[window->ns.object setStyleMask:styleMask];
[window->ns.object makeFirstResponder:window->ns.view];
@@ -1345,11 +1424,30 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return [window->ns.object isZoomed];
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
[window->ns.object setStyleMask:getStyleMask(window)];
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
[window->ns.object setStyleMask:getStyleMask(window)];
[window->ns.object makeFirstResponder:window->ns.view];
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
if (enabled)
[window->ns.object setLevel:NSFloatingWindowLevel];
else
[window->ns.object setLevel:NSNormalWindowLevel];
}
void _glfwPlatformPollEvents(void)
{
for (;;)
{
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:[NSDate distantPast]
inMode:NSDefaultRunLoopMode
dequeue:YES];
@@ -1368,7 +1466,7 @@ void _glfwPlatformWaitEvents(void)
// I wanted to pass NO to dequeue:, and rely on PollEvents to
// dequeue and send. For reasons not at all clear to me, passing
// NO to dequeue: causes this method never to return.
NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:[NSDate distantFuture]
inMode:NSDefaultRunLoopMode
dequeue:YES];
@@ -1380,7 +1478,7 @@ void _glfwPlatformWaitEvents(void)
void _glfwPlatformWaitEventsTimeout(double timeout)
{
NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:date
inMode:NSDefaultRunLoopMode
dequeue:YES];
@@ -1393,7 +1491,7 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
void _glfwPlatformPostEmptyEvent(void)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSEvent* event = [NSEvent otherEventWithType:NSApplicationDefined
NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
location:NSMakePoint(0, 0)
modifierFlags:0
timestamp:0
@@ -1467,14 +1565,8 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
updateCursorImage(window);
}
const char* _glfwPlatformGetKeyName(int key, int scancode)
const char* _glfwPlatformGetScancodeName(int scancode)
{
if (key != GLFW_KEY_UNKNOWN)
scancode = _glfw.ns.nativeKeys[key];
if (!_glfwIsPrintable(_glfw.ns.publicKeys[scancode]))
return NULL;
UInt32 deadKeyState = 0;
UniChar characters[8];
UniCharCount characterCount = 0;
@@ -1509,6 +1601,11 @@ const char* _glfwPlatformGetKeyName(int key, int scancode)
return _glfw.ns.keyName;
}
int _glfwPlatformGetKeyScancode(int key)
{
return _glfw.ns.scancodes[key];
}
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot)
@@ -1538,7 +1635,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
memcpy([rep bitmapData], image->pixels, image->width * image->height * 4);
native = [[NSImage alloc] initWithSize:NSMakeSize(image->width, image->height)];
[native addRepresentation: rep];
[native addRepresentation:rep];
cursor->ns.object = [[NSCursor alloc] initWithImage:native
hotSpot:NSMakePoint(xhot, yhot)];
@@ -1557,7 +1654,19 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
if (!initializeAppKit())
return GLFW_FALSE;
cursor->ns.object = getStandardCursor(shape);
if (shape == GLFW_ARROW_CURSOR)
cursor->ns.object = [NSCursor arrowCursor];
else if (shape == GLFW_IBEAM_CURSOR)
cursor->ns.object = [NSCursor IBeamCursor];
else if (shape == GLFW_CROSSHAIR_CURSOR)
cursor->ns.object = [NSCursor crosshairCursor];
else if (shape == GLFW_HAND_CURSOR)
cursor->ns.object = [NSCursor pointingHandCursor];
else if (shape == GLFW_HRESIZE_CURSOR)
cursor->ns.object = [NSCursor resizeLeftRightCursor];
else if (shape == GLFW_VRESIZE_CURSOR)
cursor->ns.object = [NSCursor resizeUpDownCursor];
if (!cursor->ns.object)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
@@ -1616,17 +1725,20 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
return _glfw.ns.clipboardString;
}
char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
{
*count = 0;
return NULL;
if (!_glfw.vk.KHR_surface || !_glfw.vk.MVK_macos_surface)
return;
extensions[0] = "VK_KHR_surface";
extensions[1] = "VK_MVK_macos_surface";
}
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device,
uint32_t queuefamily)
{
return GLFW_FALSE;
return GLFW_TRUE;
}
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
@@ -1634,7 +1746,57 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
const VkAllocationCallbacks* allocator,
VkSurfaceKHR* surface)
{
#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
// dependency for the majority who don't use MoltenVK
NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"];
if (!bundle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to find QuartzCore.framework");
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
// NOTE: Create the layer here as makeBackingLayer should not return nil
window->ns.layer = [[bundle classNamed:@"CAMetalLayer"] layer];
if (!window->ns.layer)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to create layer for view");
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
[window->ns.view setWantsLayer:YES];
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);
if (err)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to create Vulkan surface: %s",
_glfwGetVulkanResultString(err));
}
return err;
#else
return VK_ERROR_EXTENSION_NOT_PRESENT;
#endif
}
+92 -78
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 - www.glfw.org
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -34,56 +34,6 @@
#include <stdio.h>
// Parses the client API version string and extracts the version number
//
static GLFWbool parseVersionString(int* api, int* major, int* minor, int* rev)
{
int i;
_GLFWwindow* window;
const char* version;
const char* prefixes[] =
{
"OpenGL ES-CM ",
"OpenGL ES-CL ",
"OpenGL ES ",
NULL
};
*api = GLFW_OPENGL_API;
window = _glfwPlatformGetCurrentContext();
version = (const char*) window->context.GetString(GL_VERSION);
if (!version)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Client API version string retrieval is broken");
return GLFW_FALSE;
}
for (i = 0; prefixes[i]; i++)
{
const size_t length = strlen(prefixes[i]);
if (strncmp(version, prefixes[i], length) == 0)
{
version += length;
*api = GLFW_OPENGL_ES_API;
break;
}
}
if (!sscanf(version, "%d.%d.%d", major, minor, rev))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"No version found in client API version string");
return GLFW_FALSE;
}
return GLFW_TRUE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
@@ -91,10 +41,11 @@ static GLFWbool parseVersionString(int* api, int* major, int* minor, int* rev)
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
{
if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
ctxconfig->source != GLFW_EGL_CONTEXT_API)
ctxconfig->source != GLFW_EGL_CONTEXT_API &&
ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
{
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid context creation API %i",
"Invalid context creation API 0x%08X",
ctxconfig->source);
return GLFW_FALSE;
}
@@ -104,7 +55,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
ctxconfig->client != GLFW_OPENGL_ES_API)
{
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid client API %i",
"Invalid client API 0x%08X",
ctxconfig->client);
return GLFW_FALSE;
}
@@ -134,7 +85,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
{
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid OpenGL profile %i",
"Invalid OpenGL profile 0x%08X",
ctxconfig->profile);
return GLFW_FALSE;
}
@@ -183,7 +134,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
{
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid context robustness mode %i",
"Invalid context robustness mode 0x%08X",
ctxconfig->robustness);
return GLFW_FALSE;
}
@@ -195,7 +146,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
{
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid context release behavior %i",
"Invalid context release behavior 0x%08X",
ctxconfig->release);
return GLFW_FALSE;
}
@@ -369,27 +320,79 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
int i;
_GLFWwindow* window;
const char* version;
const char* prefixes[] =
{
"OpenGL ES-CM ",
"OpenGL ES-CL ",
"OpenGL ES ",
NULL
};
window = _glfwPlatformGetTls(&_glfw.contextSlot);
window->context.source = ctxconfig->source;
window->context.client = GLFW_OPENGL_API;
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
glfwGetProcAddress("glGetIntegerv");
window->context.getProcAddress("glGetIntegerv");
window->context.GetString = (PFNGLGETSTRINGPROC)
glfwGetProcAddress("glGetString");
window->context.getProcAddress("glGetString");
if (!window->context.GetIntegerv || !window->context.GetString)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
return GLFW_FALSE;
}
if (!parseVersionString(&window->context.client,
&window->context.major,
&window->context.minor,
&window->context.revision))
version = (const char*) window->context.GetString(GL_VERSION);
if (!version)
{
if (ctxconfig->client == GLFW_OPENGL_API)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OpenGL version string retrieval is broken");
}
else
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OpenGL ES version string retrieval is broken");
}
return GLFW_FALSE;
}
window->context.source = ctxconfig->source;
for (i = 0; prefixes[i]; i++)
{
const size_t length = strlen(prefixes[i]);
if (strncmp(version, prefixes[i], length) == 0)
{
version += length;
window->context.client = GLFW_OPENGL_ES_API;
break;
}
}
if (!sscanf(version, "%d.%d.%d",
&window->context.major,
&window->context.minor,
&window->context.revision))
{
if (window->context.client == GLFW_OPENGL_API)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"No version found in OpenGL version string");
}
else
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"No version found in OpenGL ES version string");
}
return GLFW_FALSE;
}
if (window->context.major < ctxconfig->major ||
(window->context.major == ctxconfig->major &&
@@ -402,10 +405,21 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
// For API consistency, we emulate the behavior of the
// {GLX|WGL}_ARB_create_context extension and fail here
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"Requested client API version %i.%i, got version %i.%i",
ctxconfig->major, ctxconfig->minor,
window->context.major, window->context.minor);
if (window->context.client == GLFW_OPENGL_API)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"Requested OpenGL version %i.%i, got version %i.%i",
ctxconfig->major, ctxconfig->minor,
window->context.major, window->context.minor);
}
else
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"Requested OpenGL ES version %i.%i, got version %i.%i",
ctxconfig->major, ctxconfig->minor,
window->context.major, window->context.minor);
}
return GLFW_FALSE;
}
@@ -416,7 +430,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
// users as early as possible that their build may be broken
window->context.GetStringi = (PFNGLGETSTRINGIPROC)
glfwGetProcAddress("glGetStringi");
window->context.getProcAddress("glGetStringi");
if (!window->context.GetStringi)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
@@ -521,7 +535,8 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
// Clearing the front buffer to black to avoid garbage pixels left over from
// previous uses of our bit of VRAM
{
PFNGLCLEARPROC glClear = (PFNGLCLEARPROC) glfwGetProcAddress("glClear");
PFNGLCLEARPROC glClear = (PFNGLCLEARPROC)
window->context.getProcAddress("glClear");
glClear(GL_COLOR_BUFFER_BIT);
window->context.swapBuffers(window);
}
@@ -563,7 +578,7 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFWwindow* previous = _glfwPlatformGetCurrentContext();
_GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);
_GLFW_REQUIRE_INIT();
@@ -586,7 +601,7 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return (GLFWwindow*) _glfwPlatformGetCurrentContext();
return _glfwPlatformGetTls(&_glfw.contextSlot);
}
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
@@ -611,7 +626,7 @@ GLFWAPI void glfwSwapInterval(int interval)
_GLFW_REQUIRE_INIT();
window = _glfwPlatformGetCurrentContext();
window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (!window)
{
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
@@ -624,12 +639,11 @@ GLFWAPI void glfwSwapInterval(int interval)
GLFWAPI int glfwExtensionSupported(const char* extension)
{
_GLFWwindow* window;
assert(extension != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
window = _glfwPlatformGetCurrentContext();
window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (!window)
{
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
@@ -694,7 +708,7 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
window = _glfwPlatformGetCurrentContext();
window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (!window)
{
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
+149 -96
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 EGL - www.glfw.org
// GLFW 3.3 EGL - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -28,13 +28,14 @@
#include "internal.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
// Return a description of the specified EGL error
//
static const char* getErrorString(EGLint error)
static const char* getEGLErrorString(EGLint error)
{
switch (error)
{
@@ -75,16 +76,16 @@ static const char* getErrorString(EGLint error)
// Returns the specified attribute of the specified EGLConfig
//
static int getConfigAttrib(EGLConfig config, int attrib)
static int getEGLConfigAttrib(EGLConfig config, int attrib)
{
int value;
eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
return value;
}
// Return a list of available and usable framebuffer configs
// Return the EGLConfig most closely matching the specified hints
//
static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* desired,
EGLConfig* result)
{
@@ -112,16 +113,16 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
_GLFWfbconfig* u = usableConfigs + usableCount;
// Only consider RGB(A) EGLConfigs
if (!(getConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER))
if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
continue;
// Only consider window EGLConfigs
if (!(getConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
continue;
#if defined(_GLFW_X11)
// Only consider EGLConfigs with associated Visuals
if (!getConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
continue;
#endif // _GLFW_X11
@@ -129,30 +130,30 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
{
if (ctxconfig->major == 1)
{
if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
continue;
}
else
{
if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
continue;
}
}
else if (ctxconfig->client == GLFW_OPENGL_API)
{
if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
continue;
}
u->redBits = getConfigAttrib(n, EGL_RED_SIZE);
u->greenBits = getConfigAttrib(n, EGL_GREEN_SIZE);
u->blueBits = getConfigAttrib(n, EGL_BLUE_SIZE);
u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
u->greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE);
u->blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE);
u->alphaBits = getConfigAttrib(n, EGL_ALPHA_SIZE);
u->depthBits = getConfigAttrib(n, EGL_DEPTH_SIZE);
u->stencilBits = getConfigAttrib(n, EGL_STENCIL_SIZE);
u->alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE);
u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
u->samples = getConfigAttrib(n, EGL_SAMPLES);
u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
u->doublebuffer = GLFW_TRUE;
u->handle = (uintptr_t) n;
@@ -169,7 +170,7 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
return closest != NULL;
}
static void makeContextCurrent(_GLFWwindow* window)
static void makeContextCurrentEGL(_GLFWwindow* window)
{
if (window)
{
@@ -180,7 +181,7 @@ static void makeContextCurrent(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to make context current: %s",
getErrorString(eglGetError()));
getEGLErrorString(eglGetError()));
return;
}
}
@@ -193,17 +194,17 @@ static void makeContextCurrent(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to clear current context: %s",
getErrorString(eglGetError()));
getEGLErrorString(eglGetError()));
return;
}
}
_glfwPlatformSetCurrentContext(window);
_glfwPlatformSetTls(&_glfw.contextSlot, window);
}
static void swapBuffers(_GLFWwindow* window)
static void swapBuffersEGL(_GLFWwindow* window)
{
if (window != _glfwPlatformGetCurrentContext())
if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: The context must be current on the calling thread when swapping buffers");
@@ -213,12 +214,12 @@ static void swapBuffers(_GLFWwindow* window)
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
}
static void swapInterval(int interval)
static void swapIntervalEGL(int interval)
{
eglSwapInterval(_glfw.egl.display, interval);
}
static int extensionSupported(const char* extension)
static int extensionSupportedEGL(const char* extension)
{
const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
if (extensions)
@@ -230,9 +231,9 @@ static int extensionSupported(const char* extension)
return GLFW_FALSE;
}
static GLFWglproc getProcAddress(const char* procname)
static GLFWglproc getProcAddressEGL(const char* procname)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (window->context.egl.client)
{
@@ -245,7 +246,7 @@ static GLFWglproc getProcAddress(const char* procname)
return eglGetProcAddress(procname);
}
static void destroyContext(_GLFWwindow* window)
static void destroyContextEGL(_GLFWwindow* window)
{
#if defined(_GLFW_X11)
// NOTE: Do not unload libGL.so.1 while the X11 display is still open,
@@ -290,12 +291,17 @@ GLFWbool _glfwInitEGL(void)
"EGL.dll",
#elif defined(_GLFW_COCOA)
"libEGL.dylib",
#elif defined(__CYGWIN__)
"libEGL-1.so",
#else
"libEGL.so.1",
#endif
NULL
};
if (_glfw.egl.handle)
return GLFW_TRUE;
for (i = 0; sonames[i]; i++)
{
_glfw.egl.handle = _glfw_dlopen(sonames[i]);
@@ -304,47 +310,76 @@ GLFWbool _glfwInitEGL(void)
}
if (!_glfw.egl.handle)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");
return GLFW_FALSE;
}
_glfw.egl.GetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC)
_glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
_glfw.egl.GetConfigAttrib = (PFN_eglGetConfigAttrib)
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
_glfw.egl.GetConfigs = (PFNEGLGETCONFIGSPROC)
_glfw.egl.GetConfigs = (PFN_eglGetConfigs)
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
_glfw.egl.GetDisplay = (PFNEGLGETDISPLAYPROC)
_glfw.egl.GetDisplay = (PFN_eglGetDisplay)
_glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
_glfw.egl.GetError = (PFNEGLGETERRORPROC)
_glfw.egl.GetError = (PFN_eglGetError)
_glfw_dlsym(_glfw.egl.handle, "eglGetError");
_glfw.egl.Initialize = (PFNEGLINITIALIZEPROC)
_glfw.egl.Initialize = (PFN_eglInitialize)
_glfw_dlsym(_glfw.egl.handle, "eglInitialize");
_glfw.egl.Terminate = (PFNEGLTERMINATEPROC)
_glfw.egl.Terminate = (PFN_eglTerminate)
_glfw_dlsym(_glfw.egl.handle, "eglTerminate");
_glfw.egl.BindAPI = (PFNEGLBINDAPIPROC)
_glfw.egl.BindAPI = (PFN_eglBindAPI)
_glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
_glfw.egl.CreateContext = (PFNEGLCREATECONTEXTPROC)
_glfw.egl.CreateContext = (PFN_eglCreateContext)
_glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
_glfw.egl.DestroySurface = (PFNEGLDESTROYSURFACEPROC)
_glfw.egl.DestroySurface = (PFN_eglDestroySurface)
_glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
_glfw.egl.DestroyContext = (PFNEGLDESTROYCONTEXTPROC)
_glfw.egl.DestroyContext = (PFN_eglDestroyContext)
_glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
_glfw.egl.CreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC)
_glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
_glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
_glfw.egl.MakeCurrent = (PFNEGLMAKECURRENTPROC)
_glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
_glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
_glfw.egl.SwapBuffers = (PFNEGLSWAPBUFFERSPROC)
_glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
_glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
_glfw.egl.SwapInterval = (PFNEGLSWAPINTERVALPROC)
_glfw.egl.SwapInterval = (PFN_eglSwapInterval)
_glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
_glfw.egl.QueryString = (PFNEGLQUERYSTRINGPROC)
_glfw.egl.QueryString = (PFN_eglQueryString)
_glfw_dlsym(_glfw.egl.handle, "eglQueryString");
_glfw.egl.GetProcAddress = (PFNEGLGETPROCADDRESSPROC)
_glfw.egl.GetProcAddress = (PFN_eglGetProcAddress)
_glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
if (!_glfw.egl.GetConfigAttrib ||
!_glfw.egl.GetConfigs ||
!_glfw.egl.GetDisplay ||
!_glfw.egl.GetError ||
!_glfw.egl.Initialize ||
!_glfw.egl.Terminate ||
!_glfw.egl.BindAPI ||
!_glfw.egl.CreateContext ||
!_glfw.egl.DestroySurface ||
!_glfw.egl.DestroyContext ||
!_glfw.egl.CreateWindowSurface ||
!_glfw.egl.MakeCurrent ||
!_glfw.egl.SwapBuffers ||
!_glfw.egl.SwapInterval ||
!_glfw.egl.QueryString ||
!_glfw.egl.GetProcAddress)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to load required entry points");
_glfwTerminateEGL();
return GLFW_FALSE;
}
_glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
if (_glfw.egl.display == EGL_NO_DISPLAY)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to get EGL display: %s",
getErrorString(eglGetError()));
getEGLErrorString(eglGetError()));
_glfwTerminateEGL();
return GLFW_FALSE;
@@ -354,18 +389,22 @@ GLFWbool _glfwInitEGL(void)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to initialize EGL: %s",
getErrorString(eglGetError()));
getEGLErrorString(eglGetError()));
_glfwTerminateEGL();
return GLFW_FALSE;
}
_glfw.egl.KHR_create_context =
extensionSupported("EGL_KHR_create_context");
extensionSupportedEGL("EGL_KHR_create_context");
_glfw.egl.KHR_create_context_no_error =
extensionSupported("EGL_KHR_create_context_no_error");
extensionSupportedEGL("EGL_KHR_create_context_no_error");
_glfw.egl.KHR_gl_colorspace =
extensionSupported("EGL_KHR_gl_colorspace");
extensionSupportedEGL("EGL_KHR_gl_colorspace");
_glfw.egl.KHR_get_all_proc_addresses =
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
_glfw.egl.KHR_context_flush_control =
extensionSupportedEGL("EGL_KHR_context_flush_control");
return GLFW_TRUE;
}
@@ -387,11 +426,11 @@ void _glfwTerminateEGL(void)
}
}
#define setEGLattrib(attribName, attribValue) \
#define setAttrib(a, v) \
{ \
attribs[index++] = attribName; \
attribs[index++] = attribValue; \
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
attribs[index++] = v; \
}
// Create the OpenGL or OpenGL ES context
@@ -403,6 +442,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
EGLint attribs[40];
EGLConfig config;
EGLContext share = NULL;
int index = 0;
if (!_glfw.egl.display)
{
@@ -413,7 +453,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (ctxconfig->share)
share = ctxconfig->share->context.egl.handle;
if (!chooseFBConfigs(ctxconfig, fbconfig, &config))
if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"EGL: Failed to find a suitable EGLConfig");
@@ -426,7 +466,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to bind OpenGL ES: %s",
getErrorString(eglGetError()));
getEGLErrorString(eglGetError()));
return GLFW_FALSE;
}
}
@@ -436,14 +476,14 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to bind OpenGL: %s",
getErrorString(eglGetError()));
getEGLErrorString(eglGetError()));
return GLFW_FALSE;
}
}
if (_glfw.egl.KHR_create_context)
{
int index = 0, mask = 0, flags = 0;
int mask = 0, flags = 0;
if (ctxconfig->client == GLFW_OPENGL_API)
{
@@ -454,12 +494,6 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
if (_glfw.egl.KHR_create_context_no_error)
{
if (ctxconfig->noerror)
flags |= EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
}
}
if (ctxconfig->debug)
@@ -469,44 +503,57 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
{
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
EGL_NO_RESET_NOTIFICATION_KHR);
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
EGL_NO_RESET_NOTIFICATION_KHR);
}
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
{
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
EGL_LOSE_CONTEXT_ON_RESET_KHR);
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
EGL_LOSE_CONTEXT_ON_RESET_KHR);
}
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
}
if (ctxconfig->noerror)
{
if (_glfw.egl.KHR_create_context_no_error)
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
}
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
setEGLattrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
setEGLattrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
}
if (mask)
setEGLattrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
if (flags)
setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags);
setEGLattrib(EGL_NONE, EGL_NONE);
setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
}
else
{
int index = 0;
if (ctxconfig->client == GLFW_OPENGL_ES_API)
setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
setEGLattrib(EGL_NONE, EGL_NONE);
setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
}
// Context release behaviors (GL_KHR_context_flush_control) are not yet
// supported on EGL but are not a hard constraint, so ignore and continue
if (_glfw.egl.KHR_context_flush_control)
{
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
{
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
}
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
{
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
}
}
setAttrib(EGL_NONE, EGL_NONE);
window->context.egl.handle = eglCreateContext(_glfw.egl.display,
config, share, attribs);
@@ -515,7 +562,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"EGL: Failed to create context: %s",
getErrorString(eglGetError()));
getEGLErrorString(eglGetError()));
return GLFW_FALSE;
}
@@ -526,12 +573,10 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (fbconfig->sRGB)
{
if (_glfw.egl.KHR_gl_colorspace)
{
setEGLattrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
}
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
}
setEGLattrib(EGL_NONE, EGL_NONE);
setAttrib(EGL_NONE, EGL_NONE);
}
window->context.egl.surface =
@@ -543,13 +588,14 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to create window surface: %s",
getErrorString(eglGetError()));
getEGLErrorString(eglGetError()));
return GLFW_FALSE;
}
window->context.egl.config = config;
// Load the appropriate client library
if (!_glfw.egl.KHR_get_all_proc_addresses)
{
int i;
const char** sonames;
@@ -573,6 +619,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
"libGLESv2.dll",
#elif defined(_GLFW_COCOA)
"libGLESv2.dylib",
#elif defined(__CYGWIN__)
"libGLESv2-2.so",
#else
"libGLESv2.so.2",
#endif
@@ -600,6 +648,11 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
for (i = 0; sonames[i]; i++)
{
// HACK: Match presence of lib prefix to increase chance of finding
// a matching pair in the jungle that is Win32 EGL/GLES
if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0))
continue;
window->context.egl.client = _glfw_dlopen(sonames[i]);
if (window->context.egl.client)
break;
@@ -613,17 +666,17 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
}
}
window->context.makeCurrent = makeContextCurrent;
window->context.swapBuffers = swapBuffers;
window->context.swapInterval = swapInterval;
window->context.extensionSupported = extensionSupported;
window->context.getProcAddress = getProcAddress;
window->context.destroy = destroyContext;
window->context.makeCurrent = makeContextCurrentEGL;
window->context.swapBuffers = swapBuffersEGL;
window->context.swapInterval = swapIntervalEGL;
window->context.extensionSupported = extensionSupportedEGL;
window->context.getProcAddress = getProcAddressEGL;
window->context.destroy = destroyContextEGL;
return GLFW_TRUE;
}
#undef setEGLattrib
#undef setAttrib
// Returns the Visual and depth of the chosen EGLConfig
//
@@ -638,7 +691,7 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
EGLint visualID = 0, count = 0;
const long vimask = VisualScreenMask | VisualIDMask;
if (!chooseFBConfigs(ctxconfig, fbconfig, &native))
if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"EGL: Failed to find a suitable EGLConfig");
+44 -39
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 EGL - www.glfw.org
// GLFW 3.3 EGL - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -25,15 +25,16 @@
//
//========================================================================
#ifndef _glfw3_egl_context_h_
#define _glfw3_egl_context_h_
#if defined(_GLFW_USE_EGLPLATFORM_H)
#include <EGL/eglplatform.h>
#elif defined(_GLFW_WIN32)
#define EGLAPIENTRY __stdcall
typedef HDC EGLNativeDisplayType;
typedef HWND EGLNativeWindowType;
#elif defined(_GLFW_COCOA)
#define EGLAPIENTRY
typedef void* EGLNativeDisplayType;
typedef id EGLNativeWindowType;
#elif defined(_GLFW_X11)
#define EGLAPIENTRY
typedef Display* EGLNativeDisplayType;
@@ -106,6 +107,9 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3
#define EGL_GL_COLORSPACE_KHR 0x309d
#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
typedef int EGLint;
typedef unsigned int EGLBoolean;
@@ -116,22 +120,22 @@ typedef void* EGLDisplay;
typedef void* EGLSurface;
// EGL function pointer typedefs
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay,EGLConfig,EGLint,EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGSPROC)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType);
typedef EGLint (EGLAPIENTRY * PFNEGLGETERRORPROC)(void);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLINITIALIZEPROC)(EGLDisplay,EGLint*,EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLTERMINATEPROC)(EGLDisplay);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLBINDAPIPROC)(EGLenum);
typedef EGLContext (EGLAPIENTRY * PFNEGLCREATECONTEXTPROC)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSURFACEPROC)(EGLDisplay,EGLSurface);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYCONTEXTPROC)(EGLDisplay,EGLContext);
typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLMAKECURRENTPROC)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPBUFFERSPROC)(EGLDisplay,EGLSurface);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPINTERVALPROC)(EGLDisplay,EGLint);
typedef const char* (EGLAPIENTRY * PFNEGLQUERYSTRINGPROC)(EGLDisplay,EGLint);
typedef GLFWglproc (EGLAPIENTRY * PFNEGLGETPROCADDRESSPROC)(const char*);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType);
typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglTerminate)(EGLDisplay);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglBindAPI)(EGLenum);
typedef EGLContext (EGLAPIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext);
typedef EGLSurface (EGLAPIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
#define eglGetConfigs _glfw.egl.GetConfigs
#define eglGetDisplay _glfw.egl.GetDisplay
@@ -165,36 +169,38 @@ typedef struct _GLFWcontextEGL
} _GLFWcontextEGL;
// EGL-specific global data
//
typedef struct _GLFWlibraryEGL
{
EGLDisplay display;
EGLint major, minor;
GLFWbool prefix;
GLFWbool KHR_create_context;
GLFWbool KHR_create_context_no_error;
GLFWbool KHR_gl_colorspace;
GLFWbool KHR_get_all_proc_addresses;
GLFWbool KHR_context_flush_control;
void* handle;
PFNEGLGETCONFIGATTRIBPROC GetConfigAttrib;
PFNEGLGETCONFIGSPROC GetConfigs;
PFNEGLGETDISPLAYPROC GetDisplay;
PFNEGLGETERRORPROC GetError;
PFNEGLINITIALIZEPROC Initialize;
PFNEGLTERMINATEPROC Terminate;
PFNEGLBINDAPIPROC BindAPI;
PFNEGLCREATECONTEXTPROC CreateContext;
PFNEGLDESTROYSURFACEPROC DestroySurface;
PFNEGLDESTROYCONTEXTPROC DestroyContext;
PFNEGLCREATEWINDOWSURFACEPROC CreateWindowSurface;
PFNEGLMAKECURRENTPROC MakeCurrent;
PFNEGLSWAPBUFFERSPROC SwapBuffers;
PFNEGLSWAPINTERVALPROC SwapInterval;
PFNEGLQUERYSTRINGPROC QueryString;
PFNEGLGETPROCADDRESSPROC GetProcAddress;
PFN_eglGetConfigAttrib GetConfigAttrib;
PFN_eglGetConfigs GetConfigs;
PFN_eglGetDisplay GetDisplay;
PFN_eglGetError GetError;
PFN_eglInitialize Initialize;
PFN_eglTerminate Terminate;
PFN_eglBindAPI BindAPI;
PFN_eglCreateContext CreateContext;
PFN_eglDestroySurface DestroySurface;
PFN_eglDestroyContext DestroyContext;
PFN_eglCreateWindowSurface CreateWindowSurface;
PFN_eglMakeCurrent MakeCurrent;
PFN_eglSwapBuffers SwapBuffers;
PFN_eglSwapInterval SwapInterval;
PFN_eglQueryString QueryString;
PFN_eglGetProcAddress GetProcAddress;
} _GLFWlibraryEGL;
@@ -210,4 +216,3 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
Visual** visual, int* depth);
#endif /*_GLFW_X11*/
#endif // _glfw3_egl_context_h_
+6 -12
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 - www.glfw.org
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2010-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2010-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -44,20 +44,14 @@
#cmakedefine _GLFW_WAYLAND
// Define this to 1 if building GLFW for Mir
#cmakedefine _GLFW_MIR
// Define this to 1 if building GLFW for 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
#cmakedefine _GLFW_VULKAN_STATIC
// Define this to 1 to force use of high-performance GPU on hybrid systems
#cmakedefine _GLFW_USE_HYBRID_HPG
// Define this to 1 if the Xxf86vm X11 extension is available
#cmakedefine _GLFW_HAS_XF86VM
// Define this to 1 if glfwInit should change the current directory
#cmakedefine _GLFW_USE_CHDIR
// Define this to 1 if glfwCreateWindow should populate the menu bar
#cmakedefine _GLFW_USE_MENUBAR
// Define this to 1 if windows should use full resolution on Retina displays
#cmakedefine _GLFW_USE_RETINA
+114 -80
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 GLX - www.glfw.org
// GLFW 3.3 GLX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -38,16 +38,16 @@
// Returns the specified attribute of the specified GLXFBConfig
//
static int getFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
{
int value;
glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value);
return value;
}
// Return a list of available and usable framebuffer configs
// Return the GLXFBConfig most closely matching the specified hints
//
static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result)
static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result)
{
GLXFBConfig* nativeConfigs;
_GLFWfbconfig* usableConfigs;
@@ -59,12 +59,12 @@ static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result
// HACK: This is a (hopefully temporary) workaround for Chromium
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
if (strcmp(vendor, "Chromium") == 0)
if (vendor && strcmp(vendor, "Chromium") == 0)
trustWindowBit = GLFW_FALSE;
nativeConfigs =
glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
if (!nativeCount)
if (!nativeConfigs || !nativeCount)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
return GLFW_FALSE;
@@ -79,41 +79,41 @@ static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result
_GLFWfbconfig* u = usableConfigs + usableCount;
// Only consider RGBA GLXFBConfigs
if (!(getFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
if (!(getGLXFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
continue;
// Only consider window GLXFBConfigs
if (!(getFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
if (!(getGLXFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
{
if (trustWindowBit)
continue;
}
u->redBits = getFBConfigAttrib(n, GLX_RED_SIZE);
u->greenBits = getFBConfigAttrib(n, GLX_GREEN_SIZE);
u->blueBits = getFBConfigAttrib(n, GLX_BLUE_SIZE);
u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE);
u->blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_SIZE);
u->alphaBits = getFBConfigAttrib(n, GLX_ALPHA_SIZE);
u->depthBits = getFBConfigAttrib(n, GLX_DEPTH_SIZE);
u->stencilBits = getFBConfigAttrib(n, GLX_STENCIL_SIZE);
u->alphaBits = getGLXFBConfigAttrib(n, GLX_ALPHA_SIZE);
u->depthBits = getGLXFBConfigAttrib(n, GLX_DEPTH_SIZE);
u->stencilBits = getGLXFBConfigAttrib(n, GLX_STENCIL_SIZE);
u->accumRedBits = getFBConfigAttrib(n, GLX_ACCUM_RED_SIZE);
u->accumGreenBits = getFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE);
u->accumBlueBits = getFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE);
u->accumAlphaBits = getFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
u->accumRedBits = getGLXFBConfigAttrib(n, GLX_ACCUM_RED_SIZE);
u->accumGreenBits = getGLXFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE);
u->accumBlueBits = getGLXFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE);
u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
u->auxBuffers = getFBConfigAttrib(n, GLX_AUX_BUFFERS);
u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
if (getFBConfigAttrib(n, GLX_STEREO))
if (getGLXFBConfigAttrib(n, GLX_STEREO))
u->stereo = GLFW_TRUE;
if (getFBConfigAttrib(n, GLX_DOUBLEBUFFER))
if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER))
u->doublebuffer = GLFW_TRUE;
if (_glfw.glx.ARB_multisample)
u->samples = getFBConfigAttrib(n, GLX_SAMPLES);
u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)
u->sRGB = getFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
u->sRGB = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
u->handle = (uintptr_t) n;
usableCount++;
@@ -131,9 +131,9 @@ static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result
// Create the OpenGL context using legacy API
//
static GLXContext createLegacyContext(_GLFWwindow* window,
GLXFBConfig fbconfig,
GLXContext share)
static GLXContext createLegacyContextGLX(_GLFWwindow* window,
GLXFBConfig fbconfig,
GLXContext share)
{
return glXCreateNewContext(_glfw.x11.display,
fbconfig,
@@ -142,7 +142,7 @@ static GLXContext createLegacyContext(_GLFWwindow* window,
True);
}
static void makeContextCurrent(_GLFWwindow* window)
static void makeContextCurrentGLX(_GLFWwindow* window)
{
if (window)
{
@@ -165,17 +165,17 @@ static void makeContextCurrent(_GLFWwindow* window)
}
}
_glfwPlatformSetCurrentContext(window);
_glfwPlatformSetTls(&_glfw.contextSlot, window);
}
static void swapBuffers(_GLFWwindow* window)
static void swapBuffersGLX(_GLFWwindow* window)
{
glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
}
static void swapInterval(int interval)
static void swapIntervalGLX(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (_glfw.glx.EXT_swap_control)
{
@@ -192,7 +192,7 @@ static void swapInterval(int interval)
}
}
static int extensionSupported(const char* extension)
static int extensionSupportedGLX(const char* extension)
{
const char* extensions =
glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);
@@ -205,7 +205,7 @@ static int extensionSupported(const char* extension)
return GLFW_FALSE;
}
static GLFWglproc getProcAddress(const char* procname)
static GLFWglproc getProcAddressGLX(const char* procname)
{
if (_glfw.glx.GetProcAddress)
return _glfw.glx.GetProcAddress((const GLubyte*) procname);
@@ -217,7 +217,7 @@ static GLFWglproc getProcAddress(const char* procname)
// Destroy the OpenGL context
//
static void destroyContext(_GLFWwindow* window)
static void destroyContextGLX(_GLFWwindow* window)
{
if (window->context.glx.window)
{
@@ -253,6 +253,9 @@ GLFWbool _glfwInitGLX(void)
NULL
};
if (_glfw.glx.handle)
return GLFW_TRUE;
for (i = 0; sonames[i]; i++)
{
_glfw.glx.handle = dlopen(sonames[i], RTLD_LAZY | RTLD_GLOBAL);
@@ -297,6 +300,27 @@ GLFWbool _glfwInitGLX(void)
_glfw.glx.GetVisualFromFBConfig =
dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
if (!_glfw.glx.GetFBConfigs ||
!_glfw.glx.GetFBConfigAttrib ||
!_glfw.glx.GetClientString ||
!_glfw.glx.QueryExtension ||
!_glfw.glx.QueryVersion ||
!_glfw.glx.DestroyContext ||
!_glfw.glx.MakeCurrent ||
!_glfw.glx.SwapBuffers ||
!_glfw.glx.QueryExtensionsString ||
!_glfw.glx.CreateNewContext ||
!_glfw.glx.CreateWindow ||
!_glfw.glx.DestroyWindow ||
!_glfw.glx.GetProcAddress ||
!_glfw.glx.GetProcAddressARB ||
!_glfw.glx.GetVisualFromFBConfig)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"GLX: Failed to load required entry points");
return GLFW_FALSE;
}
if (!glXQueryExtension(_glfw.x11.display,
&_glfw.glx.errorBase,
&_glfw.glx.eventBase))
@@ -319,61 +343,64 @@ GLFWbool _glfwInitGLX(void)
return GLFW_FALSE;
}
if (extensionSupported("GLX_EXT_swap_control"))
if (extensionSupportedGLX("GLX_EXT_swap_control"))
{
_glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)
getProcAddress("glXSwapIntervalEXT");
getProcAddressGLX("glXSwapIntervalEXT");
if (_glfw.glx.SwapIntervalEXT)
_glfw.glx.EXT_swap_control = GLFW_TRUE;
}
if (extensionSupported("GLX_SGI_swap_control"))
if (extensionSupportedGLX("GLX_SGI_swap_control"))
{
_glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
getProcAddress("glXSwapIntervalSGI");
getProcAddressGLX("glXSwapIntervalSGI");
if (_glfw.glx.SwapIntervalSGI)
_glfw.glx.SGI_swap_control = GLFW_TRUE;
}
if (extensionSupported("GLX_MESA_swap_control"))
if (extensionSupportedGLX("GLX_MESA_swap_control"))
{
_glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)
getProcAddress("glXSwapIntervalMESA");
getProcAddressGLX("glXSwapIntervalMESA");
if (_glfw.glx.SwapIntervalMESA)
_glfw.glx.MESA_swap_control = GLFW_TRUE;
}
if (extensionSupported("GLX_ARB_multisample"))
if (extensionSupportedGLX("GLX_ARB_multisample"))
_glfw.glx.ARB_multisample = GLFW_TRUE;
if (extensionSupported("GLX_ARB_framebuffer_sRGB"))
if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
_glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
if (extensionSupported("GLX_EXT_framebuffer_sRGB"))
if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
_glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
if (extensionSupported("GLX_ARB_create_context"))
if (extensionSupportedGLX("GLX_ARB_create_context"))
{
_glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
getProcAddress("glXCreateContextAttribsARB");
getProcAddressGLX("glXCreateContextAttribsARB");
if (_glfw.glx.CreateContextAttribsARB)
_glfw.glx.ARB_create_context = GLFW_TRUE;
}
if (extensionSupported("GLX_ARB_create_context_robustness"))
if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
_glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
if (extensionSupported("GLX_ARB_create_context_profile"))
if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
_glfw.glx.ARB_create_context_profile = GLFW_TRUE;
if (extensionSupported("GLX_EXT_create_context_es2_profile"))
if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
_glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
if (extensionSupported("GLX_ARB_context_flush_control"))
if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
_glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
_glfw.glx.ARB_context_flush_control = GLFW_TRUE;
return GLFW_TRUE;
@@ -393,11 +420,11 @@ void _glfwTerminateGLX(void)
}
}
#define setGLXattrib(attribName, attribValue) \
#define setAttrib(a, v) \
{ \
attribs[index++] = attribName; \
attribs[index++] = attribValue; \
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
attribs[index++] = v; \
}
// Create the OpenGL or OpenGL ES context
@@ -413,7 +440,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
if (ctxconfig->share)
share = ctxconfig->share->context.glx.handle;
if (!chooseFBConfig(fbconfig, &native))
if (!chooseGLXFBConfig(fbconfig, &native))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"GLX: Failed to find a suitable GLXFBConfig");
@@ -474,8 +501,6 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
if (ctxconfig->debug)
flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
if (ctxconfig->noerror)
flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
if (ctxconfig->robustness)
{
@@ -483,13 +508,13 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
{
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
{
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
GLX_NO_RESET_NOTIFICATION_ARB);
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
GLX_NO_RESET_NOTIFICATION_ARB);
}
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
{
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
GLX_LOSE_CONTEXT_ON_RESET_ARB);
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
GLX_LOSE_CONTEXT_ON_RESET_ARB);
}
flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
@@ -502,33 +527,39 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
{
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
{
setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
}
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
{
setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
}
}
}
if (ctxconfig->noerror)
{
if (_glfw.glx.ARB_create_context_no_error)
setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
}
// NOTE: Only request an explicitly versioned context when necessary, as
// explicitly requesting version 1.0 does not always return the
// highest version supported by the driver
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
setAttrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
setAttrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
}
if (mask)
setGLXattrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
setAttrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
if (flags)
setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags);
setAttrib(GLX_CONTEXT_FLAGS_ARB, flags);
setGLXattrib(None, None);
setAttrib(None, None);
window->context.glx.handle =
_glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
@@ -549,12 +580,15 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
ctxconfig->forward == GLFW_FALSE)
{
window->context.glx.handle =
createLegacyContext(window, native, share);
createLegacyContextGLX(window, native, share);
}
}
}
else
window->context.glx.handle = createLegacyContext(window, native, share);
{
window->context.glx.handle =
createLegacyContextGLX(window, native, share);
}
_glfwReleaseErrorHandlerX11();
@@ -572,17 +606,17 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
return GLFW_FALSE;
}
window->context.makeCurrent = makeContextCurrent;
window->context.swapBuffers = swapBuffers;
window->context.swapInterval = swapInterval;
window->context.extensionSupported = extensionSupported;
window->context.getProcAddress = getProcAddress;
window->context.destroy = destroyContext;
window->context.makeCurrent = makeContextCurrentGLX;
window->context.swapBuffers = swapBuffersGLX;
window->context.swapInterval = swapIntervalGLX;
window->context.extensionSupported = extensionSupportedGLX;
window->context.getProcAddress = getProcAddressGLX;
window->context.destroy = destroyContextGLX;
return GLFW_TRUE;
}
#undef setGLXattrib
#undef setAttrib
// Returns the Visual and depth of the chosen GLXFBConfig
//
@@ -593,7 +627,7 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
GLXFBConfig native;
XVisualInfo* result;
if (!chooseFBConfig(fbconfig, &native))
if (!chooseGLXFBConfig(fbconfig, &native))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"GLX: Failed to find a suitable GLXFBConfig");
+9 -11
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 GLX - www.glfw.org
// GLFW 3.3 GLX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -25,9 +25,6 @@
//
//========================================================================
#ifndef _glfw3_glx_context_h_
#define _glfw3_glx_context_h_
#define GLX_VENDOR 1
#define GLX_RGBA_BIT 0x00000001
#define GLX_WINDOW_BIT 0x00000001
@@ -67,6 +64,7 @@
#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
typedef XID GLXWindow;
typedef XID GLXDrawable;
@@ -84,15 +82,16 @@ typedef void (*PFNGLXSWAPBUFFERSPROC)(Display*,GLXDrawable);
typedef const char* (*PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display*,int);
typedef GLXFBConfig* (*PFNGLXGETFBCONFIGSPROC)(Display*,int,int*);
typedef GLXContext (*PFNGLXCREATENEWCONTEXTPROC)(Display*,GLXFBConfig,int,GLXContext,Bool);
typedef __GLXextproc (* PFNGLXGETPROCADDRESSPROC) (const GLubyte *procName);
typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int);
typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int);
typedef __GLXextproc (* PFNGLXGETPROCADDRESSPROC)(const GLubyte *procName);
typedef void (*PFNGLXSWAPINTERVALEXTPROC)(Display*,GLXDrawable,int);
typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLXContext,Bool,const int*);
typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig);
typedef GLXWindow (*PFNGLXCREATEWINDOWPROC)(Display*,GLXFBConfig,Window,const int*);
typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow);
typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int);
typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int);
typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLXContext,Bool,const int*);
// libGL.so function pointer typedefs
#define glXGetFBConfigs _glfw.glx.GetFBConfigs
#define glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib
@@ -121,7 +120,6 @@ typedef struct _GLFWcontextGLX
} _GLFWcontextGLX;
// GLX-specific global data
//
typedef struct _GLFWlibraryGLX
@@ -165,6 +163,7 @@ typedef struct _GLFWlibraryGLX
GLFWbool ARB_create_context_profile;
GLFWbool ARB_create_context_robustness;
GLFWbool EXT_create_context_es2_profile;
GLFWbool ARB_create_context_no_error;
GLFWbool ARB_context_flush_control;
} _GLFWlibraryGLX;
@@ -180,4 +179,3 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig,
Visual** visual, int* depth);
#endif // _glfw3_glx_context_h_
+206 -89
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 - www.glfw.org
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -26,33 +26,45 @@
//========================================================================
#include "internal.h"
#include "mappings.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
// The three global variables below comprise all global data in GLFW.
// The global variables below comprise all global data in GLFW.
// Any other global variable is a bug.
// Global state shared between compilation units of GLFW
// These are documented in internal.h
//
GLFWbool _glfwInitialized = GLFW_FALSE;
_GLFWlibrary _glfw;
_GLFWlibrary _glfw = { GLFW_FALSE };
// This is outside of _glfw so it can be initialized and usable before
// glfwInit is called, which lets that function report errors
// These are outside of _glfw so they can be used before initialization and
// after termination
//
static GLFWerrorfun _glfwErrorCallback = NULL;
static _GLFWerror _glfwMainThreadError;
static GLFWerrorfun _glfwErrorCallback;
static _GLFWinitconfig _glfwInitHints =
{
GLFW_TRUE, // hat buttons
{
GLFW_TRUE, // macOS menu bar
GLFW_TRUE // macOS bundle chdir
},
{
"", // X11 WM_CLASS name
"" // X11 WM_CLASS class
}
};
// Returns a generic string representation of the specified error
//
static const char* getErrorString(int error)
static const char* getErrorString(int code)
{
switch (error)
switch (code)
{
case GLFW_NOT_INITIALIZED:
return "The GLFW library is not initialized";
@@ -65,11 +77,11 @@ static const char* getErrorString(int error)
case GLFW_OUT_OF_MEMORY:
return "Out of memory";
case GLFW_API_UNAVAILABLE:
return "The requested client API is unavailable";
return "The requested API is unavailable";
case GLFW_VERSION_UNAVAILABLE:
return "The requested client API version is unavailable";
return "The requested API version is unavailable";
case GLFW_PLATFORM_ERROR:
return "A platform-specific error occurred";
return "An undocumented platform-specific error occurred";
case GLFW_FORMAT_UNAVAILABLE:
return "The requested format is unavailable";
case GLFW_NO_WINDOW_CONTEXT:
@@ -79,77 +91,12 @@ static const char* getErrorString(int error)
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW event API //////
//////////////////////////////////////////////////////////////////////////
void _glfwInputError(int error, const char* format, ...)
{
if (_glfwErrorCallback)
{
char buffer[8192];
const char* description;
if (format)
{
int count;
va_list vl;
va_start(vl, format);
count = vsnprintf(buffer, sizeof(buffer), format, vl);
va_end(vl);
if (count < 0)
buffer[sizeof(buffer) - 1] = '\0';
description = buffer;
}
else
description = getErrorString(error);
_glfwErrorCallback(error, description);
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW public API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI int glfwInit(void)
{
if (_glfwInitialized)
return GLFW_TRUE;
memset(&_glfw, 0, sizeof(_glfw));
if (!_glfwPlatformInit())
{
_glfwPlatformTerminate();
return GLFW_FALSE;
}
_glfwInitVulkan();
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
_glfwInitialized = GLFW_TRUE;
_glfw.timerOffset = _glfwPlatformGetTimerValue();
// Not all window hints have zero as their default value
glfwDefaultWindowHints();
return GLFW_TRUE;
}
GLFWAPI void glfwTerminate(void)
// Terminate the library
//
static void terminate(void)
{
int i;
if (!_glfwInitialized)
return;
memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
while (_glfw.windowListHead)
@@ -163,28 +110,174 @@ GLFWAPI void glfwTerminate(void)
_GLFWmonitor* monitor = _glfw.monitors[i];
if (monitor->originalRamp.size)
_glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
_glfwFreeMonitor(monitor);
}
_glfwTerminateVulkan();
_glfwFreeMonitors(_glfw.monitors, _glfw.monitorCount);
free(_glfw.monitors);
_glfw.monitors = NULL;
_glfw.monitorCount = 0;
free(_glfw.mappings);
_glfw.mappings = NULL;
_glfw.mappingCount = 0;
_glfwTerminateVulkan();
_glfwPlatformTerminate();
_glfw.initialized = GLFW_FALSE;
while (_glfw.errorListHead)
{
_GLFWerror* error = _glfw.errorListHead;
_glfw.errorListHead = error->next;
free(error);
}
_glfwPlatformDestroyTls(&_glfw.contextSlot);
_glfwPlatformDestroyTls(&_glfw.errorSlot);
_glfwPlatformDestroyMutex(&_glfw.errorLock);
memset(&_glfw, 0, sizeof(_glfw));
_glfwInitialized = GLFW_FALSE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW event API //////
//////////////////////////////////////////////////////////////////////////
void _glfwInputError(int code, const char* format, ...)
{
_GLFWerror* error;
char description[1024];
if (format)
{
int count;
va_list vl;
va_start(vl, format);
count = vsnprintf(description, sizeof(description), format, vl);
va_end(vl);
if (count < 0)
description[sizeof(description) - 1] = '\0';
}
else
strcpy(description, getErrorString(code));
if (_glfw.initialized)
{
error = _glfwPlatformGetTls(&_glfw.errorSlot);
if (!error)
{
error = calloc(1, sizeof(_GLFWerror));
_glfwPlatformSetTls(&_glfw.errorSlot, error);
_glfwPlatformLockMutex(&_glfw.errorLock);
error->next = _glfw.errorListHead;
_glfw.errorListHead = error;
_glfwPlatformUnlockMutex(&_glfw.errorLock);
}
}
else
error = &_glfwMainThreadError;
error->code = code;
strcpy(error->description, description);
if (_glfwErrorCallback)
_glfwErrorCallback(code, description);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW public API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI int glfwInit(void)
{
if (_glfw.initialized)
return GLFW_TRUE;
memset(&_glfw, 0, sizeof(_glfw));
_glfw.hints.init = _glfwInitHints;
if (!_glfwPlatformInit())
{
terminate();
return GLFW_FALSE;
}
if (!_glfwPlatformCreateMutex(&_glfw.errorLock))
return GLFW_FALSE;
if (!_glfwPlatformCreateTls(&_glfw.errorSlot))
return GLFW_FALSE;
if (!_glfwPlatformCreateTls(&_glfw.contextSlot))
return GLFW_FALSE;
_glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
_glfw.initialized = GLFW_TRUE;
_glfw.timer.offset = _glfwPlatformGetTimerValue();
glfwDefaultWindowHints();
glfwUpdateGamepadMappings(_glfwDefaultMappings);
return GLFW_TRUE;
}
GLFWAPI void glfwTerminate(void)
{
if (!_glfw.initialized)
return;
terminate();
}
GLFWAPI void glfwInitHint(int hint, int value)
{
switch (hint)
{
case GLFW_JOYSTICK_HAT_BUTTONS:
_glfwInitHints.hatButtons = value;
return;
case GLFW_COCOA_CHDIR_RESOURCES:
_glfwInitHints.ns.chdir = value;
return;
case GLFW_COCOA_MENUBAR:
_glfwInitHints.ns.menubar = value;
return;
}
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid integer type init hint 0x%08X", hint);
}
GLFWAPI void glfwInitHintString(int hint, const char* value)
{
assert(value != NULL);
switch (hint)
{
case GLFW_X11_WM_CLASS_NAME:
strncpy(_glfwInitHints.x11.className, value,
sizeof(_glfwInitHints.x11.className) - 1);
break;
case GLFW_X11_WM_CLASS_CLASS:
strncpy(_glfwInitHints.x11.classClass, value,
sizeof(_glfwInitHints.x11.classClass) - 1);
break;
}
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid string type init hint 0x%08X", hint);
}
GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
{
if (major != NULL)
*major = GLFW_VERSION_MAJOR;
if (minor != NULL)
*minor = GLFW_VERSION_MINOR;
if (rev != NULL)
*rev = GLFW_VERSION_REVISION;
}
@@ -194,6 +287,30 @@ GLFWAPI const char* glfwGetVersionString(void)
return _glfwPlatformGetVersionString();
}
GLFWAPI int glfwGetError(const char** description)
{
_GLFWerror* error;
int code = GLFW_NO_ERROR;
if (description)
*description = NULL;
if (_glfw.initialized)
error = _glfwPlatformGetTls(&_glfw.errorSlot);
else
error = &_glfwMainThreadError;
if (error)
{
code = error->code;
error->code = GLFW_NO_ERROR;
if (description && code)
*description = error->description;
}
return code;
}
GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
{
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
+536 -37
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 - www.glfw.org
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -29,11 +29,144 @@
#include <assert.h>
#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// Internal key state used for sticky keys
#define _GLFW_STICK 3
// Internal constants for gamepad mapping source types
#define _GLFW_JOYSTICK_AXIS 1
#define _GLFW_JOYSTICK_BUTTON 2
#define _GLFW_JOYSTICK_HATBIT 3
// Finds a mapping based on joystick GUID
//
static _GLFWmapping* findMapping(const char* guid)
{
int i;
for (i = 0; i < _glfw.mappingCount; i++)
{
if (strcmp(_glfw.mappings[i].guid, guid) == 0)
return _glfw.mappings + i;
}
return NULL;
}
// Parses an SDL_GameControllerDB line and adds it to the mapping list
//
static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
{
const char* c = string;
size_t i, length;
struct
{
const char* name;
_GLFWmapelement* element;
} fields[] =
{
{ "platform", NULL },
{ "a", mapping->buttons + GLFW_GAMEPAD_BUTTON_A },
{ "b", mapping->buttons + GLFW_GAMEPAD_BUTTON_B },
{ "x", mapping->buttons + GLFW_GAMEPAD_BUTTON_X },
{ "y", mapping->buttons + GLFW_GAMEPAD_BUTTON_Y },
{ "back", mapping->buttons + GLFW_GAMEPAD_BUTTON_BACK },
{ "start", mapping->buttons + GLFW_GAMEPAD_BUTTON_START },
{ "guide", mapping->buttons + GLFW_GAMEPAD_BUTTON_GUIDE },
{ "leftshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_BUMPER },
{ "rightshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER },
{ "leftstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_THUMB },
{ "rightstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_THUMB },
{ "dpup", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_UP },
{ "dpright", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_RIGHT },
{ "dpdown", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_DOWN },
{ "dpleft", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_LEFT },
{ "lefttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_TRIGGER },
{ "righttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER },
{ "leftx", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_X },
{ "lefty", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_Y },
{ "rightx", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_X },
{ "righty", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_Y }
};
length = strcspn(c, ",");
if (length != 32 || c[length] != ',')
{
_glfwInputError(GLFW_INVALID_VALUE, NULL);
return GLFW_FALSE;
}
memcpy(mapping->guid, c, length);
c += length + 1;
length = strcspn(c, ",");
if (length >= sizeof(mapping->name) || c[length] != ',')
{
_glfwInputError(GLFW_INVALID_VALUE, NULL);
return GLFW_FALSE;
}
memcpy(mapping->name, c, length);
c += length + 1;
while (*c)
{
for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++)
{
length = strlen(fields[i].name);
if (strncmp(c, fields[i].name, length) != 0 || c[length] != ':')
continue;
c += length + 1;
if (fields[i].element)
{
if (*c == 'a')
fields[i].element->type = _GLFW_JOYSTICK_AXIS;
else if (*c == 'b')
fields[i].element->type = _GLFW_JOYSTICK_BUTTON;
else if (*c == 'h')
fields[i].element->type = _GLFW_JOYSTICK_HATBIT;
else
break;
if (fields[i].element->type == _GLFW_JOYSTICK_HATBIT)
{
const unsigned int hat = strtoul(c + 1, (char**) &c, 10);
const unsigned int bit = strtoul(c + 1, (char**) &c, 10);
fields[i].element->value = (hat << 4) | bit;
}
else
fields[i].element->value = (uint8_t) strtoul(c + 1, (char**) &c, 10);
}
else
{
length = strlen(_GLFW_PLATFORM_MAPPING_NAME);
if (strncmp(c, _GLFW_PLATFORM_MAPPING_NAME, length) != 0)
return GLFW_FALSE;
}
break;
}
c += strcspn(c, ",");
c += strspn(c, ",");
}
for (i = 0; i < 32; i++)
{
if (mapping->guid[i] >= 'A' && mapping->guid[i] <= 'F')
mapping->guid[i] += 'a' - 'A';
}
_glfwPlatformUpdateGamepadGUID(mapping->guid);
return GLFW_TRUE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW event API //////
@@ -90,7 +223,6 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
return;
// Register mouse button action
if (action == GLFW_RELEASE && window->stickyMouseButtons)
window->mouseButtons[button] = _GLFW_STICK;
else
@@ -124,10 +256,34 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
window->callbacks.drop((GLFWwindow*) window, count, paths);
}
void _glfwInputJoystickChange(int joy, int event)
void _glfwInputJoystick(_GLFWjoystick* js, int event)
{
const int jid = (int) (js - _glfw.joysticks);
if (_glfw.callbacks.joystick)
_glfw.callbacks.joystick(joy, event);
_glfw.callbacks.joystick(jid, event);
}
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
{
js->axes[axis] = value;
}
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value)
{
js->buttons[button] = value;
}
void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
{
const int base = js->buttonCount + hat * 4;
js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[base + 2] = (value & 0x04) ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE;
js->hats[hat] = value;
}
@@ -135,11 +291,47 @@ void _glfwInputJoystickChange(int joy, int event)
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwIsPrintable(int key)
_GLFWjoystick* _glfwAllocJoystick(const char* name,
const char* guid,
int axisCount,
int buttonCount,
int hatCount)
{
return (key >= GLFW_KEY_APOSTROPHE && key <= GLFW_KEY_WORLD_2) ||
(key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) ||
key == GLFW_KEY_KP_EQUAL;
int jid;
_GLFWjoystick* js;
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (!_glfw.joysticks[jid].present)
break;
}
if (jid > GLFW_JOYSTICK_LAST)
return NULL;
js = _glfw.joysticks + jid;
js->present = GLFW_TRUE;
js->name = strdup(name);
js->axes = calloc(axisCount, sizeof(float));
js->buttons = calloc(buttonCount + hatCount * 4, 1);
js->hats = calloc(hatCount, 1);
js->axisCount = axisCount;
js->buttonCount = buttonCount;
js->hatCount = hatCount;
js->mapping = findMapping(guid);
strcpy(js->guid, guid);
return js;
}
void _glfwFreeJoystick(_GLFWjoystick* js)
{
free(js->name);
free(js->axes);
free(js->buttons);
free(js->hats);
memset(js, 0, sizeof(_GLFWjoystick));
}
@@ -163,7 +355,7 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
case GLFW_STICKY_MOUSE_BUTTONS:
return window->stickyMouseButtons;
default:
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
return 0;
}
}
@@ -184,7 +376,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
value != GLFW_CURSOR_DISABLED)
{
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid cursor mode %i",
"Invalid cursor mode 0x%08X",
value);
return;
}
@@ -247,13 +439,39 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
}
}
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
}
GLFWAPI const char* glfwGetKeyName(int key, int scancode)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return _glfwPlatformGetKeyName(key, scancode);
if (key != GLFW_KEY_UNKNOWN)
{
if (key != GLFW_KEY_KP_EQUAL &&
(key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
(key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2))
{
return NULL;
}
scancode = _glfwPlatformGetKeyScancode(key);
}
return _glfwPlatformGetScancodeName(scancode);
}
GLFWAPI int glfwGetKeyScancode(int key)
{
_GLFW_REQUIRE_INIT_OR_RETURN(-1);
if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
return GLFW_RELEASE;
}
return _glfwPlatformGetKeyScancode(key);
}
GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
@@ -332,11 +550,11 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
_GLFW_REQUIRE_INIT();
if (xpos != xpos || xpos < DBL_MIN || xpos > DBL_MAX ||
ypos != ypos || ypos < DBL_MIN || ypos > DBL_MAX)
if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX ||
ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX)
{
_glfwInputError(GLFW_INVALID_VALUE,
"Invalid cursor position %fx%f",
"Invalid cursor position %f %f",
xpos, ypos);
return;
}
@@ -391,7 +609,7 @@ GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
shape != GLFW_HRESIZE_CURSOR &&
shape != GLFW_VRESIZE_CURSOR)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor %i", shape);
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor 0x%08X", shape);
return NULL;
}
@@ -540,62 +758,167 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
return cbfun;
}
GLFWAPI int glfwJoystickPresent(int joy)
GLFWAPI int glfwJoystickPresent(int jid)
{
_GLFW_REQUIRE_INIT_OR_RETURN(0);
_GLFWjoystick* js;
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
assert(jid >= GLFW_JOYSTICK_1);
assert(jid <= GLFW_JOYSTICK_LAST);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
return 0;
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
return GLFW_FALSE;
}
return _glfwPlatformJoystickPresent(joy);
js = _glfw.joysticks + jid;
if (!js->present)
return GLFW_FALSE;
return _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
}
GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count)
GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
{
_GLFWjoystick* js;
assert(jid >= GLFW_JOYSTICK_1);
assert(jid <= GLFW_JOYSTICK_LAST);
assert(count != NULL);
*count = 0;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
return NULL;
}
return _glfwPlatformGetJoystickAxes(joy, count);
js = _glfw.joysticks + jid;
if (!js->present)
return NULL;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_AXES))
return NULL;
*count = js->axisCount;
return js->axes;
}
GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count)
GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
{
_GLFWjoystick* js;
assert(jid >= GLFW_JOYSTICK_1);
assert(jid <= GLFW_JOYSTICK_LAST);
assert(count != NULL);
*count = 0;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
return NULL;
}
return _glfwPlatformGetJoystickButtons(joy, count);
js = _glfw.joysticks + jid;
if (!js->present)
return NULL;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
return NULL;
if (_glfw.hints.init.hatButtons)
*count = js->buttonCount + js->hatCount * 4;
else
*count = js->buttonCount;
return js->buttons;
}
GLFWAPI const char* glfwGetJoystickName(int joy)
GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
{
_GLFWjoystick* js;
assert(jid >= GLFW_JOYSTICK_1);
assert(jid <= GLFW_JOYSTICK_LAST);
assert(count != NULL);
*count = 0;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
return NULL;
}
return _glfwPlatformGetJoystickName(joy);
js = _glfw.joysticks + jid;
if (!js->present)
return NULL;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
return NULL;
*count = js->hatCount;
return js->hats;
}
GLFWAPI const char* glfwGetJoystickName(int jid)
{
_GLFWjoystick* js;
assert(jid >= GLFW_JOYSTICK_1);
assert(jid <= GLFW_JOYSTICK_LAST);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
return NULL;
}
js = _glfw.joysticks + jid;
if (!js->present)
return NULL;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
return NULL;
return js->name;
}
GLFWAPI const char* glfwGetJoystickGUID(int jid)
{
_GLFWjoystick* js;
assert(jid >= GLFW_JOYSTICK_1);
assert(jid <= GLFW_JOYSTICK_LAST);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
return NULL;
}
js = _glfw.joysticks + jid;
if (!js->present)
return NULL;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
return NULL;
return js->guid;
}
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
@@ -605,6 +928,182 @@ GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
return cbfun;
}
GLFWAPI int glfwUpdateGamepadMappings(const char* string)
{
int jid;
const char* c = string;
assert(string != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
while (*c)
{
if (isxdigit(*c))
{
char line[1024];
const size_t length = strcspn(c, "\r\n");
if (length < sizeof(line))
{
_GLFWmapping mapping = {{0}};
memcpy(line, c, length);
line[length] = '\0';
if (parseMapping(&mapping, line))
{
_GLFWmapping* previous = findMapping(mapping.guid);
if (previous)
*previous = mapping;
else
{
_glfw.mappingCount++;
_glfw.mappings =
realloc(_glfw.mappings,
sizeof(_GLFWmapping) * _glfw.mappingCount);
_glfw.mappings[_glfw.mappingCount - 1] = mapping;
}
}
}
c += length;
}
else
{
c += strcspn(c, "\r\n");
c += strspn(c, "\r\n");
}
}
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
_GLFWjoystick* js = _glfw.joysticks + jid;
if (js->present)
js->mapping = findMapping(js->guid);
}
return GLFW_TRUE;
}
GLFWAPI int glfwJoystickIsGamepad(int jid)
{
_GLFWjoystick* js;
assert(jid >= GLFW_JOYSTICK_1);
assert(jid <= GLFW_JOYSTICK_LAST);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
return GLFW_FALSE;
}
js = _glfw.joysticks + jid;
if (!js->present)
return GLFW_FALSE;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
return GLFW_FALSE;
return js->mapping != NULL;
}
GLFWAPI const char* glfwGetGamepadName(int jid)
{
_GLFWjoystick* js;
assert(jid >= GLFW_JOYSTICK_1);
assert(jid <= GLFW_JOYSTICK_LAST);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
return NULL;
}
js = _glfw.joysticks + jid;
if (!js->present)
return NULL;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
return NULL;
if (!js->mapping)
return NULL;
return js->mapping->name;
}
GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
{
int i;
_GLFWjoystick* js;
assert(jid >= GLFW_JOYSTICK_1);
assert(jid <= GLFW_JOYSTICK_LAST);
assert(state != NULL);
memset(state, 0, sizeof(GLFWgamepadstate));
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
return GLFW_FALSE;
}
js = _glfw.joysticks + jid;
if (!js->present)
return GLFW_FALSE;
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_ALL))
return GLFW_FALSE;
if (!js->mapping)
return GLFW_FALSE;
for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
{
if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_AXIS)
{
if (fabs(js->axes[js->mapping->buttons[i].value]) > 0.5)
state->buttons[i] = GLFW_PRESS;
}
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_HATBIT)
{
const unsigned int hat = js->mapping->buttons[i].value >> 4;
const unsigned int bit = js->mapping->buttons[i].value & 0xf;
if (js->hats[hat] & bit)
state->buttons[i] = GLFW_PRESS;
}
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_BUTTON)
state->buttons[i] = js->buttons[js->mapping->buttons[i].value];
}
for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++)
{
if (js->mapping->axes[i].type == _GLFW_JOYSTICK_AXIS)
state->axes[i] = js->axes[js->mapping->axes[i].value];
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_HATBIT)
{
const unsigned int hat = js->mapping->buttons[i].value >> 4;
const unsigned int bit = js->mapping->buttons[i].value & 0xf;
if (js->hats[hat] & bit)
state->axes[i] = 1.f;
}
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_BUTTON)
state->axes[i] = (float) js->buttons[js->mapping->axes[i].value];
}
return GLFW_TRUE;
}
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
@@ -627,7 +1126,7 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
GLFWAPI double glfwGetTime(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
return (double) (_glfwPlatformGetTimerValue() - _glfw.timerOffset) /
return (double) (_glfwPlatformGetTimerValue() - _glfw.timer.offset) /
_glfwPlatformGetTimerFrequency();
}
@@ -641,7 +1140,7 @@ GLFWAPI void glfwSetTime(double time)
return;
}
_glfw.timerOffset = _glfwPlatformGetTimerValue() -
_glfw.timer.offset = _glfwPlatformGetTimerValue() -
(uint64_t) (time * _glfwPlatformGetTimerFrequency());
}
+262 -306
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 - www.glfw.org
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -25,10 +25,6 @@
//
//========================================================================
#ifndef _glfw3_internal_h_
#define _glfw3_internal_h_
#if defined(_GLFW_USE_CONFIG_H)
#include "glfw_config.h"
#endif
@@ -37,9 +33,12 @@
defined(GLFW_INCLUDE_ES1) || \
defined(GLFW_INCLUDE_ES2) || \
defined(GLFW_INCLUDE_ES3) || \
defined(GLFW_INCLUDE_ES31) || \
defined(GLFW_INCLUDE_ES32) || \
defined(GLFW_INCLUDE_NONE) || \
defined(GLFW_INCLUDE_GLEXT) || \
defined(GLFW_INCLUDE_GLU) || \
defined(GLFW_INCLUDE_VULKAN) || \
defined(GLFW_DLL)
#error "You must not define any header option macros when compiling GLFW"
#endif
@@ -47,8 +46,18 @@
#define GLFW_INCLUDE_NONE
#include "../include/GLFW/glfw3.h"
#define _GLFW_INSERT_FIRST 0
#define _GLFW_INSERT_LAST 1
#define _GLFW_POLL_PRESENCE 0
#define _GLFW_POLL_AXES 1
#define _GLFW_POLL_BUTTONS 2
#define _GLFW_POLL_ALL (_GLFW_POLL_AXES | _GLFW_POLL_BUTTONS)
typedef int GLFWbool;
typedef struct _GLFWerror _GLFWerror;
typedef struct _GLFWinitconfig _GLFWinitconfig;
typedef struct _GLFWwndconfig _GLFWwndconfig;
typedef struct _GLFWctxconfig _GLFWctxconfig;
typedef struct _GLFWfbconfig _GLFWfbconfig;
@@ -57,6 +66,11 @@ typedef struct _GLFWwindow _GLFWwindow;
typedef struct _GLFWlibrary _GLFWlibrary;
typedef struct _GLFWmonitor _GLFWmonitor;
typedef struct _GLFWcursor _GLFWcursor;
typedef struct _GLFWmapelement _GLFWmapelement;
typedef struct _GLFWmapping _GLFWmapping;
typedef struct _GLFWjoystick _GLFWjoystick;
typedef struct _GLFWtls _GLFWtls;
typedef struct _GLFWmutex _GLFWmutex;
typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
@@ -68,6 +82,7 @@ typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
#define GL_VERSION 0x1f02
#define GL_NONE 0
#define GL_COLOR_BUFFER_BIT 0x00004000
#define GL_UNSIGNED_BYTE 0x1401
#define GL_EXTENSIONS 0x1f03
#define GL_NUM_EXTENSIONS 0x821d
#define GL_CONTEXT_FLAGS 0x821e
@@ -109,6 +124,7 @@ typedef enum VkStructureType
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000053000,
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
} VkStructureType;
@@ -149,11 +165,16 @@ typedef struct VkExtensionProperties
} VkExtensionProperties;
typedef void (APIENTRY * PFN_vkVoidFunction)(void);
typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*);
typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*);
#define vkEnumerateInstanceExtensionProperties _glfw.vk.EnumerateInstanceExtensionProperties
#define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr
#if defined(_GLFW_VULKAN_STATIC)
PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance,const char*);
VkResult vkEnumerateInstanceExtensionProperties(const char*,uint32_t*,VkExtensionProperties*);
#else
typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*);
typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*);
#define vkEnumerateInstanceExtensionProperties _glfw.vk.EnumerateInstanceExtensionProperties
#define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr
#endif
#if defined(_GLFW_COCOA)
#include "cocoa_platform.h"
@@ -165,6 +186,8 @@ typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const c
#include "wl_platform.h"
#elif defined(_GLFW_MIR)
#include "mir_platform.h"
#elif defined(_GLFW_OSMESA)
#include "null_platform.h"
#else
#error "No supported window creation API selected"
#endif
@@ -210,13 +233,13 @@ typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const c
// Checks for whether the library has been initialized
#define _GLFW_REQUIRE_INIT() \
if (!_glfwInitialized) \
if (!_glfw.initialized) \
{ \
_glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
return; \
}
#define _GLFW_REQUIRE_INIT_OR_RETURN(x) \
if (!_glfwInitialized) \
if (!_glfw.initialized) \
{ \
_glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
return x; \
@@ -236,6 +259,30 @@ typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const c
// Platform-independent structures
//========================================================================
struct _GLFWerror
{
_GLFWerror* next;
int code;
char description[1024];
};
/*! @brief Initialization configuration.
*
* Parameters relating to the initialization of the library.
*/
struct _GLFWinitconfig
{
GLFWbool hatButtons;
struct {
GLFWbool menubar;
GLFWbool chdir;
} ns;
struct {
char className[256];
char classClass[256];
} x11;
};
/*! @brief Window configuration.
*
* Parameters relating to the creation of the window but not directly related
@@ -254,9 +301,13 @@ struct _GLFWwndconfig
GLFWbool autoIconify;
GLFWbool floating;
GLFWbool maximized;
GLFWbool centerCursor;
struct {
GLFWbool retina;
GLFWbool frame;
} ns;
};
/*! @brief Context configuration.
*
* Parameters relating to the creation of the context but not directly related
@@ -276,9 +327,11 @@ struct _GLFWctxconfig
int robustness;
int release;
_GLFWwindow* share;
struct {
GLFWbool offline;
} nsgl;
};
/*! @brief Framebuffer configuration.
*
* This describes buffers and their sizes. It also contains
@@ -307,7 +360,6 @@ struct _GLFWfbconfig
uintptr_t handle;
};
/*! @brief Context structure.
*/
struct _GLFWcontext
@@ -335,9 +387,10 @@ struct _GLFWcontext
_GLFW_PLATFORM_CONTEXT_STATE;
// This is defined in egl_context.h
_GLFW_EGL_CONTEXT_STATE;
// This is defined in osmesa_context.h
_GLFW_OSMESA_CONTEXT_STATE;
};
/*! @brief Window and context structure.
*/
struct _GLFWwindow
@@ -349,7 +402,7 @@ struct _GLFWwindow
GLFWbool decorated;
GLFWbool autoIconify;
GLFWbool floating;
GLFWbool closed;
GLFWbool shouldClose;
void* userPointer;
GLFWvidmode videoMode;
_GLFWmonitor* monitor;
@@ -376,6 +429,7 @@ struct _GLFWwindow
GLFWwindowrefreshfun refresh;
GLFWwindowfocusfun focus;
GLFWwindowiconifyfun iconify;
GLFWwindowmaximizefun maximize;
GLFWframebuffersizefun fbsize;
GLFWmousebuttonfun mouseButton;
GLFWcursorposfun cursorPos;
@@ -391,7 +445,6 @@ struct _GLFWwindow
_GLFW_PLATFORM_WINDOW_STATE;
};
/*! @brief Monitor structure.
*/
struct _GLFWmonitor
@@ -415,7 +468,6 @@ struct _GLFWmonitor
_GLFW_PLATFORM_MONITOR_STATE;
};
/*! @brief Cursor structure
*/
struct _GLFWcursor
@@ -426,39 +478,115 @@ struct _GLFWcursor
_GLFW_PLATFORM_CURSOR_STATE;
};
/*! @brief Gamepad mapping element structure
*/
struct _GLFWmapelement
{
uint8_t type;
uint8_t value;
};
/*! @brief Gamepad mapping structure
*/
struct _GLFWmapping
{
char name[128];
char guid[33];
_GLFWmapelement buttons[15];
_GLFWmapelement axes[6];
};
/*! @brief Joystick structure
*/
struct _GLFWjoystick
{
GLFWbool present;
float* axes;
int axisCount;
unsigned char* buttons;
int buttonCount;
unsigned char* hats;
int hatCount;
char* name;
char guid[33];
_GLFWmapping* mapping;
// This is defined in the joystick API's joystick.h
_GLFW_PLATFORM_JOYSTICK_STATE;
};
/*! @brief Thread local storage structure.
*/
struct _GLFWtls
{
// This is defined in the platform's thread.h
_GLFW_PLATFORM_TLS_STATE;
};
/*! @brief Mutex structure.
*/
struct _GLFWmutex
{
// This is defined in the platform's thread.h
_GLFW_PLATFORM_MUTEX_STATE;
};
/*! @brief Library global data.
*/
struct _GLFWlibrary
{
GLFWbool initialized;
struct {
_GLFWinitconfig init;
_GLFWfbconfig framebuffer;
_GLFWwndconfig window;
_GLFWctxconfig context;
int refreshRate;
} hints;
_GLFWerror* errorListHead;
_GLFWcursor* cursorListHead;
_GLFWwindow* windowListHead;
_GLFWmonitor** monitors;
int monitorCount;
uint64_t timerOffset;
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
_GLFWmapping* mappings;
int mappingCount;
_GLFWtls errorSlot;
_GLFWtls contextSlot;
_GLFWmutex errorLock;
struct {
uint64_t offset;
// This is defined in the platform's time.h
_GLFW_PLATFORM_LIBRARY_TIMER_STATE;
} timer;
struct {
GLFWbool available;
void* handle;
char** extensions;
uint32_t extensionCount;
char* extensions[2];
#if !defined(_GLFW_VULKAN_STATIC)
PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
#endif
GLFWbool KHR_surface;
#if defined(_GLFW_WIN32)
GLFWbool KHR_win32_surface;
#elif defined(_GLFW_COCOA)
GLFWbool MVK_macos_surface;
#elif defined(_GLFW_X11)
GLFWbool KHR_xlib_surface;
GLFWbool KHR_xcb_surface;
#elif defined(_GLFW_WAYLAND)
GLFWbool KHR_wayland_surface;
#elif defined(_GLFW_MIR)
GLFWbool KHR_mir_surface;
#endif
} vk;
struct {
@@ -470,14 +598,12 @@ struct _GLFWlibrary
_GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
// This is defined in the context API's context.h
_GLFW_PLATFORM_LIBRARY_CONTEXT_STATE;
// This is defined in the platform's time.h
_GLFW_PLATFORM_LIBRARY_TIME_STATE;
// This is defined in the platform's joystick.h
_GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE;
// This is defined in the platform's tls.h
_GLFW_PLATFORM_LIBRARY_TLS_STATE;
// This is defined in egl_context.h
_GLFW_EGL_LIBRARY_CONTEXT_STATE;
// This is defined in osmesa_context.h
_GLFW_OSMESA_LIBRARY_CONTEXT_STATE;
};
@@ -485,13 +611,7 @@ struct _GLFWlibrary
// Global state shared between compilation units of GLFW
//========================================================================
/*! @brief Flag indicating whether GLFW has been successfully initialized.
*/
extern GLFWbool _glfwInitialized;
/*! @brief All global data protected by @ref _glfwInitialized.
* This should only be touched after a call to @ref glfwInit that has not been
* followed by a call to @ref glfwTerminate.
/*! @brief All global data shared between compilation units.
*/
extern _GLFWlibrary _glfw;
@@ -500,312 +620,97 @@ extern _GLFWlibrary _glfw;
// Platform API functions
//========================================================================
/*! @brief Initializes the platform-specific part of the library.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an error occurred.
* @ingroup platform
*/
/*! @addtogroup platform @{ */
int _glfwPlatformInit(void);
/*! @brief Terminates the platform-specific part of the library.
* @ingroup platform
*/
void _glfwPlatformTerminate(void);
/*! @copydoc glfwGetVersionString
* @ingroup platform
*
* @note The returned string must be available for the duration of the program.
*
* @note The returned string must not change for the duration of the program.
*/
const char* _glfwPlatformGetVersionString(void);
/*! @copydoc glfwGetCursorPos
* @ingroup platform
*/
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos);
/*! @copydoc glfwSetCursorPos
* @ingroup platform
*/
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos);
/*! @brief Sets the specified cursor mode of the specified window.
* @param[in] window The window whose cursor mode to set.
* @ingroup platform
*/
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape);
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
/*! @copydoc glfwGetKeyName
* @ingroup platform
*/
const char* _glfwPlatformGetKeyName(int key, int scancode);
const char* _glfwPlatformGetScancodeName(int scancode);
int _glfwPlatformGetKeyScancode(int key);
/*! @copydoc glfwGetMonitors
* @ingroup platform
*/
_GLFWmonitor** _glfwPlatformGetMonitors(int* count);
/*! @brief Checks whether two monitor objects represent the same monitor.
*
* @param[in] first The first monitor.
* @param[in] second The second monitor.
* @return @c GLFW_TRUE if the monitor objects represent the same monitor, or
* @c GLFW_FALSE otherwise.
* @ingroup platform
*/
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second);
/*! @copydoc glfwGetMonitorPos
* @ingroup platform
*/
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
/*! @copydoc glfwGetVideoModes
* @ingroup platform
*/
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
/*! @ingroup platform
*/
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
/*! @copydoc glfwGetGammaRamp
* @ingroup platform
*/
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
/*! @copydoc glfwSetGammaRamp
* @ingroup platform
*/
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
/*! @copydoc glfwSetClipboardString
* @ingroup platform
*/
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string);
/*! @copydoc glfwGetClipboardString
* @ingroup platform
*
* @note The returned string must be valid until the next call to @ref
* _glfwPlatformGetClipboardString or @ref _glfwPlatformSetClipboardString.
*/
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window);
/*! @copydoc glfwJoystickPresent
* @ingroup platform
*/
int _glfwPlatformJoystickPresent(int joy);
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
void _glfwPlatformUpdateGamepadGUID(char* guid);
/*! @copydoc glfwGetJoystickAxes
* @ingroup platform
*/
const float* _glfwPlatformGetJoystickAxes(int joy, int* count);
/*! @copydoc glfwGetJoystickButtons
* @ingroup platform
*/
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count);
/*! @copydoc glfwGetJoystickName
* @ingroup platform
*/
const char* _glfwPlatformGetJoystickName(int joy);
/*! @copydoc glfwGetTimerValue
* @ingroup platform
*/
uint64_t _glfwPlatformGetTimerValue(void);
/*! @copydoc glfwGetTimerFrequency
* @ingroup platform
*/
uint64_t _glfwPlatformGetTimerFrequency(void);
/*! @ingroup platform
*/
int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig);
/*! @ingroup platform
*/
void _glfwPlatformDestroyWindow(_GLFWwindow* window);
/*! @copydoc glfwSetWindowTitle
* @ingroup platform
*/
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title);
/*! @copydoc glfwSetWindowIcon
* @ingroup platform
*/
void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count, const GLFWimage* images);
/*! @copydoc glfwGetWindowPos
* @ingroup platform
*/
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos);
/*! @copydoc glfwSetWindowPos
* @ingroup platform
*/
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos);
/*! @copydoc glfwGetWindowSize
* @ingroup platform
*/
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height);
/*! @copydoc glfwSetWindowSize
* @ingroup platform
*/
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height);
/*! @copydoc glfwSetWindowSizeLimits
* @ingroup platform
*/
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight);
/*! @copydoc glfwSetWindowAspectRatio
* @ingroup platform
*/
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
/*! @copydoc glfwGetFramebufferSize
* @ingroup platform
*/
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
/*! @copydoc glfwGetWindowFrameSize
* @ingroup platform
*/
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, int* left, int* top, int* right, int* bottom);
/*! @copydoc glfwIconifyWindow
* @ingroup platform
*/
void _glfwPlatformIconifyWindow(_GLFWwindow* window);
/*! @copydoc glfwRestoreWindow
* @ingroup platform
*/
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
/*! @copydoc glfwMaximizeWindow
* @ingroup platform
*/
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
/*! @copydoc glfwShowWindow
* @ingroup platform
*/
void _glfwPlatformShowWindow(_GLFWwindow* window);
/*! @copydoc glfwHideWindow
* @ingroup platform
*/
void _glfwPlatformHideWindow(_GLFWwindow* window);
/*! @copydoc glfwFocusWindow
* @ingroup platform
*/
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window);
void _glfwPlatformFocusWindow(_GLFWwindow* window);
/*! @copydoc glfwSetWindowMonitor
* @ingroup platform
*/
void _glfwPlatformDragWindow(_GLFWwindow* window);
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
/*! @brief Returns whether the window is focused.
* @ingroup platform
*/
int _glfwPlatformWindowFocused(_GLFWwindow* window);
/*! @brief Returns whether the window is iconified.
* @ingroup platform
*/
int _glfwPlatformWindowIconified(_GLFWwindow* window);
/*! @brief Returns whether the window is visible.
* @ingroup platform
*/
int _glfwPlatformWindowVisible(_GLFWwindow* window);
/*! @brief Returns whether the window is maximized.
* @ingroup platform
*/
int _glfwPlatformWindowMaximized(_GLFWwindow* window);
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
/*! @copydoc glfwPollEvents
* @ingroup platform
*/
void _glfwPlatformPollEvents(void);
/*! @copydoc glfwWaitEvents
* @ingroup platform
*/
void _glfwPlatformWaitEvents(void);
/*! @copydoc glfwWaitEventsTimeout
* @ingroup platform
*/
void _glfwPlatformWaitEventsTimeout(double timeout);
/*! @copydoc glfwPostEmptyEvent
* @ingroup platform
*/
void _glfwPlatformPostEmptyEvent(void);
/*! @ingroup platform
*/
void _glfwPlatformSetCurrentContext(_GLFWwindow* context);
/*! @copydoc glfwGetCurrentContext
* @ingroup platform
*/
_GLFWwindow* _glfwPlatformGetCurrentContext(void);
/*! @copydoc glfwCreateCursor
* @ingroup platform
*/
int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
/*! @copydoc glfwCreateStandardCursor
* @ingroup platform
*/
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape);
/*! @copydoc glfwDestroyCursor
* @ingroup platform
*/
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
/*! @copydoc glfwSetCursor
* @ingroup platform
*/
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
/*! @ingroup platform
*/
char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count);
/*! @ingroup platform
*/
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
/*! @ingroup platform
*/
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls);
void _glfwPlatformDestroyTls(_GLFWtls* tls);
void* _glfwPlatformGetTls(_GLFWtls* tls);
void _glfwPlatformSetTls(_GLFWtls* tls, void* value);
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex);
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex);
void _glfwPlatformLockMutex(_GLFWmutex* mutex);
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
/*! @} */
//========================================================================
// Event API functions
//========================================================================
/*! @brief Notifies shared code of a window focus event.
/*! @brief Notifies shared code that a window has lost or received input focus.
* @param[in] window The window that received the event.
* @param[in] focused `GLFW_TRUE` if the window received focus, or `GLFW_FALSE`
* if it lost focus.
@@ -813,7 +718,7 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, _GLFWwindow* wind
*/
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
/*! @brief Notifies shared code of a window movement event.
/*! @brief Notifies shared code that a window has moved.
* @param[in] window The window that received the event.
* @param[in] xpos The new x-coordinate of the client area of the window.
* @param[in] ypos The new y-coordinate of the client area of the window.
@@ -821,7 +726,7 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
*/
void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
/*! @brief Notifies shared code of a window resize event.
/*! @brief Notifies shared code that a window has been resized.
* @param[in] window The window that received the event.
* @param[in] width The new width of the client area of the window.
* @param[in] height The new height of the client area of the window.
@@ -829,7 +734,7 @@ void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
*/
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
/*! @brief Notifies shared code of a framebuffer resize event.
/*! @brief Notifies shared code that a window framebuffer has been resized.
* @param[in] window The window that received the event.
* @param[in] width The new width, in pixels, of the framebuffer.
* @param[in] height The new height, in pixels, of the framebuffer.
@@ -837,7 +742,7 @@ void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
*/
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
/*! @brief Notifies shared code of a window iconification event.
/*! @brief Notifies shared code that a window has been iconified or restored.
* @param[in] window The window that received the event.
* @param[in] iconified `GLFW_TRUE` if the window was iconified, or
* `GLFW_FALSE` if it was restored.
@@ -845,17 +750,30 @@ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
*/
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
/*! @brief Notifies shared code of a window damage event.
/*! @brief Notifies shared code that a window has been maximized or restored.
* @param[in] window The window that received the event.
* @param[in] maximized `GLFW_TRUE` if the window was maximized, or
* `GLFW_FALSE` if it was restored.
* @ingroup event
*/
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized);
/*! @brief Notifies shared code that a window's contents needs updating.
* @param[in] window The window that received the event.
*/
void _glfwInputWindowDamage(_GLFWwindow* window);
/*! @brief Notifies shared code of a window close request event
/*! @brief Notifies shared code that the user wishes to close a window.
* @param[in] window The window that received the event.
* @ingroup event
*/
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
/*! @brief Notifies shared code that a window has changed its desired monitor.
* @param[in] window The window that received the event.
* @param[in] monitor The new desired monitor, or `NULL`.
* @ingroup event
*/
void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor);
/*! @brief Notifies shared code of a physical key event.
@@ -890,6 +808,7 @@ void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
* @param[in] window The window that received the event.
* @param[in] button The button that was pressed or released.
* @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE.
* @param[in] mods The modifiers pressed when the event was generated.
* @ingroup event
*/
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
@@ -912,27 +831,35 @@ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
*/
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
/*! @ingroup event
/*! @brief Notifies shared code of a monitor connection or disconnection.
* @param[in] monitor The monitor that was connected or disconnected.
* @param[in] action One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
* @param[in] placement `_GLFW_INSERT_FIRST` or `_GLFW_INSERT_LAST`.
* @ingroup event
*/
void _glfwInputMonitorChange(void);
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement);
/*! @ingroup event
/*! @brief Notifies shared code that a full screen window has acquired or
* released a monitor.
* @param[in] monitor The monitor that was acquired or released.
* @param[in] window The window that acquired the monitor, or `NULL`.
* @ingroup event
*/
void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window);
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);
/*! @brief Notifies shared code of an error.
* @param[in] error The error code most suitable for the error.
* @param[in] code The error code most suitable for the error.
* @param[in] format The `printf` style format string of the error
* description.
* @ingroup event
*/
#if defined(__GNUC__)
void _glfwInputError(int error, const char* format, ...) __attribute__((format(printf, 2, 3)));
void _glfwInputError(int code, const char* format, ...) __attribute__((format(printf, 2, 3)));
#else
void _glfwInputError(int error, const char* format, ...);
void _glfwInputError(int code, const char* format, ...);
#endif
/*! @brief Notifies dropped object over window.
/*! @brief Notifies shared code of files or directories dropped on a window.
* @param[in] window The window that received the event.
* @param[in] count The number of dropped objects.
* @param[in] names The names of the dropped objects.
@@ -940,19 +867,41 @@ void _glfwInputError(int error, const char* format, ...);
*/
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
/*! @brief Notifies shared code of a joystick connection/disconnection event.
* @param[in] joy The joystick that was connected or disconnected.
/*! @brief Notifies shared code of a joystick connection or disconnection.
* @param[in] js The joystick that was connected or disconnected.
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
* @ingroup event
*/
void _glfwInputJoystickChange(int joy, int event);
void _glfwInputJoystick(_GLFWjoystick* js, int event);
/*! @brief Notifies shared code of the new value of a joystick axis.
* @param[in] js The joystick whose axis to update.
* @param[in] axis The index of the axis to update.
* @param[in] value The new value of the axis.
*/
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
/*! @brief Notifies shared code of the new value of a joystick button.
* @param[in] js The joystick whose button to update.
* @param[in] button The index of the button to update.
* @param[in] value The new value of the button.
*/
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
/*! @brief Notifies shared code of the new value of a joystick hat.
* @param[in] js The joystick whose hat to update.
* @param[in] button The index of the hat to update.
* @param[in] value The new value of the hat.
*/
void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value);
//========================================================================
// Utility functions
//========================================================================
/*! @ingroup utility
/*! @brief Chooses the video mode most closely matching the desired one.
* @ingroup utility
*/
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
const GLFWvidmode* desired);
@@ -1007,11 +956,13 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig);
*/
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
/*! @ingroup utility
/*! @brief Allocates red, green and blue value arrays of the specified size.
* @ingroup utility
*/
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size);
/*! @ingroup utility
/*! @brief Frees the red, green and blue value arrays and clears the struct.
* @ingroup utility
*/
void _glfwFreeGammaArrays(GLFWgammaramp* ramp);
@@ -1030,17 +981,23 @@ _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM);
*/
void _glfwFreeMonitor(_GLFWmonitor* monitor);
/*! @ingroup utility
/*! @brief Returns an available joystick object with arrays and name allocated.
* @ingroup utility
*/
void _glfwFreeMonitors(_GLFWmonitor** monitors, int count);
_GLFWjoystick* _glfwAllocJoystick(const char* name,
const char* guid,
int axisCount,
int buttonCount,
int hatCount);
/*! @brief Frees arrays and name and flags the joystick object as unused.
* @ingroup utility
*/
void _glfwFreeJoystick(_GLFWjoystick* js);
/*! @ingroup utility
*/
GLFWbool _glfwIsPrintable(int key);
/*! @ingroup utility
*/
void _glfwInitVulkan(void);
GLFWbool _glfwInitVulkan(int mode);
/*! @ingroup utility
*/
@@ -1050,4 +1007,3 @@ void _glfwTerminateVulkan(void);
*/
const char* _glfwGetVulkanResultString(VkResult result);
#endif // _glfw3_internal_h_
+266 -164
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 Linux - www.glfw.org
// GLFW 3.3 Linux - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -27,9 +27,6 @@
#include "internal.h"
#if defined(__linux__)
#include <linux/joystick.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/inotify.h>
@@ -40,129 +37,220 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif // __linux__
// Apply an EV_KEY event to the specified joystick
//
static void handleKeyEvent(_GLFWjoystick* js, int code, int value)
{
_glfwInputJoystickButton(js,
js->linjs.keyMap[code - BTN_MISC],
value ? GLFW_PRESS : GLFW_RELEASE);
}
// Apply an EV_ABS event to the specified joystick
//
static void handleAbsEvent(_GLFWjoystick* js, int code, int value)
{
const int index = js->linjs.absMap[code];
if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
{
static const char stateMap[3][3] =
{
{ GLFW_HAT_CENTERED, GLFW_HAT_UP, GLFW_HAT_DOWN },
{ GLFW_HAT_LEFT, GLFW_HAT_LEFT_UP, GLFW_HAT_LEFT_DOWN },
{ GLFW_HAT_RIGHT, GLFW_HAT_RIGHT_UP, GLFW_HAT_RIGHT_DOWN },
};
const int hat = (code - ABS_HAT0X) / 2;
const int axis = (code - ABS_HAT0X) % 2;
int* state = js->linjs.hats[hat];
// NOTE: Looking at several input drivers, it seems all hat events use
// -1 for left / up, 0 for centered and 1 for right / down
if (value == 0)
state[axis] = 0;
else if (value < 0)
state[axis] = 1;
else if (value > 0)
state[axis] = 2;
_glfwInputJoystickHat(js, index, stateMap[state[0]][state[1]]);
}
else
{
const struct input_absinfo* info = &js->linjs.absInfo[code];
float normalized = value;
const int range = info->maximum - info->minimum;
if (range)
{
// Normalize to 0.0 -> 1.0
normalized = (normalized - info->minimum) / range;
// Normalize to -1.0 -> 1.0
normalized = normalized * 2.0f - 1.0f;
}
_glfwInputJoystickAxis(js, index, normalized);
}
}
// Poll state of absolute axes
//
static void pollAbsState(_GLFWjoystick* js)
{
int code;
for (code = 0; code < ABS_CNT; code++)
{
if (js->linjs.absMap[code] < 0)
continue;
struct input_absinfo* info = &js->linjs.absInfo[code];
if (ioctl(js->linjs.fd, EVIOCGABS(code), info) < 0)
continue;
handleAbsEvent(js, code, info->value);
}
}
#define isBitSet(bit, arr) (arr[(bit) / 8] & (1 << ((bit) % 8)))
// Attempt to open the specified joystick device
//
#if defined(__linux__)
static GLFWbool openJoystickDevice(const char* path)
{
char axisCount, buttonCount;
char name[256];
int joy, fd, version;
_GLFWjoystickLinux* js;
int jid, code;
char name[256] = "";
char guid[33] = "";
char evBits[(EV_CNT + 7) / 8] = {0};
char keyBits[(KEY_CNT + 7) / 8] = {0};
char absBits[(ABS_CNT + 7) / 8] = {0};
int axisCount = 0, buttonCount = 0, hatCount = 0;
struct input_id id;
_GLFWjoystickLinux linjs = {0};
_GLFWjoystick* js = NULL;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (!_glfw.linux_js.js[joy].present)
if (!_glfw.joysticks[jid].present)
continue;
if (strcmp(_glfw.linux_js.js[joy].path, path) == 0)
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
return GLFW_FALSE;
}
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
if (!_glfw.linux_js.js[joy].present)
break;
}
if (joy > GLFW_JOYSTICK_LAST)
linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
if (linjs.fd == -1)
return GLFW_FALSE;
fd = open(path, O_RDONLY | O_NONBLOCK);
if (fd == -1)
return GLFW_FALSE;
// Verify that the joystick driver version is at least 1.0
ioctl(fd, JSIOCGVERSION, &version);
if (version < 0x010000)
if (ioctl(linjs.fd, EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 ||
ioctl(linjs.fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) < 0 ||
ioctl(linjs.fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) < 0 ||
ioctl(linjs.fd, EVIOCGID, &id) < 0)
{
// It's an old 0.x interface (we don't support it)
close(fd);
_glfwInputError(GLFW_PLATFORM_ERROR,
"Linux: Failed to query input device: %s",
strerror(errno));
close(linjs.fd);
return GLFW_FALSE;
}
if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
// Ensure this device supports the events expected of a joystick
if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))
{
close(linjs.fd);
return GLFW_FALSE;
}
if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
strncpy(name, "Unknown", sizeof(name));
js = _glfw.linux_js.js + joy;
js->present = GLFW_TRUE;
js->name = strdup(name);
js->path = strdup(path);
js->fd = fd;
// Generate a joystick GUID that matches the SDL 2.0.5+ one
if (id.vendor && id.product && id.version)
{
sprintf(guid, "%02x%02x0000%02x%02x0000%02x%02x0000%02x%02x0000",
id.bustype & 0xff, id.bustype >> 8,
id.vendor & 0xff, id.vendor >> 8,
id.product & 0xff, id.product >> 8,
id.version & 0xff, id.version >> 8);
}
else
{
sprintf(guid, "%02x%02x0000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
id.bustype & 0xff, id.bustype >> 8,
name[0], name[1], name[2], name[3],
name[4], name[5], name[6], name[7],
name[8], name[9], name[10]);
}
ioctl(fd, JSIOCGAXES, &axisCount);
js->axisCount = (int) axisCount;
js->axes = calloc(axisCount, sizeof(float));
for (code = BTN_MISC; code < KEY_CNT; code++)
{
if (!isBitSet(code, keyBits))
continue;
ioctl(fd, JSIOCGBUTTONS, &buttonCount);
js->buttonCount = (int) buttonCount;
js->buttons = calloc(buttonCount, 1);
linjs.keyMap[code - BTN_MISC] = buttonCount;
buttonCount++;
}
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
for (code = 0; code < ABS_CNT; code++)
{
linjs.absMap[code] = -1;
if (!isBitSet(code, absBits))
continue;
if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
{
linjs.absMap[code] = hatCount;
hatCount++;
// Skip the Y axis
code++;
}
else
{
if (ioctl(linjs.fd, EVIOCGABS(code), &linjs.absInfo[code]) < 0)
continue;
linjs.absMap[code] = axisCount;
axisCount++;
}
}
js = _glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount);
if (!js)
{
close(linjs.fd);
return GLFW_FALSE;
}
strncpy(linjs.path, path, sizeof(linjs.path));
memcpy(&js->linjs, &linjs, sizeof(linjs));
pollAbsState(js);
_glfwInputJoystick(js, GLFW_CONNECTED);
return GLFW_TRUE;
}
#endif // __linux__
// Polls for and processes events the specified joystick
#undef isBitSet
// Frees all resources associated with the specified joystick
//
static GLFWbool pollJoystickEvents(_GLFWjoystickLinux* js)
static void closeJoystick(_GLFWjoystick* js)
{
#if defined(__linux__)
_glfwPollJoystickEvents();
if (!js->present)
return GLFW_FALSE;
// Read all queued events (non-blocking)
for (;;)
{
struct js_event e;
errno = 0;
if (read(js->fd, &e, sizeof(e)) < 0)
{
// Reset the joystick slot if the device was disconnected
if (errno == ENODEV)
{
free(js->axes);
free(js->buttons);
free(js->name);
free(js->path);
memset(js, 0, sizeof(_GLFWjoystickLinux));
_glfwInputJoystickChange(js - _glfw.linux_js.js,
GLFW_DISCONNECTED);
}
break;
}
// Clear the initial-state bit
e.type &= ~JS_EVENT_INIT;
if (e.type == JS_EVENT_AXIS)
js->axes[e.number] = (float) e.value / 32767.0f;
else if (e.type == JS_EVENT_BUTTON)
js->buttons[e.number] = e.value ? GLFW_PRESS : GLFW_RELEASE;
}
#endif // __linux__
return js->present;
close(js->linjs.fd);
_glfwFreeJoystick(js);
_glfwInputJoystick(js, GLFW_DISCONNECTED);
}
// Lexically compare joysticks, used by quicksort
// Lexically compare joysticks by name; used by qsort
//
#if defined(__linux__)
static int compareJoysticks(const void* fp, const void* sp)
{
const _GLFWjoystickLinux* fj = fp;
const _GLFWjoystickLinux* sj = sp;
return strcmp(fj->path, sj->path);
const _GLFWjoystick* fj = fp;
const _GLFWjoystick* sj = sp;
return strcmp(fj->linjs.path, sj->linjs.path);
}
#endif // __linux__
//////////////////////////////////////////////////////////////////////////
@@ -173,13 +261,12 @@ static int compareJoysticks(const void* fp, const void* sp)
//
GLFWbool _glfwInitJoysticksLinux(void)
{
#if defined(__linux__)
DIR* dir;
int count = 0;
const char* dirname = "/dev/input";
_glfw.linux_js.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
if (_glfw.linux_js.inotify == -1)
_glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
if (_glfw.linjs.inotify == -1)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Linux: Failed to initialize inotify: %s",
@@ -190,10 +277,10 @@ GLFWbool _glfwInitJoysticksLinux(void)
// HACK: Register for IN_ATTRIB as well to get notified when udev is done
// This works well in practice but the true way is libudev
_glfw.linux_js.watch = inotify_add_watch(_glfw.linux_js.inotify,
dirname,
IN_CREATE | IN_ATTRIB);
if (_glfw.linux_js.watch == -1)
_glfw.linjs.watch = inotify_add_watch(_glfw.linjs.inotify,
dirname,
IN_CREATE | IN_ATTRIB | IN_DELETE);
if (_glfw.linjs.watch == -1)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Linux: Failed to watch for joystick connections in %s: %s",
@@ -202,7 +289,7 @@ GLFWbool _glfwInitJoysticksLinux(void)
// Continue without device connection notifications
}
if (regcomp(&_glfw.linux_js.regex, "^js[0-9]\\+$", 0) != 0)
if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
return GLFW_FALSE;
@@ -215,13 +302,15 @@ GLFWbool _glfwInitJoysticksLinux(void)
while ((entry = readdir(dir)))
{
char path[20];
regmatch_t match;
if (regexec(&_glfw.linux_js.regex, entry->d_name, 1, &match, 0) != 0)
if (regexec(&_glfw.linjs.regex, entry->d_name, 1, &match, 0) != 0)
continue;
char path[PATH_MAX];
snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
if (openJoystickDevice(path))
count++;
}
@@ -237,9 +326,7 @@ GLFWbool _glfwInitJoysticksLinux(void)
// Continue with no joysticks detected
}
qsort(_glfw.linux_js.js, count, sizeof(_GLFWjoystickLinux), compareJoysticks);
#endif // __linux__
qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
return GLFW_TRUE;
}
@@ -247,56 +334,62 @@ GLFWbool _glfwInitJoysticksLinux(void)
//
void _glfwTerminateJoysticksLinux(void)
{
#if defined(__linux__)
int i;
int jid;
for (i = 0; i <= GLFW_JOYSTICK_LAST; i++)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (_glfw.linux_js.js[i].present)
{
close(_glfw.linux_js.js[i].fd);
free(_glfw.linux_js.js[i].axes);
free(_glfw.linux_js.js[i].buttons);
free(_glfw.linux_js.js[i].name);
free(_glfw.linux_js.js[i].path);
}
_GLFWjoystick* js = _glfw.joysticks + jid;
if (js->present)
closeJoystick(js);
}
regfree(&_glfw.linux_js.regex);
regfree(&_glfw.linjs.regex);
if (_glfw.linux_js.inotify > 0)
if (_glfw.linjs.inotify > 0)
{
if (_glfw.linux_js.watch > 0)
inotify_rm_watch(_glfw.linux_js.inotify, _glfw.linux_js.watch);
if (_glfw.linjs.watch > 0)
inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch);
close(_glfw.linux_js.inotify);
close(_glfw.linjs.inotify);
}
#endif // __linux__
}
void _glfwPollJoystickEvents(void)
void _glfwDetectJoystickConnectionLinux(void)
{
#if defined(__linux__)
ssize_t offset = 0;
char buffer[16384];
const ssize_t size = read(_glfw.linux_js.inotify, buffer, sizeof(buffer));
const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
while (size > offset)
{
regmatch_t match;
const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
if (regexec(&_glfw.linux_js.regex, e->name, 1, &match, 0) == 0)
{
char path[20];
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
openJoystickDevice(path);
}
offset += sizeof(struct inotify_event) + e->len;
if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0)
continue;
char path[PATH_MAX];
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
if (e->mask & (IN_CREATE | IN_ATTRIB))
openJoystickDevice(path);
else if (e->mask & IN_DELETE)
{
int jid;
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
{
closeJoystick(_glfw.joysticks + jid);
break;
}
}
}
}
#endif
}
@@ -304,38 +397,47 @@ void _glfwPollJoystickEvents(void)
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformJoystickPresent(int joy)
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
{
_GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
return pollJoystickEvents(js);
// Read all queued events (non-blocking)
for (;;)
{
struct input_event e;
errno = 0;
if (read(js->linjs.fd, &e, sizeof(e)) < 0)
{
// Reset the joystick slot if the device was disconnected
if (errno == ENODEV)
closeJoystick(js);
break;
}
if (e.type == EV_SYN)
{
if (e.code == SYN_DROPPED)
_glfw.linjs.dropped = GLFW_TRUE;
else if (e.code == SYN_REPORT)
{
_glfw.linjs.dropped = GLFW_FALSE;
pollAbsState(js);
}
}
if (_glfw.linjs.dropped)
continue;
if (e.type == EV_KEY)
handleKeyEvent(js, e.code, e.value);
else if (e.type == EV_ABS)
handleAbsEvent(js, e.code, e.value);
}
return js->present;
}
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
void _glfwPlatformUpdateGamepadGUID(char* guid)
{
_GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
if (!pollJoystickEvents(js))
return NULL;
*count = js->axisCount;
return js->axes;
}
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
{
_GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
if (!pollJoystickEvents(js))
return NULL;
*count = js->buttonCount;
return js->buttons;
}
const char* _glfwPlatformGetJoystickName(int joy)
{
_GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
if (!pollJoystickEvents(js))
return NULL;
return js->name;
}
+19 -26
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.2 Linux - www.glfw.org
// GLFW 3.3 Linux - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
@@ -24,46 +24,39 @@
//
//========================================================================
#ifndef _glfw3_linux_joystick_h_
#define _glfw3_linux_joystick_h_
#include <linux/input.h>
#include <linux/limits.h>
#include <regex.h>
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWjoylistLinux linux_js
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickLinux linjs
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs
#define _GLFW_PLATFORM_MAPPING_NAME "Linux"
// Linux-specific joystick data
//
typedef struct _GLFWjoystickLinux
{
GLFWbool present;
int fd;
float* axes;
int axisCount;
unsigned char* buttons;
int buttonCount;
char* name;
char* path;
int fd;
char path[PATH_MAX];
int keyMap[KEY_CNT - BTN_MISC];
int absMap[ABS_CNT];
struct input_absinfo absInfo[ABS_CNT];
int hats[4][2];
} _GLFWjoystickLinux;
// Linux-specific joystick API data
//
typedef struct _GLFWjoylistLinux
typedef struct _GLFWlibraryLinux
{
_GLFWjoystickLinux js[GLFW_JOYSTICK_LAST + 1];
#if defined(__linux__)
int inotify;
int watch;
regex_t regex;
#endif /*__linux__*/
} _GLFWjoylistLinux;
int inotify;
int watch;
regex_t regex;
GLFWbool dropped;
} _GLFWlibraryLinux;
GLFWbool _glfwInitJoysticksLinux(void);
void _glfwTerminateJoysticksLinux(void);
void _glfwDetectJoystickConnectionLinux(void);
void _glfwPollJoystickEvents(void);
#endif // _glfw3_linux_joystick_h_
+230
View File
@@ -0,0 +1,230 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
// All gamepad mappings not labeled GLFW are copied from the
// SDL_GameControllerDB project under the following license:
//
// Simple DirectMedia Layer
// Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the
// use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
const char* _glfwDefaultMappings =
"8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
"341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n"
"ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n"
"6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n"
"0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n"
"88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,\n"
"4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,\n"
"25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,\n"
"4c05c405000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,\n"
"4c05cc09000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,\n"
"4c05a00b000000000000504944564944,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,\n"
"6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,\n"
"4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows,\n"
"00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,\n"
"00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,\n"
"28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,\n"
"ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,\n"
"8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
"8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
"10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5,\n"
"79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows,\n"
"4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,platform:Windows,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
"83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Windows,\n"
"10080100000000000000504944564944,PS1 USB,platform:Windows,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
"49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Windows,\n"
"4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"79004318000000000000504944564944,Mayflash GameCube Controller Adapter,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b0,start:b9,guide:b0,leftshoulder:b4,rightshoulder:b7,leftstick:b0,rightstick:b0,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
"79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Windows,\n"
"10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,y:b3,x:b4,start:b11,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,platform:Windows,\n"
"63252305000000000000504944564944,USB Vibration Joystick (BM),platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
"02200090000000000000504944564944,8Bitdo NES30 PRO USB,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
"ff113133000000000000504944564944,Gembird JPD-DualForce,platform:Windows,a:b2,b:b3,x:b0,y:b1,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,leftstick:b10,rightstick:b11,\n"
"341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,leftstick:b8,rightstick:b7,back:b8,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows,\n"
"c0111352000000000000504944564944,Battalife Joystick,platform:Windows,x:b4,a:b6,b:b7,y:b5,back:b2,start:b3,leftshoulder:b0,rightshoulder:b1,leftx:a0,lefty:a1,\n"
"100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Windows,\n"
"79000600000000000000504944564944,NGS Phantom,a:b2,b:b3,y:b1,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,\n"
"6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n"
"6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n"
"6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n"
"6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n"
"4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,\n"
"4c05000000000000c405000000000000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X,\n"
"4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X,\n"
"5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n"
"891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X,\n"
"4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Mac OS X,\n"
"8f0e0000000000000300000000000000,Piranha xtreme,platform:Mac OS X,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
"0d0f0000000000004d00000000000000,HORI Gem Pad 3,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
"79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,\n"
"4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,platform:Mac OS X,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n"
"050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,y:b9,x:b10,start:b6,guide:b8,back:b7,dpup:b2,dpleft:b0,dpdown:b3,dpright:b1,leftx:a0,lefty:a1,lefttrigger:b12,righttrigger:,leftshoulder:b11,platform:Mac OS X,\n"
"83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X,\n"
"bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X,\n"
"79000000000000001100000000000000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a3,lefty:a4,platform:Mac OS X,\n"
"5e04000000000000dd02000000000000,Xbox One Wired Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"5e04000000000000ea02000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"5e04000000000000e002000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b10,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,x:b18,y:b17,back:b7,guide:b8,start:b6,leftstick:b23,rightstick:b24,leftshoulder:b19,rightshoulder:b20,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b21,righttrigger:b22,platform:Mac OS X,\n"
"79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,x:b0,y:b12,back:b32,start:b36,leftstick:b40,rightstick:b44,leftshoulder:b16,rightshoulder:b20,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a8,righty:a12,lefttrigger:b24,righttrigger:b28,platform:Mac OS X,\n"
"2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,\n"
"351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,\n"
"b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,x:b3,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,\n"
"81170000000000007e05000000000000,Sega Saturn,x:b0,a:b2,b:b4,y:b6,start:b13,dpleft:b15,dpdown:b16,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,lefttrigger:b10,rightshoulder:b9,righttrigger:a4,righttrigger:b11,leftx:a0,lefty:a2,platform:Mac OS X,\n"
"10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,\n"
"d814000000000000cecf000000000000,MC Cthulhu,platform:Mac OS X,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,righttrigger:b7,\n"
"0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:a4,\n"
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n"
"03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,\n"
"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n"
"030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
"030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux,\n"
"030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
"030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n"
"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,\n"
"030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,\n"
"050000004c050000c405000000010000,Sony DualShock 4 BT,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n"
"030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,\n"
"050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,\n"
"030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,\n"
"030000006f0e00003001000001010000,EA Sports PS3 Controller,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
"03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
"03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux,\n"
"03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Linux,\n"
"030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,\n"
"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,\n"
"030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
"030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
"030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,\n"
"030000006d04000016c2000010010000,Logitech Logitech Dual Action,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux,\n"
"030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,platform:Linux,\n"
"030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"05000000d6200000ad0d000001000000,Moga Pro,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,\n"
"030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
"030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,\n"
"0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,\n"
"0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,\n"
"030000006f0e00001f01000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"03000000280400000140000000010000,Gravis GamePad Pro USB ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,\n"
"030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"030000005e0400008502000000010000,Microsoft X-Box pad (Japan),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
"03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,platform:Linux,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,\n"
"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,\n"
"030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,\n"
"03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,\n"
"060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux,\n"
"050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux,\n"
"03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a3,rightx:a1,righty:a4,\n"
"03000000666600000488000000010000,Super Joy Box 5 Pro,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,\n"
"05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,\n"
"05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,\n"
"030000008916000001fd000024010000,Razer Onza Classic Edition,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"030000005e040000d102000001010000,Microsoft X-Box One pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux,\n"
"03000000790000001100000010010000,RetroLink Saturn Classic Controller,platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,\n"
"050000007e0500003003000001000000,Nintendo Wii U Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16,\n"
"030000005e0400008e02000004010000,Microsoft X-Box 360 pad,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
"030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,\n"
"030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7\n"
"03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux,\n"
"030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"030000006f0e00001304000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:a0,rightstick:a3,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,\n"
"03000000bd12000015d0000010010000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,\n"
"03000000790000001100000010010000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,\n"
"03000000c9110000f055000011010000,HJC Game GAMEPAD,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b2,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:b7,b:b1,platform:Linux,\n"
"03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux,\n"
"03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,y:b3,x:b0,start:b9,guide:,back:,leftstick:,rightstick:,leftshoulder:,dpleft:b15,dpdown:b14,dpright:b13,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,rightshoulder:b7,dpup:b12,platform:Linux,\n"
"030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,platform:Linux,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,platform:Linux,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,guide:b8,leftstick:b9,rightstick:b10,lefttrigger:a2,righttrigger:a5,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux,\n"
"030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,platform:Linux,a:b0,b:b2,x:b1,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,\n"
"05000000102800000900000000010000,8Bitdo SFC30 GamePad,platform:Linux,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,\n"
"03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1,\n"
"030000000d0f00000d00000000010000,hori,platform:Linux,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5,\n"
"03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,\n"
"03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,platform:Linux,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,\n"
"03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),platform:Linux,a:b3,b:b4,y:b1,x:b0,start:b7,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,\n"
"05000000010000000100000003000000,Nintendo Wiimote,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
"030000005e0400008e02000062230000,Microsoft X-Box 360 pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,platform:Linux,\n"
"030000006f0e00000103000000020000,Logic3 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"05000000380700006652000025010000,Mad Catz C.T.R.L.R ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
"030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
"03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:a2,righttrigger:a5,\n"
"05000000a00500003232000001000000,8Bitdo Zero GamePad,platform:Linux,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,\n"
"030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Linux,\n"
"03000000100800000300000010010000,USB Gamepad,platform:Linux,a:b2,b:b1,x:b3,y:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,\n"
"05000000ac0500003232000001000000,VR-BOX,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,\n"
"03000000780000000600000010010000,Microntek USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1,\n"
"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n";
+135 -136
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 Mir - www.glfw.org
// GLFW 3.3 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -35,124 +35,134 @@
//
static void createKeyTables(void)
{
memset(_glfw.mir.publicKeys, -1, sizeof(_glfw.mir.publicKeys));
int scancode;
_glfw.mir.publicKeys[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
_glfw.mir.publicKeys[KEY_1] = GLFW_KEY_1;
_glfw.mir.publicKeys[KEY_2] = GLFW_KEY_2;
_glfw.mir.publicKeys[KEY_3] = GLFW_KEY_3;
_glfw.mir.publicKeys[KEY_4] = GLFW_KEY_4;
_glfw.mir.publicKeys[KEY_5] = GLFW_KEY_5;
_glfw.mir.publicKeys[KEY_6] = GLFW_KEY_6;
_glfw.mir.publicKeys[KEY_7] = GLFW_KEY_7;
_glfw.mir.publicKeys[KEY_8] = GLFW_KEY_8;
_glfw.mir.publicKeys[KEY_9] = GLFW_KEY_9;
_glfw.mir.publicKeys[KEY_0] = GLFW_KEY_0;
_glfw.mir.publicKeys[KEY_MINUS] = GLFW_KEY_MINUS;
_glfw.mir.publicKeys[KEY_EQUAL] = GLFW_KEY_EQUAL;
_glfw.mir.publicKeys[KEY_Q] = GLFW_KEY_Q;
_glfw.mir.publicKeys[KEY_W] = GLFW_KEY_W;
_glfw.mir.publicKeys[KEY_E] = GLFW_KEY_E;
_glfw.mir.publicKeys[KEY_R] = GLFW_KEY_R;
_glfw.mir.publicKeys[KEY_T] = GLFW_KEY_T;
_glfw.mir.publicKeys[KEY_Y] = GLFW_KEY_Y;
_glfw.mir.publicKeys[KEY_U] = GLFW_KEY_U;
_glfw.mir.publicKeys[KEY_I] = GLFW_KEY_I;
_glfw.mir.publicKeys[KEY_O] = GLFW_KEY_O;
_glfw.mir.publicKeys[KEY_P] = GLFW_KEY_P;
_glfw.mir.publicKeys[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
_glfw.mir.publicKeys[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
_glfw.mir.publicKeys[KEY_A] = GLFW_KEY_A;
_glfw.mir.publicKeys[KEY_S] = GLFW_KEY_S;
_glfw.mir.publicKeys[KEY_D] = GLFW_KEY_D;
_glfw.mir.publicKeys[KEY_F] = GLFW_KEY_F;
_glfw.mir.publicKeys[KEY_G] = GLFW_KEY_G;
_glfw.mir.publicKeys[KEY_H] = GLFW_KEY_H;
_glfw.mir.publicKeys[KEY_J] = GLFW_KEY_J;
_glfw.mir.publicKeys[KEY_K] = GLFW_KEY_K;
_glfw.mir.publicKeys[KEY_L] = GLFW_KEY_L;
_glfw.mir.publicKeys[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
_glfw.mir.publicKeys[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
_glfw.mir.publicKeys[KEY_Z] = GLFW_KEY_Z;
_glfw.mir.publicKeys[KEY_X] = GLFW_KEY_X;
_glfw.mir.publicKeys[KEY_C] = GLFW_KEY_C;
_glfw.mir.publicKeys[KEY_V] = GLFW_KEY_V;
_glfw.mir.publicKeys[KEY_B] = GLFW_KEY_B;
_glfw.mir.publicKeys[KEY_N] = GLFW_KEY_N;
_glfw.mir.publicKeys[KEY_M] = GLFW_KEY_M;
_glfw.mir.publicKeys[KEY_COMMA] = GLFW_KEY_COMMA;
_glfw.mir.publicKeys[KEY_DOT] = GLFW_KEY_PERIOD;
_glfw.mir.publicKeys[KEY_SLASH] = GLFW_KEY_SLASH;
_glfw.mir.publicKeys[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
_glfw.mir.publicKeys[KEY_ESC] = GLFW_KEY_ESCAPE;
_glfw.mir.publicKeys[KEY_TAB] = GLFW_KEY_TAB;
_glfw.mir.publicKeys[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
_glfw.mir.publicKeys[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
_glfw.mir.publicKeys[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
_glfw.mir.publicKeys[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
_glfw.mir.publicKeys[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
_glfw.mir.publicKeys[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
_glfw.mir.publicKeys[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
_glfw.mir.publicKeys[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
_glfw.mir.publicKeys[KEY_MENU] = GLFW_KEY_MENU;
_glfw.mir.publicKeys[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
_glfw.mir.publicKeys[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
_glfw.mir.publicKeys[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
_glfw.mir.publicKeys[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
_glfw.mir.publicKeys[KEY_PAUSE] = GLFW_KEY_PAUSE;
_glfw.mir.publicKeys[KEY_DELETE] = GLFW_KEY_DELETE;
_glfw.mir.publicKeys[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
_glfw.mir.publicKeys[KEY_ENTER] = GLFW_KEY_ENTER;
_glfw.mir.publicKeys[KEY_HOME] = GLFW_KEY_HOME;
_glfw.mir.publicKeys[KEY_END] = GLFW_KEY_END;
_glfw.mir.publicKeys[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
_glfw.mir.publicKeys[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
_glfw.mir.publicKeys[KEY_INSERT] = GLFW_KEY_INSERT;
_glfw.mir.publicKeys[KEY_LEFT] = GLFW_KEY_LEFT;
_glfw.mir.publicKeys[KEY_RIGHT] = GLFW_KEY_RIGHT;
_glfw.mir.publicKeys[KEY_DOWN] = GLFW_KEY_DOWN;
_glfw.mir.publicKeys[KEY_UP] = GLFW_KEY_UP;
_glfw.mir.publicKeys[KEY_F1] = GLFW_KEY_F1;
_glfw.mir.publicKeys[KEY_F2] = GLFW_KEY_F2;
_glfw.mir.publicKeys[KEY_F3] = GLFW_KEY_F3;
_glfw.mir.publicKeys[KEY_F4] = GLFW_KEY_F4;
_glfw.mir.publicKeys[KEY_F5] = GLFW_KEY_F5;
_glfw.mir.publicKeys[KEY_F6] = GLFW_KEY_F6;
_glfw.mir.publicKeys[KEY_F7] = GLFW_KEY_F7;
_glfw.mir.publicKeys[KEY_F8] = GLFW_KEY_F8;
_glfw.mir.publicKeys[KEY_F9] = GLFW_KEY_F9;
_glfw.mir.publicKeys[KEY_F10] = GLFW_KEY_F10;
_glfw.mir.publicKeys[KEY_F11] = GLFW_KEY_F11;
_glfw.mir.publicKeys[KEY_F12] = GLFW_KEY_F12;
_glfw.mir.publicKeys[KEY_F13] = GLFW_KEY_F13;
_glfw.mir.publicKeys[KEY_F14] = GLFW_KEY_F14;
_glfw.mir.publicKeys[KEY_F15] = GLFW_KEY_F15;
_glfw.mir.publicKeys[KEY_F16] = GLFW_KEY_F16;
_glfw.mir.publicKeys[KEY_F17] = GLFW_KEY_F17;
_glfw.mir.publicKeys[KEY_F18] = GLFW_KEY_F18;
_glfw.mir.publicKeys[KEY_F19] = GLFW_KEY_F19;
_glfw.mir.publicKeys[KEY_F20] = GLFW_KEY_F20;
_glfw.mir.publicKeys[KEY_F21] = GLFW_KEY_F21;
_glfw.mir.publicKeys[KEY_F22] = GLFW_KEY_F22;
_glfw.mir.publicKeys[KEY_F23] = GLFW_KEY_F23;
_glfw.mir.publicKeys[KEY_F24] = GLFW_KEY_F24;
_glfw.mir.publicKeys[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
_glfw.mir.publicKeys[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
_glfw.mir.publicKeys[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
_glfw.mir.publicKeys[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
_glfw.mir.publicKeys[KEY_KP0] = GLFW_KEY_KP_0;
_glfw.mir.publicKeys[KEY_KP1] = GLFW_KEY_KP_1;
_glfw.mir.publicKeys[KEY_KP2] = GLFW_KEY_KP_2;
_glfw.mir.publicKeys[KEY_KP3] = GLFW_KEY_KP_3;
_glfw.mir.publicKeys[KEY_KP4] = GLFW_KEY_KP_4;
_glfw.mir.publicKeys[KEY_KP5] = GLFW_KEY_KP_5;
_glfw.mir.publicKeys[KEY_KP6] = GLFW_KEY_KP_6;
_glfw.mir.publicKeys[KEY_KP7] = GLFW_KEY_KP_7;
_glfw.mir.publicKeys[KEY_KP8] = GLFW_KEY_KP_8;
_glfw.mir.publicKeys[KEY_KP9] = GLFW_KEY_KP_9;
_glfw.mir.publicKeys[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
_glfw.mir.publicKeys[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
_glfw.mir.publicKeys[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
memset(_glfw.mir.keycodes, -1, sizeof(_glfw.mir.keycodes));
memset(_glfw.mir.scancodes, -1, sizeof(_glfw.mir.scancodes));
_glfw.mir.keycodes[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
_glfw.mir.keycodes[KEY_1] = GLFW_KEY_1;
_glfw.mir.keycodes[KEY_2] = GLFW_KEY_2;
_glfw.mir.keycodes[KEY_3] = GLFW_KEY_3;
_glfw.mir.keycodes[KEY_4] = GLFW_KEY_4;
_glfw.mir.keycodes[KEY_5] = GLFW_KEY_5;
_glfw.mir.keycodes[KEY_6] = GLFW_KEY_6;
_glfw.mir.keycodes[KEY_7] = GLFW_KEY_7;
_glfw.mir.keycodes[KEY_8] = GLFW_KEY_8;
_glfw.mir.keycodes[KEY_9] = GLFW_KEY_9;
_glfw.mir.keycodes[KEY_0] = GLFW_KEY_0;
_glfw.mir.keycodes[KEY_SPACE] = GLFW_KEY_SPACE;
_glfw.mir.keycodes[KEY_MINUS] = GLFW_KEY_MINUS;
_glfw.mir.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
_glfw.mir.keycodes[KEY_Q] = GLFW_KEY_Q;
_glfw.mir.keycodes[KEY_W] = GLFW_KEY_W;
_glfw.mir.keycodes[KEY_E] = GLFW_KEY_E;
_glfw.mir.keycodes[KEY_R] = GLFW_KEY_R;
_glfw.mir.keycodes[KEY_T] = GLFW_KEY_T;
_glfw.mir.keycodes[KEY_Y] = GLFW_KEY_Y;
_glfw.mir.keycodes[KEY_U] = GLFW_KEY_U;
_glfw.mir.keycodes[KEY_I] = GLFW_KEY_I;
_glfw.mir.keycodes[KEY_O] = GLFW_KEY_O;
_glfw.mir.keycodes[KEY_P] = GLFW_KEY_P;
_glfw.mir.keycodes[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
_glfw.mir.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
_glfw.mir.keycodes[KEY_A] = GLFW_KEY_A;
_glfw.mir.keycodes[KEY_S] = GLFW_KEY_S;
_glfw.mir.keycodes[KEY_D] = GLFW_KEY_D;
_glfw.mir.keycodes[KEY_F] = GLFW_KEY_F;
_glfw.mir.keycodes[KEY_G] = GLFW_KEY_G;
_glfw.mir.keycodes[KEY_H] = GLFW_KEY_H;
_glfw.mir.keycodes[KEY_J] = GLFW_KEY_J;
_glfw.mir.keycodes[KEY_K] = GLFW_KEY_K;
_glfw.mir.keycodes[KEY_L] = GLFW_KEY_L;
_glfw.mir.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
_glfw.mir.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
_glfw.mir.keycodes[KEY_Z] = GLFW_KEY_Z;
_glfw.mir.keycodes[KEY_X] = GLFW_KEY_X;
_glfw.mir.keycodes[KEY_C] = GLFW_KEY_C;
_glfw.mir.keycodes[KEY_V] = GLFW_KEY_V;
_glfw.mir.keycodes[KEY_B] = GLFW_KEY_B;
_glfw.mir.keycodes[KEY_N] = GLFW_KEY_N;
_glfw.mir.keycodes[KEY_M] = GLFW_KEY_M;
_glfw.mir.keycodes[KEY_COMMA] = GLFW_KEY_COMMA;
_glfw.mir.keycodes[KEY_DOT] = GLFW_KEY_PERIOD;
_glfw.mir.keycodes[KEY_SLASH] = GLFW_KEY_SLASH;
_glfw.mir.keycodes[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
_glfw.mir.keycodes[KEY_ESC] = GLFW_KEY_ESCAPE;
_glfw.mir.keycodes[KEY_TAB] = GLFW_KEY_TAB;
_glfw.mir.keycodes[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
_glfw.mir.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
_glfw.mir.keycodes[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
_glfw.mir.keycodes[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
_glfw.mir.keycodes[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
_glfw.mir.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
_glfw.mir.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
_glfw.mir.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
_glfw.mir.keycodes[KEY_MENU] = GLFW_KEY_MENU;
_glfw.mir.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
_glfw.mir.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
_glfw.mir.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
_glfw.mir.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
_glfw.mir.keycodes[KEY_PAUSE] = GLFW_KEY_PAUSE;
_glfw.mir.keycodes[KEY_DELETE] = GLFW_KEY_DELETE;
_glfw.mir.keycodes[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
_glfw.mir.keycodes[KEY_ENTER] = GLFW_KEY_ENTER;
_glfw.mir.keycodes[KEY_HOME] = GLFW_KEY_HOME;
_glfw.mir.keycodes[KEY_END] = GLFW_KEY_END;
_glfw.mir.keycodes[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
_glfw.mir.keycodes[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
_glfw.mir.keycodes[KEY_INSERT] = GLFW_KEY_INSERT;
_glfw.mir.keycodes[KEY_LEFT] = GLFW_KEY_LEFT;
_glfw.mir.keycodes[KEY_RIGHT] = GLFW_KEY_RIGHT;
_glfw.mir.keycodes[KEY_DOWN] = GLFW_KEY_DOWN;
_glfw.mir.keycodes[KEY_UP] = GLFW_KEY_UP;
_glfw.mir.keycodes[KEY_F1] = GLFW_KEY_F1;
_glfw.mir.keycodes[KEY_F2] = GLFW_KEY_F2;
_glfw.mir.keycodes[KEY_F3] = GLFW_KEY_F3;
_glfw.mir.keycodes[KEY_F4] = GLFW_KEY_F4;
_glfw.mir.keycodes[KEY_F5] = GLFW_KEY_F5;
_glfw.mir.keycodes[KEY_F6] = GLFW_KEY_F6;
_glfw.mir.keycodes[KEY_F7] = GLFW_KEY_F7;
_glfw.mir.keycodes[KEY_F8] = GLFW_KEY_F8;
_glfw.mir.keycodes[KEY_F9] = GLFW_KEY_F9;
_glfw.mir.keycodes[KEY_F10] = GLFW_KEY_F10;
_glfw.mir.keycodes[KEY_F11] = GLFW_KEY_F11;
_glfw.mir.keycodes[KEY_F12] = GLFW_KEY_F12;
_glfw.mir.keycodes[KEY_F13] = GLFW_KEY_F13;
_glfw.mir.keycodes[KEY_F14] = GLFW_KEY_F14;
_glfw.mir.keycodes[KEY_F15] = GLFW_KEY_F15;
_glfw.mir.keycodes[KEY_F16] = GLFW_KEY_F16;
_glfw.mir.keycodes[KEY_F17] = GLFW_KEY_F17;
_glfw.mir.keycodes[KEY_F18] = GLFW_KEY_F18;
_glfw.mir.keycodes[KEY_F19] = GLFW_KEY_F19;
_glfw.mir.keycodes[KEY_F20] = GLFW_KEY_F20;
_glfw.mir.keycodes[KEY_F21] = GLFW_KEY_F21;
_glfw.mir.keycodes[KEY_F22] = GLFW_KEY_F22;
_glfw.mir.keycodes[KEY_F23] = GLFW_KEY_F23;
_glfw.mir.keycodes[KEY_F24] = GLFW_KEY_F24;
_glfw.mir.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
_glfw.mir.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
_glfw.mir.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
_glfw.mir.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
_glfw.mir.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
_glfw.mir.keycodes[KEY_KP1] = GLFW_KEY_KP_1;
_glfw.mir.keycodes[KEY_KP2] = GLFW_KEY_KP_2;
_glfw.mir.keycodes[KEY_KP3] = GLFW_KEY_KP_3;
_glfw.mir.keycodes[KEY_KP4] = GLFW_KEY_KP_4;
_glfw.mir.keycodes[KEY_KP5] = GLFW_KEY_KP_5;
_glfw.mir.keycodes[KEY_KP6] = GLFW_KEY_KP_6;
_glfw.mir.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
_glfw.mir.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
_glfw.mir.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
_glfw.mir.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
_glfw.mir.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
_glfw.mir.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
for (scancode = 0; scancode < 256; scancode++)
{
if (_glfw.mir.keycodes[scancode] > 0)
_glfw.mir.scancodes[_glfw.mir.keycodes[scancode]] = scancode;
}
}
@@ -180,24 +190,15 @@ int _glfwPlatformInit(void)
createKeyTables();
if (!_glfwInitThreadLocalStoragePOSIX())
return GLFW_FALSE;
if (!_glfwInitEGL())
return GLFW_FALSE;
if (!_glfwInitJoysticksLinux())
return GLFW_FALSE;
_glfwInitTimerPOSIX();
// Need the default conf for when we set a NULL cursor
_glfw.mir.default_conf = mir_cursor_configuration_from_name(mir_arrow_cursor_name);
_glfw.mir.eventQueue = calloc(1, sizeof(EventQueue));
_glfwInitEventQueueMir(_glfw.mir.eventQueue);
_glfw.mir.event_queue = calloc(1, sizeof(EventQueue));
_glfwInitEventQueueMir(_glfw.mir.event_queue);
error = pthread_mutex_init(&_glfw.mir.event_mutex, NULL);
error = pthread_mutex_init(&_glfw.mir.eventMutex, NULL);
if (error)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
@@ -206,6 +207,7 @@ int _glfwPlatformInit(void)
return GLFW_FALSE;
}
_glfwPollMonitorsMir();
return GLFW_TRUE;
}
@@ -213,11 +215,10 @@ void _glfwPlatformTerminate(void)
{
_glfwTerminateEGL();
_glfwTerminateJoysticksLinux();
_glfwTerminateThreadLocalStoragePOSIX();
_glfwDeleteEventQueueMir(_glfw.mir.event_queue);
_glfwDeleteEventQueueMir(_glfw.mir.eventQueue);
pthread_mutex_destroy(&_glfw.mir.event_mutex);
pthread_mutex_destroy(&_glfw.mir.eventMutex);
mir_connection_release(_glfw.mir.connection);
}
@@ -230,9 +231,7 @@ const char* _glfwPlatformGetVersionString(void)
#else
" gettimeofday"
#endif
#if defined(__linux__)
" /dev/js"
#endif
#if defined(_GLFW_BUILD_DLL)
" shared"
#endif
+73 -50
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 Mir - www.glfw.org
// GLFW 3.3 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -30,53 +30,55 @@
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
// Poll for changes in the set of connected monitors
//
void _glfwPollMonitorsMir(void)
{
int i, found = 0;
_GLFWmonitor** monitors = NULL;
MirDisplayConfiguration* displayConfig =
mir_connection_create_display_config(_glfw.mir.connection);
int i;
MirDisplayConfig* displayConfig =
mir_connection_create_display_configuration(_glfw.mir.connection);
*count = 0;
int numOutputs = mir_display_config_get_num_outputs(displayConfig);
for (i = 0; i < displayConfig->num_outputs; i++)
for (i = 0; i < numOutputs; i++)
{
const MirDisplayOutput* out = displayConfig->outputs + i;
const MirOutput* output = mir_display_config_get_output(displayConfig, i);
MirOutputConnectionState state = mir_output_get_connection_state(output);
bool enabled = mir_output_is_enabled(output);
if (out->used &&
out->connected &&
out->num_modes &&
out->current_mode < out->num_modes)
if (enabled && state == mir_output_connection_state_connected)
{
found++;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
monitors[i] = _glfwAllocMonitor("Unknown",
out->physical_width_mm,
out->physical_height_mm);
int widthMM = mir_output_get_physical_width_mm(output);
int heightMM = mir_output_get_physical_height_mm(output);
int x = mir_output_get_position_x(output);
int y = mir_output_get_position_y(output);
int id = mir_output_get_id(output);
size_t currentMode = mir_output_get_current_mode_index(output);
const char* name = mir_output_type_name(mir_output_get_type(output));
monitors[i]->mir.x = out->position_x;
monitors[i]->mir.y = out->position_y;
monitors[i]->mir.output_id = out->output_id;
monitors[i]->mir.cur_mode = out->current_mode;
_GLFWmonitor* monitor = _glfwAllocMonitor(name,
widthMM,
heightMM);
monitor->mir.x = x;
monitor->mir.y = y;
monitor->mir.outputId = id;
monitor->mir.curMode = currentMode;
monitor->modes = _glfwPlatformGetVideoModes(monitor, &monitor->modeCount);
monitors[i]->modes = _glfwPlatformGetVideoModes(monitors[i],
&monitors[i]->modeCount);
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
}
}
mir_display_config_destroy(displayConfig);
*count = found;
return monitors;
mir_display_config_release(displayConfig);
}
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
{
return first->mir.output_id == second->mir.output_id;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{
@@ -86,7 +88,7 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
*ypos = monitor->mir.y;
}
void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)
static void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)
{
switch (pf)
{
@@ -123,37 +125,59 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
{
int i;
GLFWvidmode* modes = NULL;
MirDisplayConfiguration* displayConfig =
mir_connection_create_display_config(_glfw.mir.connection);
MirDisplayConfig* displayConfig =
mir_connection_create_display_configuration(_glfw.mir.connection);
for (i = 0; i < displayConfig->num_outputs; i++)
int numOutputs = mir_display_config_get_num_outputs(displayConfig);
for (i = 0; i < numOutputs; i++)
{
const MirDisplayOutput* out = displayConfig->outputs + i;
if (out->output_id != monitor->mir.output_id)
const MirOutput* output = mir_display_config_get_output(displayConfig, i);
int id = mir_output_get_id(output);
if (id != monitor->mir.outputId)
continue;
modes = calloc(out->num_modes, sizeof(GLFWvidmode));
MirOutputConnectionState state = mir_output_get_connection_state(output);
bool enabled = mir_output_is_enabled(output);
for (*found = 0; *found < out->num_modes; (*found)++)
// We must have been disconnected
if (!enabled || state != mir_output_connection_state_connected)
{
modes[*found].width = out->modes[*found].horizontal_resolution;
modes[*found].height = out->modes[*found].vertical_resolution;
modes[*found].refreshRate = out->modes[*found].refresh_rate;
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Monitor no longer connected");
return NULL;
}
FillInRGBBitsFromPixelFormat(&modes[*found], out->output_formats[*found]);
int numModes = mir_output_get_num_modes(output);
modes = calloc(numModes, sizeof(GLFWvidmode));
for (*found = 0; *found < numModes; (*found)++)
{
const MirOutputMode* mode = mir_output_get_mode(output, *found);
int width = mir_output_mode_get_width(mode);
int height = mir_output_mode_get_height(mode);
double refreshRate = mir_output_mode_get_refresh_rate(mode);
MirPixelFormat currentFormat = mir_output_get_current_pixel_format(output);
modes[*found].width = width;
modes[*found].height = height;
modes[*found].refreshRate = refreshRate;
FillInRGBBitsFromPixelFormat(&modes[*found], currentFormat);
}
break;
}
mir_display_config_destroy(displayConfig);
mir_display_config_release(displayConfig);
return modes;
}
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
{
*mode = monitor->modes[monitor->mir.cur_mode];
*mode = monitor->modes[monitor->mir.curMode];
}
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
@@ -177,6 +201,5 @@ GLFWAPI int glfwGetMirMonitor(GLFWmonitor* handle)
{
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(0);
return monitor->mir.output_id;
return monitor->mir.outputId;
}
+27 -27
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 Mir - www.glfw.org
// GLFW 3.3 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -24,40 +24,38 @@
//
//========================================================================
#ifndef _glfw3_mir_platform_h_
#define _glfw3_mir_platform_h_
#include <sys/queue.h>
#include <pthread.h>
#include <dlfcn.h>
#include <mir_toolkit/mir_client_library.h>
typedef VkFlags VkMirSurfaceCreateFlagsKHR;
typedef VkFlags VkMirWindowCreateFlagsKHR;
typedef struct VkMirSurfaceCreateInfoKHR
typedef struct VkMirWindowCreateInfoKHR
{
VkStructureType sType;
const void* pNext;
VkMirSurfaceCreateFlagsKHR flags;
VkMirWindowCreateFlagsKHR flags;
MirConnection* connection;
MirSurface* mirSurface;
} VkMirSurfaceCreateInfoKHR;
MirWindow* mirWindow;
} VkMirWindowCreateInfoKHR;
typedef VkResult (APIENTRY *PFN_vkCreateMirSurfaceKHR)(VkInstance,const VkMirSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkResult (APIENTRY *PFN_vkCreateMirWindowKHR)(VkInstance,const VkMirWindowCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice,uint32_t,MirConnection*);
#include "posix_tls.h"
#include "posix_thread.h"
#include "posix_time.h"
#include "linux_joystick.h"
#include "xkb_unicode.h"
#include "egl_context.h"
#include "osmesa_context.h"
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
#define _glfw_dlsym(handle, name) dlsym(handle, name)
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->mir.window)
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->mir.nativeWindow)
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.mir.display)
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowMir mir
@@ -80,54 +78,56 @@ typedef struct EventQueue
//
typedef struct _GLFWwindowMir
{
MirSurface* surface;
MirWindow* window;
int width;
int height;
MirEGLNativeWindowType window;
MirEGLNativeWindowType nativeWindow;
_GLFWcursor* currentCursor;
} _GLFWwindowMir;
// Mir-specific per-monitor data
//
typedef struct _GLFWmonitorMir
{
int cur_mode;
int output_id;
int curMode;
int outputId;
int x;
int y;
} _GLFWmonitorMir;
// Mir-specific global data
//
typedef struct _GLFWlibraryMir
{
MirConnection* connection;
MirEGLNativeDisplayType display;
MirCursorConfiguration* default_conf;
EventQueue* event_queue;
EventQueue* eventQueue;
short int publicKeys[256];
short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1];
pthread_mutex_t event_mutex;
pthread_cond_t event_cond;
pthread_mutex_t eventMutex;
pthread_cond_t eventCond;
// The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow;
} _GLFWlibraryMir;
// Mir-specific per-cursor data
// TODO: Only system cursors are implemented in Mir atm. Need to wait for support.
//
typedef struct _GLFWcursorMir
{
MirCursorConfiguration* conf;
MirBufferStream* custom_cursor;
MirBufferStream* customCursor;
char const* cursorName; // only needed for system cursors
} _GLFWcursorMir;
extern void _glfwPollMonitorsMir(void);
extern void _glfwInitEventQueueMir(EventQueue* queue);
extern void _glfwDeleteEventQueueMir(EventQueue* queue);
#endif // _glfw3_mir_platform_h_
+265 -169
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 Mir - www.glfw.org
// GLFW 3.3 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -54,44 +54,41 @@ static GLFWbool emptyEventQueue(EventQueue* queue)
// for single threaded event handling.
static EventNode* newEventNode(const MirEvent* event, _GLFWwindow* context)
{
EventNode* new_node = calloc(1, sizeof(EventNode));
new_node->event = mir_event_ref(event);
new_node->window = context;
EventNode* newNode = calloc(1, sizeof(EventNode));
newNode->event = mir_event_ref(event);
newNode->window = context;
return new_node;
return newNode;
}
static void enqueueEvent(const MirEvent* event, _GLFWwindow* context)
{
pthread_mutex_lock(&_glfw.mir.event_mutex);
pthread_mutex_lock(&_glfw.mir.eventMutex);
EventNode* new_node = newEventNode(event, context);
TAILQ_INSERT_TAIL(&_glfw.mir.event_queue->head, new_node, entries);
EventNode* newNode = newEventNode(event, context);
TAILQ_INSERT_TAIL(&_glfw.mir.eventQueue->head, newNode, entries);
pthread_cond_signal(&_glfw.mir.event_cond);
pthread_cond_signal(&_glfw.mir.eventCond);
pthread_mutex_unlock(&_glfw.mir.event_mutex);
pthread_mutex_unlock(&_glfw.mir.eventMutex);
}
static EventNode* dequeueEvent(EventQueue* queue)
{
EventNode* node = NULL;
pthread_mutex_lock(&_glfw.mir.event_mutex);
pthread_mutex_lock(&_glfw.mir.eventMutex);
node = queue->head.tqh_first;
if (node)
TAILQ_REMOVE(&queue->head, node, entries);
pthread_mutex_unlock(&_glfw.mir.event_mutex);
pthread_mutex_unlock(&_glfw.mir.eventMutex);
return node;
}
/* FIXME Soon to be changed upstream mir! So we can use an egl config to figure out
the best pixel format!
*/
static MirPixelFormat findValidPixelFormat(void)
{
unsigned int i, validFormats, mirPixelFormats = 32;
@@ -132,8 +129,8 @@ static int mirModToGLFWMod(uint32_t mods)
static int toGLFWKeyCode(uint32_t key)
{
if (key < sizeof(_glfw.mir.publicKeys) / sizeof(_glfw.mir.publicKeys[0]))
return _glfw.mir.publicKeys[key];
if (key < sizeof(_glfw.mir.keycodes) / sizeof(_glfw.mir.keycodes[0]))
return _glfw.mir.keycodes[key];
return GLFW_KEY_UNKNOWN;
}
@@ -201,16 +198,31 @@ static void handlePointerButton(_GLFWwindow* window,
static void handlePointerMotion(_GLFWwindow* window,
const MirPointerEvent* pointer_event)
{
int current_x = window->virtualCursorPosX;
int current_y = window->virtualCursorPosY;
int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);
int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);
int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
const int hscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
const int vscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
_glfwInputCursorPos(window, x, y);
if (dx != 0 || dy != 0)
_glfwInputScroll(window, dx, dy);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
if (_glfw.mir.disabledCursorWindow != window)
return;
const int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_x);
const int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_y);
const int current_x = window->virtualCursorPosX;
const int current_y = window->virtualCursorPosY;
_glfwInputCursorPos(window, dx + current_x, dy + current_y);
}
else
{
const int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);
const int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);
_glfwInputCursorPos(window, x, y);
}
if (hscroll != 0 || vscroll != 0)
_glfwInputScroll(window, hscroll, vscroll);
}
static void handlePointerEvent(const MirPointerEvent* pointer_event,
@@ -234,7 +246,6 @@ static void handlePointerEvent(const MirPointerEvent* pointer_event,
break;
default:
break;
}
}
@@ -269,14 +280,14 @@ static void handleEvent(const MirEvent* event, _GLFWwindow* window)
}
}
static void addNewEvent(MirSurface* surface, const MirEvent* event, void* context)
static void addNewEvent(MirWindow* window, const MirEvent* event, void* context)
{
enqueueEvent(event, context);
}
static GLFWbool createSurface(_GLFWwindow* window)
static GLFWbool createWindow(_GLFWwindow* window)
{
MirSurfaceSpec* spec;
MirWindowSpec* spec;
MirBufferUsage buffer_usage = mir_buffer_usage_hardware;
MirPixelFormat pixel_format = findValidPixelFormat();
@@ -286,32 +297,42 @@ static GLFWbool createSurface(_GLFWwindow* window)
"Mir: Unable to find a correct pixel format");
return GLFW_FALSE;
}
spec = mir_connection_create_spec_for_normal_surface(_glfw.mir.connection,
window->mir.width,
window->mir.height,
pixel_format);
mir_surface_spec_set_buffer_usage(spec, buffer_usage);
mir_surface_spec_set_name(spec, "MirSurface");
spec = mir_create_normal_window_spec(_glfw.mir.connection,
window->mir.width,
window->mir.height);
window->mir.surface = mir_surface_create_sync(spec);
mir_surface_spec_release(spec);
mir_window_spec_set_pixel_format(spec, pixel_format);
mir_window_spec_set_buffer_usage(spec, buffer_usage);
if (!mir_surface_is_valid(window->mir.surface))
window->mir.window = mir_create_window_sync(spec);
mir_window_spec_release(spec);
if (!mir_window_is_valid(window->mir.window))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unable to create surface: %s",
mir_surface_get_error_message(window->mir.surface));
"Mir: Unable to create window: %s",
mir_window_get_error_message(window->mir.window));
return GLFW_FALSE;
}
mir_surface_set_event_handler(window->mir.surface, addNewEvent, window);
mir_window_set_event_handler(window->mir.window, addNewEvent, window);
return GLFW_TRUE;
}
static void setWindowConfinement(_GLFWwindow* window, MirPointerConfinementState state)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_pointer_confinement(spec, state);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
@@ -356,12 +377,12 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
GLFWvidmode mode;
_glfwPlatformGetVideoMode(window->monitor, &mode);
mir_surface_set_state(window->mir.surface, mir_surface_state_fullscreen);
mir_window_set_state(window->mir.window, mir_window_state_fullscreen);
if (wndconfig->width > mode.width || wndconfig->height > mode.height)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Requested surface size too large: %ix%i",
"Mir: Requested window size too large: %ix%i",
wndconfig->width, wndconfig->height);
return GLFW_FALSE;
@@ -370,17 +391,31 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
window->mir.width = wndconfig->width;
window->mir.height = wndconfig->height;
window->mir.currentCursor = NULL;
if (!createSurface(window))
if (!createWindow(window))
return GLFW_FALSE;
window->mir.window = mir_buffer_stream_get_egl_native_window(
mir_surface_get_buffer_stream(window->mir.surface));
window->mir.nativeWindow = mir_buffer_stream_get_egl_native_window(
mir_window_get_buffer_stream(window->mir.window));
if (ctxconfig->client != GLFW_NO_API)
{
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
{
if (!_glfwInitEGL())
return GLFW_FALSE;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{
if (!_glfwInitOSMesa())
return GLFW_FALSE;
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
}
return GLFW_TRUE;
@@ -388,26 +423,27 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
{
if (mir_surface_is_valid(window->mir.surface))
if (_glfw.mir.disabledCursorWindow == window)
_glfw.mir.disabledCursorWindow = NULL;
if (mir_window_is_valid(window->mir.window))
{
mir_surface_release_sync(window->mir.surface);
window->mir.surface = NULL;
mir_window_release_sync(window->mir.window);
window->mir.window= NULL;
}
if (window->context.client != GLFW_NO_API)
if (window->context.destroy)
window->context.destroy(window);
}
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
{
MirSurfaceSpec* spec;
const char* e_title = title ? title : "";
MirWindowSpec* spec;
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
mir_surface_spec_set_name(spec, e_title);
mir_surface_apply_spec(window->mir.surface, spec);
mir_surface_spec_release(spec);
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_name(spec, title);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
@@ -419,22 +455,30 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
MirSurfaceSpec* spec;
MirWindowSpec* spec;
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
mir_surface_spec_set_width (spec, width);
mir_surface_spec_set_height(spec, height);
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_width (spec, width);
mir_window_spec_set_height(spec, height);
mir_surface_apply_spec(window->mir.surface, spec);
mir_surface_spec_release(spec);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_max_width (spec, maxwidth);
mir_window_spec_set_max_height(spec, maxheight);
mir_window_spec_set_min_width (spec, minwidth);
mir_window_spec_set_min_height(spec, minheight);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
@@ -473,40 +517,63 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
{
mir_surface_set_state(window->mir.surface, mir_surface_state_minimized);
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_minimized);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
{
mir_surface_set_state(window->mir.surface, mir_surface_state_restored);
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_restored);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_maximized);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformHideWindow(_GLFWwindow* window)
{
MirSurfaceSpec* spec;
MirWindowSpec* spec;
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
mir_surface_spec_set_state(spec, mir_surface_state_hidden);
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_hidden);
mir_surface_apply_spec(window->mir.surface, spec);
mir_surface_spec_release(spec);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
MirSurfaceSpec* spec;
MirWindowSpec* spec;
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
mir_surface_spec_set_state(spec, mir_surface_state_restored);
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_restored);
mir_surface_apply_spec(window->mir.surface, spec);
mir_surface_spec_release(spec);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformFocusWindow(_GLFWwindow* window)
@@ -515,6 +582,10 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformDragWindow(_GLFWwindow* window)
{
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
@@ -527,9 +598,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return GLFW_FALSE;
return mir_window_get_focus_state(window->mir.window) == mir_window_focus_state_focused;
}
int _glfwPlatformWindowIconified(_GLFWwindow* window)
@@ -541,53 +610,69 @@ int _glfwPlatformWindowIconified(_GLFWwindow* window)
int _glfwPlatformWindowVisible(_GLFWwindow* window)
{
return mir_surface_get_visibility(window->mir.surface) == mir_surface_visibility_exposed;
return mir_window_get_visibility(window->mir.window) == mir_window_visibility_exposed;
}
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
{
return mir_window_get_state(window->mir.window) == mir_window_state_maximized;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return GLFW_FALSE;
}
void _glfwPlatformPollEvents(void)
{
EventNode* node = NULL;
while ((node = dequeueEvent(_glfw.mir.event_queue)))
while ((node = dequeueEvent(_glfw.mir.eventQueue)))
{
handleEvent(node->event, node->window);
deleteNode(_glfw.mir.event_queue, node);
deleteNode(_glfw.mir.eventQueue, node);
}
}
void _glfwPlatformWaitEvents(void)
{
pthread_mutex_lock(&_glfw.mir.event_mutex);
pthread_mutex_lock(&_glfw.mir.eventMutex);
if (emptyEventQueue(_glfw.mir.event_queue))
pthread_cond_wait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex);
while (emptyEventQueue(_glfw.mir.eventQueue))
pthread_cond_wait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex);
pthread_mutex_unlock(&_glfw.mir.event_mutex);
pthread_mutex_unlock(&_glfw.mir.eventMutex);
_glfwPlatformPollEvents();
}
void _glfwPlatformWaitEventsTimeout(double timeout)
{
pthread_mutex_lock(&_glfw.mir.event_mutex);
pthread_mutex_lock(&_glfw.mir.eventMutex);
if (emptyEventQueue(_glfw.mir.event_queue))
if (emptyEventQueue(_glfw.mir.eventQueue))
{
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
time.tv_sec += (long) timeout;
time.tv_nsec += (long) ((timeout - (long) timeout) * 1e9);
pthread_cond_timedwait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex, &time);
pthread_cond_timedwait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex, &time);
}
pthread_mutex_unlock(&_glfw.mir.event_mutex);
pthread_mutex_unlock(&_glfw.mir.eventMutex);
_glfwPlatformPollEvents();
}
@@ -604,60 +689,45 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh
*height = window->mir.height;
}
// FIXME implement
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot)
{
MirBufferStream* stream;
MirPixelFormat pixel_format = findValidPixelFormat();
int i_w = image->width;
int i_h = image->height;
if (pixel_format == mir_pixel_format_invalid)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unable to find a correct pixel format");
return GLFW_FALSE;
}
stream = mir_connection_create_buffer_stream_sync(_glfw.mir.connection,
i_w, i_h,
pixel_format,
mir_pixel_format_argb_8888,
mir_buffer_usage_software);
cursor->mir.conf = mir_cursor_configuration_from_buffer_stream(stream, xhot, yhot);
char* dest;
unsigned char *pixels;
int i, r_stride, bytes_per_pixel, bytes_per_row;
MirGraphicsRegion region;
mir_buffer_stream_get_graphics_region(stream, &region);
// FIXME Figure this out based on the current_pf
bytes_per_pixel = 4;
bytes_per_row = bytes_per_pixel * i_w;
unsigned char* pixels = image->pixels;
char* dest = region.vaddr;
int i;
dest = region.vaddr;
pixels = image->pixels;
r_stride = region.stride;
for (i = 0; i < i_h; i++)
for (i = 0; i < i_w * i_h; i++, pixels += 4)
{
memcpy(dest, pixels, bytes_per_row);
dest += r_stride;
pixels += r_stride;
unsigned int alpha = pixels[3];
*dest++ = (char)(pixels[2] * alpha / 255);
*dest++ = (char)(pixels[1] * alpha / 255);
*dest++ = (char)(pixels[0] * alpha / 255);
*dest++ = (char)alpha;
}
cursor->mir.custom_cursor = stream;
mir_buffer_stream_swap_buffers_sync(stream);
cursor->mir.customCursor = stream;
return GLFW_TRUE;
}
const char* getSystemCursorName(int shape)
static const char* getSystemCursorName(int shape)
{
switch (shape)
{
@@ -680,40 +750,47 @@ const char* getSystemCursorName(int shape)
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
const char* cursor_name = getSystemCursorName(shape);
cursor->mir.conf = NULL;
cursor->mir.customCursor = NULL;
cursor->mir.cursorName = getSystemCursorName(shape);
if (cursor_name)
{
cursor->mir.conf = mir_cursor_configuration_from_name(cursor_name);
cursor->mir.custom_cursor = NULL;
return GLFW_TRUE;
}
return GLFW_FALSE;
return cursor->mir.cursorName != NULL;
}
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
{
if (cursor->mir.conf)
mir_cursor_configuration_destroy(cursor->mir.conf);
if (cursor->mir.custom_cursor)
mir_buffer_stream_release_sync(cursor->mir.custom_cursor);
if (cursor->mir.customCursor)
mir_buffer_stream_release_sync(cursor->mir.customCursor);
}
static void setCursorNameForWindow(MirWindow* window, char const* name)
{
MirWindowSpec* spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_cursor_name(spec, name);
mir_window_apply_spec(window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
if (cursor && cursor->mir.conf)
if (cursor)
{
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf));
if (cursor->mir.custom_cursor)
window->mir.currentCursor = cursor;
if (cursor->mir.cursorName)
{
mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor);
setCursorNameForWindow(window->mir.window, cursor->mir.cursorName);
}
else if (cursor->mir.conf)
{
mir_window_configure_cursor(window->mir.window, cursor->mir.conf);
}
}
else
{
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.default_conf));
setCursorNameForWindow(window->mir.window, mir_default_cursor_name);
}
}
@@ -731,17 +808,44 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
if (mode == GLFW_CURSOR_DISABLED)
{
_glfw.mir.disabledCursorWindow = window;
setWindowConfinement(window, mir_pointer_confined_to_window);
setCursorNameForWindow(window->mir.window, mir_disabled_cursor_name);
}
else
{
// If we were disabled before lets undo that!
if (_glfw.mir.disabledCursorWindow == window)
{
_glfw.mir.disabledCursorWindow = NULL;
setWindowConfinement(window, mir_pointer_unconfined);
}
if (window->cursorMode == GLFW_CURSOR_NORMAL)
{
_glfwPlatformSetCursor(window, window->mir.currentCursor);
}
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
{
setCursorNameForWindow(window->mir.window, mir_disabled_cursor_name);
}
}
}
const char* _glfwPlatformGetKeyName(int key, int scancode)
const char* _glfwPlatformGetScancodeName(int scancode)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return NULL;
}
int _glfwPlatformGetKeyScancode(int key)
{
return _glfw.mir.scancodes[key];
}
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
@@ -756,21 +860,13 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
return NULL;
}
char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
{
char** extensions;
if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_mir_surface)
return;
*count = 0;
if (!_glfw.vk.KHR_mir_surface)
return NULL;
extensions = calloc(2, sizeof(char*));
extensions[0] = strdup("VK_KHR_surface");
extensions[1] = strdup("VK_KHR_mir_surface");
*count = 2;
return extensions;
extensions[0] = "VK_KHR_surface";
extensions[1] = "VK_KHR_mir_surface";
}
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
@@ -798,12 +894,12 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
VkSurfaceKHR* surface)
{
VkResult err;
VkMirSurfaceCreateInfoKHR sci;
PFN_vkCreateMirSurfaceKHR vkCreateMirSurfaceKHR;
VkMirWindowCreateInfoKHR sci;
PFN_vkCreateMirWindowKHR vkCreateMirWindowKHR;
vkCreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR)
vkGetInstanceProcAddr(instance, "vkCreateMirSurfaceKHR");
if (!vkCreateMirSurfaceKHR)
vkCreateMirWindowKHR = (PFN_vkCreateMirWindowKHR)
vkGetInstanceProcAddr(instance, "vkCreateMirWindowKHR");
if (!vkCreateMirWindowKHR)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"Mir: Vulkan instance missing VK_KHR_mir_surface extension");
@@ -813,9 +909,9 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
memset(&sci, 0, sizeof(sci));
sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR;
sci.connection = _glfw.mir.connection;
sci.mirSurface = window->mir.surface;
sci.mirWindow = window->mir.window;
err = vkCreateMirSurfaceKHR(instance, &sci, allocator, surface);
err = vkCreateMirWindowKHR(instance, &sci, allocator, surface);
if (err)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
@@ -837,10 +933,10 @@ GLFWAPI MirConnection* glfwGetMirDisplay(void)
return _glfw.mir.connection;
}
GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* handle)
GLFWAPI MirWindow* glfwGetMirWindow(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return window->mir.surface;
return window->mir.window;
}
+42 -78
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 - www.glfw.org
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -86,83 +86,49 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
////// GLFW event API //////
//////////////////////////////////////////////////////////////////////////
void _glfwInputMonitorChange(void)
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
{
int i, j, monitorCount = _glfw.monitorCount;
_GLFWmonitor** monitors = _glfw.monitors;
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
// Re-use still connected monitor objects
for (i = 0; i < _glfw.monitorCount; i++)
if (action == GLFW_CONNECTED)
{
for (j = 0; j < monitorCount; j++)
_glfw.monitorCount++;
_glfw.monitors =
realloc(_glfw.monitors, sizeof(_GLFWmonitor*) * _glfw.monitorCount);
if (placement == _GLFW_INSERT_FIRST)
{
if (_glfwPlatformIsSameMonitor(_glfw.monitors[i], monitors[j]))
memmove(_glfw.monitors + 1,
_glfw.monitors,
(_glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
_glfw.monitors[0] = monitor;
}
else
_glfw.monitors[_glfw.monitorCount - 1] = monitor;
}
else if (action == GLFW_DISCONNECTED)
{
int i;
for (i = 0; i < _glfw.monitorCount; i++)
{
if (_glfw.monitors[i] == monitor)
{
_glfwFreeMonitor(_glfw.monitors[i]);
_glfw.monitors[i] = monitors[j];
_glfw.monitorCount--;
memmove(_glfw.monitors + i,
_glfw.monitors + i + 1,
(_glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
break;
}
}
}
// Find and report disconnected monitors (not in the new list)
if (_glfw.callbacks.monitor)
_glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
for (i = 0; i < monitorCount; i++)
{
_GLFWwindow* window;
for (j = 0; j < _glfw.monitorCount; j++)
{
if (monitors[i] == _glfw.monitors[j])
break;
}
if (j < _glfw.monitorCount)
continue;
for (window = _glfw.windowListHead; window; window = window->next)
{
if (window->monitor == monitors[i])
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
}
}
if (_glfw.callbacks.monitor)
_glfw.callbacks.monitor((GLFWmonitor*) monitors[i], GLFW_DISCONNECTED);
}
// Find and report newly connected monitors (not in the old list)
// Re-used monitor objects are then removed from the old list to avoid
// having them destroyed at the end of this function
for (i = 0; i < _glfw.monitorCount; i++)
{
for (j = 0; j < monitorCount; j++)
{
if (_glfw.monitors[i] == monitors[j])
{
monitors[j] = NULL;
break;
}
}
if (j < monitorCount)
continue;
if (_glfw.callbacks.monitor)
_glfw.callbacks.monitor((GLFWmonitor*) _glfw.monitors[i], GLFW_CONNECTED);
}
_glfwFreeMonitors(monitors, monitorCount);
if (action == GLFW_DISCONNECTED)
_glfwFreeMonitor(monitor);
}
void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window)
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
{
monitor->window = window;
}
@@ -175,10 +141,12 @@ void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window)
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
{
_GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
monitor->name = strdup(name);
monitor->widthMM = widthMM;
monitor->heightMM = heightMM;
if (name)
monitor->name = strdup(name);
return monitor;
}
@@ -212,16 +180,6 @@ void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
memset(ramp, 0, sizeof(GLFWgammaramp));
}
void _glfwFreeMonitors(_GLFWmonitor** monitors, int count)
{
int i;
for (i = 0; i < count; i++)
_glfwFreeMonitor(monitors[i]);
free(monitors);
}
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
const GLFWvidmode* desired)
{
@@ -304,6 +262,7 @@ void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
{
assert(count != NULL);
*count = 0;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@@ -404,6 +363,10 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
int i;
unsigned short values[256];
GLFWgammaramp ramp;
assert(handle != NULL);
assert(gamma == gamma);
assert(gamma >= 0.f);
assert(gamma <= FLT_MAX);
_GLFW_REQUIRE_INIT();
@@ -455,6 +418,7 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
assert(ramp != NULL);
assert(ramp->size > 0);
assert(ramp->red != NULL);
assert(ramp->green != NULL);
assert(ramp->blue != NULL);
+2 -7
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 OS X - www.glfw.org
// GLFW 3.3 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -24,9 +24,6 @@
//
//========================================================================
#ifndef _glfw3_nsgl_context_h_
#define _glfw3_nsgl_context_h_
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl
@@ -40,7 +37,6 @@ typedef struct _GLFWcontextNSGL
} _GLFWcontextNSGL;
// NSGL-specific global data
//
typedef struct _GLFWlibraryNSGL
@@ -58,4 +54,3 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
const _GLFWfbconfig* fbconfig);
void _glfwDestroyContextNSGL(_GLFWwindow* window);
#endif // _glfw3_nsgl_context_h_
+81 -57
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 OS X - www.glfw.org
// GLFW 3.3 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -27,38 +27,38 @@
#include "internal.h"
static void makeContextCurrent(_GLFWwindow* window)
static void makeContextCurrentNSGL(_GLFWwindow* window)
{
if (window)
[window->context.nsgl.object makeCurrentContext];
else
[NSOpenGLContext clearCurrentContext];
_glfwPlatformSetCurrentContext(window);
_glfwPlatformSetTls(&_glfw.contextSlot, window);
}
static void swapBuffers(_GLFWwindow* window)
static void swapBuffersNSGL(_GLFWwindow* window)
{
// ARP appears to be unnecessary, but this is future-proof
[window->context.nsgl.object flushBuffer];
}
static void swapInterval(int interval)
static void swapIntervalNSGL(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
GLint sync = interval;
[window->context.nsgl.object setValues:&sync
forParameter:NSOpenGLCPSwapInterval];
}
static int extensionSupported(const char* extension)
static int extensionSupportedNSGL(const char* extension)
{
// There are no NSGL extensions
return GLFW_FALSE;
}
static GLFWglproc getProcAddress(const char* procname)
static GLFWglproc getProcAddressNSGL(const char* procname)
{
CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault,
procname,
@@ -74,7 +74,7 @@ static GLFWglproc getProcAddress(const char* procname)
// Destroy the OpenGL context
//
static void destroyContext(_GLFWwindow* window)
static void destroyContextNSGL(_GLFWwindow* window)
{
[window->context.nsgl.pixelFormat release];
window->context.nsgl.pixelFormat = nil;
@@ -92,6 +92,9 @@ static void destroyContext(_GLFWwindow* window)
//
GLFWbool _glfwInitNSGL(void)
{
if (_glfw.nsgl.framework)
return GLFW_TRUE;
_glfw.nsgl.framework =
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
if (_glfw.nsgl.framework == NULL)
@@ -116,70 +119,83 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
unsigned int attributeCount = 0;
if (ctxconfig->client == GLFW_OPENGL_ES_API)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"NSGL: OpenGL ES is not available on OS X");
return GLFW_FALSE;
}
if (ctxconfig->major == 3 && ctxconfig->minor < 2)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"NSGL: The targeted version of OS X does not support OpenGL 3.0 or 3.1");
"NSGL: OpenGL ES is not available on macOS");
return GLFW_FALSE;
}
if (ctxconfig->major > 2)
{
if (!ctxconfig->forward)
if (ctxconfig->major == 3 && ctxconfig->minor < 2)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"NSGL: The targeted version of OS X only supports forward-compatible contexts for OpenGL 3.2 and above");
"NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1 but may support 3.2 and above");
return GLFW_FALSE;
}
if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
if (!ctxconfig->forward || ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"NSGL: The targeted version of OS X only supports core profile contexts for OpenGL 3.2 and above");
"NSGL: The targeted version of macOS only supports forward-compatible core profile contexts for OpenGL 3.2 and above");
return GLFW_FALSE;
}
}
// Context robustness modes (GL_KHR_robustness) are not yet supported on
// OS X but are not a hard constraint, so ignore and continue
// Context robustness modes (GL_KHR_robustness) are not yet supported by
// macOS but are not a hard constraint, so ignore and continue
// Context release behaviors (GL_KHR_context_flush_control) are not yet
// supported on OS X but are not a hard constraint, so ignore and continue
// supported by macOS but are not a hard constraint, so ignore and continue
#define ADD_ATTR(x) { attributes[attributeCount++] = x; }
#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); }
// Debug contexts (GL_KHR_debug) are not yet supported by macOS but are not
// a hard constraint, so ignore and continue
// Arbitrary array size here
NSOpenGLPixelFormatAttribute attributes[40];
// No-error contexts (GL_KHR_no_error) are not yet supported by macOS but
// are not a hard constraint, so ignore and continue
ADD_ATTR(NSOpenGLPFAAccelerated);
ADD_ATTR(NSOpenGLPFAClosestPolicy);
#define addAttrib(a) \
{ \
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
}
#define setAttrib(a, v) { addAttrib(a); addAttrib(v); }
NSOpenGLPixelFormatAttribute attribs[40];
int index = 0;
addAttrib(NSOpenGLPFAAccelerated);
addAttrib(NSOpenGLPFAClosestPolicy);
if (ctxconfig->nsgl.offline)
{
addAttrib(NSOpenGLPFAAllowOfflineRenderers);
// NOTE: This replaces the NSSupportsAutomaticGraphicsSwitching key in
// Info.plist for unbundled applications
// HACK: This assumes that NSOpenGLPixelFormat will remain
// a straightforward wrapper of its CGL counterpart
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 100800
addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
if (ctxconfig->major >= 4)
{
ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
}
else
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
if (ctxconfig->major >= 3)
{
ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
}
if (ctxconfig->major <= 2)
{
if (fbconfig->auxBuffers != GLFW_DONT_CARE)
ADD_ATTR2(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
setAttrib(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
fbconfig->accumGreenBits != GLFW_DONT_CARE &&
@@ -191,7 +207,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
fbconfig->accumBlueBits +
fbconfig->accumAlphaBits;
ADD_ATTR2(NSOpenGLPFAAccumSize, accumBits);
setAttrib(NSOpenGLPFAAccumSize, accumBits);
}
}
@@ -203,53 +219,61 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
fbconfig->greenBits +
fbconfig->blueBits;
// OS X needs non-zero color size, so set reasonable values
// macOS needs non-zero color size, so set reasonable values
if (colorBits == 0)
colorBits = 24;
else if (colorBits < 15)
colorBits = 15;
ADD_ATTR2(NSOpenGLPFAColorSize, colorBits);
setAttrib(NSOpenGLPFAColorSize, colorBits);
}
if (fbconfig->alphaBits != GLFW_DONT_CARE)
ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
setAttrib(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
if (fbconfig->depthBits != GLFW_DONT_CARE)
ADD_ATTR2(NSOpenGLPFADepthSize, fbconfig->depthBits);
setAttrib(NSOpenGLPFADepthSize, fbconfig->depthBits);
if (fbconfig->stencilBits != GLFW_DONT_CARE)
ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
setAttrib(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
if (fbconfig->stereo)
ADD_ATTR(NSOpenGLPFAStereo);
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"NSGL: Stereo rendering is deprecated");
return GLFW_FALSE;
#else
addAttrib(NSOpenGLPFAStereo);
#endif
}
if (fbconfig->doublebuffer)
ADD_ATTR(NSOpenGLPFADoubleBuffer);
addAttrib(NSOpenGLPFADoubleBuffer);
if (fbconfig->samples != GLFW_DONT_CARE)
{
if (fbconfig->samples == 0)
{
ADD_ATTR2(NSOpenGLPFASampleBuffers, 0);
setAttrib(NSOpenGLPFASampleBuffers, 0);
}
else
{
ADD_ATTR2(NSOpenGLPFASampleBuffers, 1);
ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples);
setAttrib(NSOpenGLPFASampleBuffers, 1);
setAttrib(NSOpenGLPFASamples, fbconfig->samples);
}
}
// NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
// framebuffer, so there's no need (and no way) to request it
ADD_ATTR(0);
addAttrib(0);
#undef ADD_ATTR
#undef ADD_ATTR2
#undef addAttrib
#undef setAttrib
window->context.nsgl.pixelFormat =
[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
[[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
if (window->context.nsgl.pixelFormat == nil)
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
@@ -274,12 +298,12 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
[window->context.nsgl.object setView:window->ns.view];
window->context.makeCurrent = makeContextCurrent;
window->context.swapBuffers = swapBuffers;
window->context.swapInterval = swapInterval;
window->context.extensionSupported = extensionSupported;
window->context.getProcAddress = getProcAddress;
window->context.destroy = destroyContext;
window->context.makeCurrent = makeContextCurrentNSGL;
window->context.swapBuffers = swapBuffersNSGL;
window->context.swapInterval = swapIntervalNSGL;
window->context.extensionSupported = extensionSupportedNSGL;
window->context.getProcAddress = getProcAddressNSGL;
window->context.destroy = destroyContextNSGL;
return GLFW_TRUE;
}
+13 -31
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 POSIX - www.glfw.org
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -28,41 +28,23 @@
#include "internal.h"
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwInitThreadLocalStoragePOSIX(void)
{
if (pthread_key_create(&_glfw.posix_tls.context, NULL) != 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"POSIX: Failed to create context TLS");
return GLFW_FALSE;
}
_glfw.posix_tls.allocated = GLFW_TRUE;
return GLFW_TRUE;
}
void _glfwTerminateThreadLocalStoragePOSIX(void)
{
if (_glfw.posix_tls.allocated)
pthread_key_delete(_glfw.posix_tls.context);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformSetCurrentContext(_GLFWwindow* context)
int _glfwPlatformInit(void)
{
pthread_setspecific(_glfw.posix_tls.context, context);
_glfwInitTimerPOSIX();
return GLFW_TRUE;
}
_GLFWwindow* _glfwPlatformGetCurrentContext(void)
void _glfwPlatformTerminate(void)
{
return pthread_getspecific(_glfw.posix_tls.context);
_glfwTerminateOSMesa();
}
const char* _glfwPlatformGetVersionString(void)
{
return _GLFW_VERSION_NUMBER " null OSMesa";
}
+42
View File
@@ -0,0 +1,42 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
{
return GLFW_FALSE;
}
void _glfwPlatformUpdateGamepadGUID(char* guid)
{
}
+31
View File
@@ -0,0 +1,31 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#define _GLFW_PLATFORM_JOYSTICK_STATE int nulljs
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int nulljs
#define _GLFW_PLATFORM_MAPPING_NAME ""
+18 -32
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 Win32 - www.glfw.org
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -28,42 +28,28 @@
#include "internal.h"
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwInitThreadLocalStorageWin32(void)
{
_glfw.win32_tls.context = TlsAlloc();
if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to allocate TLS index");
return GLFW_FALSE;
}
_glfw.win32_tls.allocated = GLFW_TRUE;
return GLFW_TRUE;
}
void _glfwTerminateThreadLocalStorageWin32(void)
{
if (_glfw.win32_tls.allocated)
TlsFree(_glfw.win32_tls.context);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformSetCurrentContext(_GLFWwindow* context)
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{
TlsSetValue(_glfw.win32_tls.context, context);
}
_GLFWwindow* _glfwPlatformGetCurrentContext(void)
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
{
return NULL;
}
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
{
}
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{
return TlsGetValue(_glfw.win32_tls.context);
}
+62
View File
@@ -0,0 +1,62 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include <dlfcn.h>
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNull null
#define _GLFW_PLATFORM_CONTEXT_STATE
#define _GLFW_PLATFORM_MONITOR_STATE
#define _GLFW_PLATFORM_CURSOR_STATE
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
#define _GLFW_EGL_CONTEXT_STATE
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
#include "osmesa_context.h"
#include "posix_time.h"
#include "posix_thread.h"
#include "null_joystick.h"
#if defined(_GLFW_WIN32)
#define _glfw_dlopen(name) LoadLibraryA(name)
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
#else
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
#define _glfw_dlsym(handle, name) dlsym(handle, name)
#endif
// Null-specific per-window data
//
typedef struct _GLFWwindowNull
{
int width;
int height;
} _GLFWwindowNull;
+297
View File
@@ -0,0 +1,297 @@
//========================================================================
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
static int createNativeWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig)
{
window->null.width = wndconfig->width;
window->null.height = wndconfig->height;
return GLFW_TRUE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
if (!createNativeWindow(window, wndconfig))
return GLFW_FALSE;
if (ctxconfig->client != GLFW_NO_API)
{
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API ||
ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{
if (!_glfwInitOSMesa())
return GLFW_FALSE;
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else
{
_glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available");
return GLFW_FALSE;
}
}
return GLFW_TRUE;
}
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
{
if (window->context.destroy)
window->context.destroy(window);
}
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
{
}
void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count,
const GLFWimage* images)
{
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
}
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
{
}
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
{
}
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
{
if (width)
*width = window->null.width;
if (height)
*height = window->null.height;
}
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
window->null.width = width;
window->null.height = height;
}
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight)
{
}
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d)
{
}
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
{
if (width)
*width = window->null.width;
if (height)
*height = window->null.height;
}
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
int* left, int* top,
int* right, int* bottom)
{
}
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
{
}
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
{
}
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{
}
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
{
return GLFW_FALSE;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
}
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
{
}
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
{
}
void _glfwPlatformHideWindow(_GLFWwindow* window)
{
}
void _glfwPlatformFocusWindow(_GLFWwindow* window)
{
}
void _glfwPlatformDragWindow(_GLFWwindow* window)
{
}
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
return GLFW_FALSE;
}
int _glfwPlatformWindowIconified(_GLFWwindow* window)
{
return GLFW_FALSE;
}
int _glfwPlatformWindowVisible(_GLFWwindow* window)
{
return GLFW_FALSE;
}
void _glfwPlatformPollEvents(void)
{
}
void _glfwPlatformWaitEvents(void)
{
}
void _glfwPlatformWaitEventsTimeout(double timeout)
{
}
void _glfwPlatformPostEmptyEvent(void)
{
}
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
{
}
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
{
}
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
}
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot)
{
return GLFW_TRUE;
}
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
return GLFW_TRUE;
}
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
{
}
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
}
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
{
}
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
{
return NULL;
}
const char* _glfwPlatformGetScancodeName(int scancode)
{
return "";
}
int _glfwPlatformGetKeyScancode(int key)
{
return -1;
}
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
{
}
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device,
uint32_t queuefamily)
{
return GLFW_FALSE;
}
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
_GLFWwindow* window,
const VkAllocationCallbacks* allocator,
VkSurfaceKHR* surface)
{
// This seems like the most appropriate error to return here
return VK_ERROR_INITIALIZATION_FAILED;
}
+368
View File
@@ -0,0 +1,368 @@
//========================================================================
// GLFW 3.3 OSMesa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "internal.h"
static void makeContextCurrentOSMesa(_GLFWwindow* window)
{
if (window)
{
int width, height;
_glfwPlatformGetFramebufferSize(window, &width, &height);
// Check to see if we need to allocate a new buffer
if ((window->context.osmesa.buffer == NULL) ||
(width != window->context.osmesa.width) ||
(height != window->context.osmesa.height))
{
free(window->context.osmesa.buffer);
// Allocate the new buffer (width * height * 8-bit RGBA)
window->context.osmesa.buffer = calloc(4, width * height);
window->context.osmesa.width = width;
window->context.osmesa.height = height;
}
if (!OSMesaMakeCurrent(window->context.osmesa.handle,
window->context.osmesa.buffer,
GL_UNSIGNED_BYTE,
width, height))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to make context current");
return;
}
}
_glfwPlatformSetTls(&_glfw.contextSlot, window);
}
static GLFWglproc getProcAddressOSMesa(const char* procname)
{
return (GLFWglproc) OSMesaGetProcAddress(procname);
}
static void destroyContextOSMesa(_GLFWwindow* window)
{
if (window->context.osmesa.handle)
{
OSMesaDestroyContext(window->context.osmesa.handle);
window->context.osmesa.handle = NULL;
}
if (window->context.osmesa.buffer)
{
free(window->context.osmesa.buffer);
window->context.osmesa.width = 0;
window->context.osmesa.height = 0;
}
}
static void swapBuffersOSMesa(_GLFWwindow* window)
{
// No double buffering on OSMesa
}
static void swapIntervalOSMesa(int interval)
{
// No swap interval on OSMesa
}
static int extensionSupportedOSMesa(const char* extension)
{
// OSMesa does not have extensions
return GLFW_FALSE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwInitOSMesa(void)
{
int i;
const char* sonames[] =
{
#if defined(_WIN32)
"libOSMesa.dll",
"OSMesa.dll",
#elif defined(__APPLE__)
"libOSMesa.8.dylib",
#elif defined(__CYGWIN__)
"libOSMesa-8.so",
#else
"libOSMesa.so.8",
"libOSMesa.so.6",
#endif
NULL
};
if (_glfw.osmesa.handle)
return GLFW_TRUE;
for (i = 0; sonames[i]; i++)
{
_glfw.osmesa.handle = _glfw_dlopen(sonames[i]);
if (_glfw.osmesa.handle)
break;
}
if (!_glfw.osmesa.handle)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
return GLFW_FALSE;
}
_glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextExt");
_glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextAttribs");
_glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext");
_glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent");
_glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
_glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
_glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress");
if (!_glfw.osmesa.CreateContextExt ||
!_glfw.osmesa.DestroyContext ||
!_glfw.osmesa.MakeCurrent ||
!_glfw.osmesa.GetColorBuffer ||
!_glfw.osmesa.GetDepthBuffer ||
!_glfw.osmesa.GetProcAddress)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to load required entry points");
_glfwTerminateOSMesa();
return GLFW_FALSE;
}
return GLFW_TRUE;
}
void _glfwTerminateOSMesa(void)
{
if (_glfw.osmesa.handle)
{
_glfw_dlclose(_glfw.osmesa.handle);
_glfw.osmesa.handle = NULL;
}
}
#define setAttrib(a, v) \
{ \
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
attribs[index++] = v; \
}
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
OSMesaContext share = NULL;
const int accumBits = fbconfig->accumRedBits +
fbconfig->accumGreenBits +
fbconfig->accumBlueBits +
fbconfig->accumAlphaBits;
if (ctxconfig->client == GLFW_OPENGL_ES_API)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"OSMesa: OpenGL ES is not available on OSMesa");
return GLFW_FALSE;
}
if (ctxconfig->share)
share = ctxconfig->share->context.osmesa.handle;
if (OSMesaCreateContextAttribs)
{
int index = 0, attribs[40];
setAttrib(OSMESA_FORMAT, OSMESA_RGBA);
setAttrib(OSMESA_DEPTH_BITS, fbconfig->depthBits);
setAttrib(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
setAttrib(OSMESA_ACCUM_BITS, accumBits);
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
{
setAttrib(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
}
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
{
setAttrib(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
}
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
setAttrib(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
setAttrib(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
}
if (ctxconfig->forward)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"OSMesa: Foward-compatible contexts not supported");
return GLFW_FALSE;
}
setAttrib(0, 0);
window->context.osmesa.handle =
OSMesaCreateContextAttribs(attribs, share);
}
else
{
if (ctxconfig->profile)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"OSMesa: OpenGL profiles unavailable");
return GLFW_FALSE;
}
window->context.osmesa.handle =
OSMesaCreateContextExt(OSMESA_RGBA,
fbconfig->depthBits,
fbconfig->stencilBits,
accumBits,
share);
}
if (window->context.osmesa.handle == NULL)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"OSMesa: Failed to create context");
return GLFW_FALSE;
}
window->context.makeCurrent = makeContextCurrentOSMesa;
window->context.swapBuffers = swapBuffersOSMesa;
window->context.swapInterval = swapIntervalOSMesa;
window->context.extensionSupported = extensionSupportedOSMesa;
window->context.getProcAddress = getProcAddressOSMesa;
window->context.destroy = destroyContextOSMesa;
return GLFW_TRUE;
}
#undef setAttrib
//////////////////////////////////////////////////////////////////////////
////// GLFW native API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
int* height, int* format, void** buffer)
{
void* mesaBuffer;
GLint mesaWidth, mesaHeight, mesaFormat;
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
&mesaWidth, &mesaHeight,
&mesaFormat, &mesaBuffer))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to retrieve color buffer");
return GLFW_FALSE;
}
if (width)
*width = mesaWidth;
if (height)
*height = mesaHeight;
if (format)
*format = mesaFormat;
if (buffer)
*buffer = mesaBuffer;
return GLFW_TRUE;
}
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
int* width, int* height,
int* bytesPerValue,
void** buffer)
{
void* mesaBuffer;
GLint mesaWidth, mesaHeight, mesaBytes;
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
&mesaWidth, &mesaHeight,
&mesaBytes, &mesaBuffer))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to retrieve depth buffer");
return GLFW_FALSE;
}
if (width)
*width = mesaWidth;
if (height)
*height = mesaHeight;
if (bytesPerValue)
*bytesPerValue = mesaBytes;
if (buffer)
*buffer = mesaBuffer;
return GLFW_TRUE;
}
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (window->context.client == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL;
}
return window->context.osmesa.handle;
}
+94
View File
@@ -0,0 +1,94 @@
//========================================================================
// GLFW 3.3 OSMesa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#define OSMESA_RGBA 0x1908
#define OSMESA_FORMAT 0x22
#define OSMESA_DEPTH_BITS 0x30
#define OSMESA_STENCIL_BITS 0x31
#define OSMESA_ACCUM_BITS 0x32
#define OSMESA_PROFILE 0x33
#define OSMESA_CORE_PROFILE 0x34
#define OSMESA_COMPAT_PROFILE 0x35
#define OSMESA_CONTEXT_MAJOR_VERSION 0x36
#define OSMESA_CONTEXT_MINOR_VERSION 0x37
typedef void* OSMesaContext;
typedef void (*OSMESAproc)();
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextExt)(GLenum,GLint,GLint,GLint,OSMesaContext);
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextAttribs)(const int*,OSMesaContext);
typedef void (GLAPIENTRY * PFN_OSMesaDestroyContext)(OSMesaContext);
typedef int (GLAPIENTRY * PFN_OSMesaMakeCurrent)(OSMesaContext,void*,int,int,int);
typedef int (GLAPIENTRY * PFN_OSMesaGetColorBuffer)(OSMesaContext,int*,int*,int*,void**);
typedef int (GLAPIENTRY * PFN_OSMesaGetDepthBuffer)(OSMesaContext,int*,int*,int*,void**);
typedef GLFWglproc (GLAPIENTRY * PFN_OSMesaGetProcAddress)(const char*);
#define OSMesaCreateContextExt _glfw.osmesa.CreateContextExt
#define OSMesaCreateContextAttribs _glfw.osmesa.CreateContextAttribs
#define OSMesaDestroyContext _glfw.osmesa.DestroyContext
#define OSMesaMakeCurrent _glfw.osmesa.MakeCurrent
#define OSMesaGetColorBuffer _glfw.osmesa.GetColorBuffer
#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer
#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress
#define _GLFW_OSMESA_CONTEXT_STATE _GLFWcontextOSMesa osmesa
#define _GLFW_OSMESA_LIBRARY_CONTEXT_STATE _GLFWlibraryOSMesa osmesa
// OSMesa-specific per-context data
//
typedef struct _GLFWcontextOSMesa
{
OSMesaContext handle;
int width;
int height;
void* buffer;
} _GLFWcontextOSMesa;
// OSMesa-specific global data
//
typedef struct _GLFWlibraryOSMesa
{
void* handle;
PFN_OSMesaCreateContextExt CreateContextExt;
PFN_OSMesaCreateContextAttribs CreateContextAttribs;
PFN_OSMesaDestroyContext DestroyContext;
PFN_OSMesaMakeCurrent MakeCurrent;
PFN_OSMesaGetColorBuffer GetColorBuffer;
PFN_OSMesaGetDepthBuffer GetDepthBuffer;
PFN_OSMesaGetProcAddress GetProcAddress;
} _GLFWlibraryOSMesa;
GLFWbool _glfwInitOSMesa(void);
void _glfwTerminateOSMesa(void);
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig);
+103
View File
@@ -0,0 +1,103 @@
//========================================================================
// GLFW 3.3 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
#include <assert.h>
#include <string.h>
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
{
assert(tls->posix.allocated == GLFW_FALSE);
if (pthread_key_create(&tls->posix.key, NULL) != 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"POSIX: Failed to create context TLS");
return GLFW_FALSE;
}
tls->posix.allocated = GLFW_TRUE;
return GLFW_TRUE;
}
void _glfwPlatformDestroyTls(_GLFWtls* tls)
{
if (tls->posix.allocated)
pthread_key_delete(tls->posix.key);
memset(tls, 0, sizeof(_GLFWtls));
}
void* _glfwPlatformGetTls(_GLFWtls* tls)
{
assert(tls->posix.allocated == GLFW_TRUE);
return pthread_getspecific(tls->posix.key);
}
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
{
assert(tls->posix.allocated == GLFW_TRUE);
pthread_setspecific(tls->posix.key, value);
}
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
{
assert(mutex->posix.allocated == GLFW_FALSE);
if (pthread_mutex_init(&mutex->posix.handle, NULL) != 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "POSIX: Failed to create mutex");
return GLFW_FALSE;
}
return mutex->posix.allocated = GLFW_TRUE;
}
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
{
if (mutex->posix.allocated)
pthread_mutex_destroy(&mutex->posix.handle);
memset(mutex, 0, sizeof(_GLFWmutex));
}
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
{
assert(mutex->posix.allocated == GLFW_TRUE);
pthread_mutex_lock(&mutex->posix.handle);
}
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
{
assert(mutex->posix.allocated == GLFW_TRUE);
pthread_mutex_unlock(&mutex->posix.handle);
}
+13 -11
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 POSIX - www.glfw.org
// GLFW 3.3 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -25,25 +25,27 @@
//
//========================================================================
#ifndef _glfw3_posix_tls_h_
#define _glfw3_posix_tls_h_
#include <pthread.h>
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsPOSIX posix_tls
#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsPOSIX posix
#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexPOSIX posix
// POSIX-specific global TLS data
// POSIX-specific thread local storage data
//
typedef struct _GLFWtlsPOSIX
{
GLFWbool allocated;
pthread_key_t context;
pthread_key_t key;
} _GLFWtlsPOSIX;
// POSIX-specific mutex data
//
typedef struct _GLFWmutexPOSIX
{
GLFWbool allocated;
pthread_mutex_t handle;
GLFWbool _glfwInitThreadLocalStoragePOSIX(void);
void _glfwTerminateThreadLocalStoragePOSIX(void);
} _GLFWmutexPOSIX;
#endif // _glfw3_posix_tls_h_
+8 -8
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 POSIX - www.glfw.org
// GLFW 3.3 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -44,14 +44,14 @@ void _glfwInitTimerPOSIX(void)
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
{
_glfw.posix_time.monotonic = GLFW_TRUE;
_glfw.posix_time.frequency = 1000000000;
_glfw.timer.posix.monotonic = GLFW_TRUE;
_glfw.timer.posix.frequency = 1000000000;
}
else
#endif
{
_glfw.posix_time.monotonic = GLFW_FALSE;
_glfw.posix_time.frequency = 1000000;
_glfw.timer.posix.monotonic = GLFW_FALSE;
_glfw.timer.posix.frequency = 1000000;
}
}
@@ -63,7 +63,7 @@ void _glfwInitTimerPOSIX(void)
uint64_t _glfwPlatformGetTimerValue(void)
{
#if defined(CLOCK_MONOTONIC)
if (_glfw.posix_time.monotonic)
if (_glfw.timer.posix.monotonic)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
@@ -80,6 +80,6 @@ uint64_t _glfwPlatformGetTimerValue(void)
uint64_t _glfwPlatformGetTimerFrequency(void)
{
return _glfw.posix_time.frequency;
return _glfw.timer.posix.frequency;
}
+5 -9
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 POSIX - www.glfw.org
// GLFW 3.3 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -25,24 +25,20 @@
//
//========================================================================
#ifndef _glfw3_posix_time_h_
#define _glfw3_posix_time_h_
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimePOSIX posix_time
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerPOSIX posix
#include <stdint.h>
// POSIX-specific global timer data
//
typedef struct _GLFWtimePOSIX
typedef struct _GLFWtimerPOSIX
{
GLFWbool monotonic;
uint64_t frequency;
} _GLFWtimePOSIX;
} _GLFWtimerPOSIX;
void _glfwInitTimerPOSIX(void);
#endif // _glfw3_posix_time_h_
+87 -54
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 - www.glfw.org
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -31,25 +31,38 @@
#include <string.h>
#include <stdlib.h>
#define _GLFW_FIND_LOADER 1
#define _GLFW_REQUIRE_LOADER 2
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
void _glfwInitVulkan(void)
GLFWbool _glfwInitVulkan(int mode)
{
VkResult err;
VkExtensionProperties* ep;
uint32_t i, count;
#if defined(_GLFW_WIN32)
const char* name = "vulkan-1.dll";
#else
const char* name = "libvulkan.so.1";
#endif
_glfw.vk.handle = _glfw_dlopen(name);
if (_glfw.vk.available)
return GLFW_TRUE;
#if !defined(_GLFW_VULKAN_STATIC)
#if defined(_GLFW_WIN32)
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
#elif defined(_GLFW_COCOA)
_glfw.vk.handle = _glfw_dlopen("libMoltenVK.dylib");
#else
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
#endif
if (!_glfw.vk.handle)
return;
{
if (mode == _GLFW_REQUIRE_LOADER)
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
return GLFW_FALSE;
}
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
@@ -57,7 +70,9 @@ void _glfwInitVulkan(void)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"Vulkan: Loader does not export vkGetInstanceProcAddr");
return;
_glfwTerminateVulkan();
return GLFW_FALSE;
}
_glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
@@ -66,16 +81,25 @@ void _glfwInitVulkan(void)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
return;
_glfwTerminateVulkan();
return GLFW_FALSE;
}
#endif // _GLFW_VULKAN_STATIC
err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
if (err)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Vulkan: Failed to query instance extension count: %s",
_glfwGetVulkanResultString(err));
return;
// NOTE: This happens on systems with a loader but without any Vulkan ICD
if (mode == _GLFW_REQUIRE_LOADER)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"Vulkan: Failed to query instance extension count: %s",
_glfwGetVulkanResultString(err));
}
_glfwTerminateVulkan();
return GLFW_FALSE;
}
ep = calloc(count, sizeof(VkExtensionProperties));
@@ -83,51 +107,54 @@ void _glfwInitVulkan(void)
err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
if (err)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
_glfwInputError(GLFW_API_UNAVAILABLE,
"Vulkan: Failed to query instance extensions: %s",
_glfwGetVulkanResultString(err));
free(ep);
return;
_glfwTerminateVulkan();
return GLFW_FALSE;
}
for (i = 0; i < count; i++)
{
if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
_glfw.vk.KHR_surface = GLFW_TRUE;
if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
#if defined(_GLFW_WIN32)
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
_glfw.vk.KHR_win32_surface = GLFW_TRUE;
if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
#elif defined(_GLFW_COCOA)
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
_glfw.vk.MVK_macos_surface = GLFW_TRUE;
#elif defined(_GLFW_X11)
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
_glfw.vk.KHR_xcb_surface = GLFW_TRUE;
if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
#elif defined(_GLFW_WAYLAND)
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
_glfw.vk.KHR_wayland_surface = GLFW_TRUE;
if (strcmp(ep[i].extensionName, "VK_KHR_mir_surface") == 0)
#elif defined(_GLFW_MIR)
else if (strcmp(ep[i].extensionName, "VK_KHR_mir_surface") == 0)
_glfw.vk.KHR_mir_surface = GLFW_TRUE;
#endif
}
free(ep);
_glfw.vk.available = GLFW_TRUE;
if (!_glfw.vk.KHR_surface)
return;
_glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
_glfw.vk.extensions =
_glfwPlatformGetRequiredInstanceExtensions(&_glfw.vk.extensionCount);
return GLFW_TRUE;
}
void _glfwTerminateVulkan(void)
{
uint32_t i;
for (i = 0; i < _glfw.vk.extensionCount; i++)
free(_glfw.vk.extensions[i]);
free(_glfw.vk.extensions);
#if !defined(_GLFW_VULKAN_STATIC)
if (_glfw.vk.handle)
_glfw_dlclose(_glfw.vk.handle);
#endif
}
const char* _glfwGetVulkanResultString(VkResult result)
@@ -193,22 +220,24 @@ const char* _glfwGetVulkanResultString(VkResult result)
GLFWAPI int glfwVulkanSupported(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
return _glfw.vk.available;
return _glfwInitVulkan(_GLFW_FIND_LOADER);
}
GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
{
assert(count != NULL);
*count = 0;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (!_glfw.vk.available)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
return NULL;
}
*count = _glfw.vk.extensionCount;
if (!_glfw.vk.extensions[0])
return NULL;
*count = 2;
return (const char**) _glfw.vk.extensions;
}
@@ -216,18 +245,24 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
const char* procname)
{
GLFWvkproc proc;
assert(procname != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (!_glfw.vk.available)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
return NULL;
}
proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
#if defined(_GLFW_VULKAN_STATIC)
if (!proc)
{
if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
return (GLFWvkproc) vkGetInstanceProcAddr;
}
#else
if (!proc)
proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
#endif
return proc;
}
@@ -236,15 +271,15 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device,
uint32_t queuefamily)
{
assert(instance != VK_NULL_HANDLE);
assert(device != VK_NULL_HANDLE);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (!_glfw.vk.available)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
return GLFW_FALSE;
}
if (!_glfw.vk.extensions)
if (!_glfw.vk.extensions[0])
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"Vulkan: Window surface creation extensions not found");
@@ -262,20 +297,18 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
VkSurfaceKHR* surface)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(instance != VK_NULL_HANDLE);
assert(window != NULL);
assert(surface != NULL);
*surface = VK_NULL_HANDLE;
_GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
if (!_glfw.vk.available)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
return VK_ERROR_INITIALIZATION_FAILED;
}
if (!_glfw.vk.extensions)
if (!_glfw.vk.extensions[0])
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"Vulkan: Window surface creation extensions not found");
+242 -201
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 WGL - www.glfw.org
// GLFW 3.3 WGL - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -44,9 +44,8 @@ static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib
pixelFormat,
0, 1, &attrib, &value))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve pixel format attribute %i",
attrib);
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve pixel format attribute");
return 0;
}
@@ -55,19 +54,19 @@ static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib
// Return a list of available and usable framebuffer configs
//
static GLFWbool choosePixelFormat(_GLFWwindow* window,
const _GLFWfbconfig* desired,
int* result)
static int choosePixelFormat(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
_GLFWfbconfig* usableConfigs;
const _GLFWfbconfig* closest;
int i, nativeCount, usableCount;
int i, pixelFormat, nativeCount, usableCount;
if (_glfw.wgl.ARB_pixel_format)
{
nativeCount = getPixelFormatAttrib(window,
1,
WGL_NUMBER_PIXEL_FORMATS_ARB);
1,
WGL_NUMBER_PIXEL_FORMATS_ARB);
}
else
{
@@ -130,11 +129,25 @@ static GLFWbool choosePixelFormat(_GLFWwindow* window,
if (_glfw.wgl.ARB_multisample)
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
if (_glfw.wgl.ARB_framebuffer_sRGB ||
_glfw.wgl.EXT_framebuffer_sRGB)
if (ctxconfig->client == GLFW_OPENGL_API)
{
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
u->sRGB = GLFW_TRUE;
if (_glfw.wgl.ARB_framebuffer_sRGB ||
_glfw.wgl.EXT_framebuffer_sRGB)
{
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
u->sRGB = GLFW_TRUE;
}
}
else
{
if (_glfw.wgl.EXT_colorspace)
{
if (getPixelFormatAttrib(window, n, WGL_COLORSPACE_EXT) ==
WGL_COLORSPACE_SRGB_EXT)
{
u->sRGB = GLFW_TRUE;
}
}
}
}
else
@@ -197,23 +210,23 @@ static GLFWbool choosePixelFormat(_GLFWwindow* window,
"WGL: The driver does not appear to support OpenGL");
free(usableConfigs);
return GLFW_FALSE;
return 0;
}
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
if (!closest)
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"WGL: Failed to find a suitable pixel format");
free(usableConfigs);
return GLFW_FALSE;
return 0;
}
*result = (int) closest->handle;
pixelFormat = (int) closest->handle;
free(usableConfigs);
return GLFW_TRUE;
return pixelFormat;
}
// Returns whether desktop compositing is enabled
@@ -231,32 +244,32 @@ static GLFWbool isCompositionEnabled(void)
return enabled;
}
static void makeContextCurrent(_GLFWwindow* window)
static void makeContextCurrentWGL(_GLFWwindow* window)
{
if (window)
{
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
_glfwPlatformSetCurrentContext(window);
_glfwPlatformSetTls(&_glfw.contextSlot, window);
else
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to make context current");
_glfwPlatformSetCurrentContext(NULL);
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to make context current");
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
}
}
else
{
if (!wglMakeCurrent(NULL, NULL))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to clear current context");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to clear current context");
}
_glfwPlatformSetCurrentContext(NULL);
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
}
}
static void swapBuffers(_GLFWwindow* window)
static void swapBuffersWGL(_GLFWwindow* window)
{
// HACK: Use DwmFlush when desktop composition is enabled
if (isCompositionEnabled() && !window->monitor)
@@ -269,9 +282,9 @@ static void swapBuffers(_GLFWwindow* window)
SwapBuffers(window->context.wgl.dc);
}
static void swapInterval(int interval)
static void swapIntervalWGL(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
window->context.wgl.interval = interval;
@@ -284,12 +297,10 @@ static void swapInterval(int interval)
_glfw.wgl.SwapIntervalEXT(interval);
}
static int extensionSupported(const char* extension)
static int extensionSupportedWGL(const char* extension)
{
const char* extensions;
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (_glfw.wgl.GetExtensionsStringEXT)
{
extensions = _glfw.wgl.GetExtensionsStringEXT();
@@ -302,7 +313,7 @@ static int extensionSupported(const char* extension)
if (_glfw.wgl.GetExtensionsStringARB)
{
extensions = _glfw.wgl.GetExtensionsStringARB(window->context.wgl.dc);
extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC());
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
@@ -313,7 +324,7 @@ static int extensionSupported(const char* extension)
return GLFW_FALSE;
}
static GLFWglproc getProcAddress(const char* procname)
static GLFWglproc getProcAddressWGL(const char* procname)
{
const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
if (proc)
@@ -324,7 +335,7 @@ static GLFWglproc getProcAddress(const char* procname)
// Destroy the OpenGL context
//
static void destroyContext(_GLFWwindow* window)
static void destroyContextWGL(_GLFWwindow* window)
{
if (window->context.wgl.handle)
{
@@ -335,51 +346,91 @@ static void destroyContext(_GLFWwindow* window)
// Initialize WGL-specific extensions
//
static void loadExtensions(void)
static void loadWGLExtensions(void)
{
// Functions for WGL_EXT_extension_string
// NOTE: These are needed by extensionSupported
PIXELFORMATDESCRIPTOR pfd;
HGLRC rc;
HDC dc = GetDC(_glfw.win32.helperWindowHandle);;
_glfw.wgl.extensionsLoaded = GLFW_TRUE;
// NOTE: A dummy context has to be created for opengl32.dll to load the
// OpenGL ICD, from which we can then query WGL extensions
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
// creation failure occurs during manual pixel format enumeration
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to set pixel format for dummy context");
return;
}
rc = wglCreateContext(dc);
if (!rc)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to create dummy context");
return;
}
if (!wglMakeCurrent(dc, rc))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to make dummy context current");
wglDeleteContext(rc);
return;
}
// NOTE: Functions must be loaded first as they're needed to retrieve the
// extension string that tells us whether the functions are supported
_glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
wglGetProcAddress("wglGetExtensionsStringEXT");
_glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
wglGetProcAddress("wglGetExtensionsStringARB");
// Functions for WGL_ARB_create_context
_glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
// Functions for WGL_EXT_swap_control
_glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
wglGetProcAddress("wglSwapIntervalEXT");
// Functions for WGL_ARB_pixel_format
_glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
wglGetProcAddress("wglGetPixelFormatAttribivARB");
// This needs to include every extension used below except for
// WGL_ARB_extensions_string and WGL_EXT_extensions_string
// NOTE: WGL_ARB_extensions_string and WGL_EXT_extensions_string are not
// checked below as we are already using them
_glfw.wgl.ARB_multisample =
extensionSupported("WGL_ARB_multisample");
extensionSupportedWGL("WGL_ARB_multisample");
_glfw.wgl.ARB_framebuffer_sRGB =
extensionSupported("WGL_ARB_framebuffer_sRGB");
extensionSupportedWGL("WGL_ARB_framebuffer_sRGB");
_glfw.wgl.EXT_framebuffer_sRGB =
extensionSupported("WGL_EXT_framebuffer_sRGB");
extensionSupportedWGL("WGL_EXT_framebuffer_sRGB");
_glfw.wgl.ARB_create_context =
extensionSupported("WGL_ARB_create_context");
extensionSupportedWGL("WGL_ARB_create_context");
_glfw.wgl.ARB_create_context_profile =
extensionSupported("WGL_ARB_create_context_profile");
extensionSupportedWGL("WGL_ARB_create_context_profile");
_glfw.wgl.EXT_create_context_es2_profile =
extensionSupported("WGL_EXT_create_context_es2_profile");
extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
_glfw.wgl.ARB_create_context_robustness =
extensionSupported("WGL_ARB_create_context_robustness");
extensionSupportedWGL("WGL_ARB_create_context_robustness");
_glfw.wgl.ARB_create_context_no_error =
extensionSupportedWGL("WGL_ARB_create_context_no_error");
_glfw.wgl.EXT_swap_control =
extensionSupported("WGL_EXT_swap_control");
extensionSupportedWGL("WGL_EXT_swap_control");
_glfw.wgl.EXT_colorspace =
extensionSupportedWGL("WGL_EXT_colorspace");
_glfw.wgl.ARB_pixel_format =
extensionSupported("WGL_ARB_pixel_format");
extensionSupportedWGL("WGL_ARB_pixel_format");
_glfw.wgl.ARB_context_flush_control =
extensionSupported("WGL_ARB_context_flush_control");
extensionSupportedWGL("WGL_ARB_context_flush_control");
_glfw.wgl.extensionsLoaded = GLFW_TRUE;
wglMakeCurrent(dc, NULL);
wglDeleteContext(rc);
}
@@ -391,22 +442,28 @@ static void loadExtensions(void)
//
GLFWbool _glfwInitWGL(void)
{
if (_glfw.wgl.instance)
return GLFW_TRUE;
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
if (!_glfw.wgl.instance)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "WGL: Failed to load opengl32.dll");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to load opengl32.dll");
return GLFW_FALSE;
}
_glfw.wgl.CreateContext = (WGLCREATECONTEXT_T)
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
_glfw.wgl.DeleteContext = (WGLDELETECONTEXT_T)
_glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
_glfw.wgl.GetProcAddress = (WGLGETPROCADDRESS_T)
_glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
_glfw.wgl.MakeCurrent = (WGLMAKECURRENT_T)
_glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
_glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
_glfw.wgl.ShareLists = (WGLSHARELISTS_T)
_glfw.wgl.ShareLists = (PFN_wglShareLists)
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
return GLFW_TRUE;
@@ -420,11 +477,11 @@ void _glfwTerminateWGL(void)
FreeLibrary(_glfw.wgl.instance);
}
#define setWGLattrib(attribName, attribValue) \
#define setAttrib(a, v) \
{ \
attribs[index++] = attribName; \
attribs[index++] = attribValue; \
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
attribs[index++] = v; \
}
// Create the OpenGL or OpenGL ES context
@@ -434,12 +491,12 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
const _GLFWfbconfig* fbconfig)
{
int attribs[40];
int pixelFormat = 0;
int pixelFormat;
PIXELFORMATDESCRIPTOR pfd;
HGLRC share = NULL;
if (ctxconfig->client == GLFW_NO_API)
return GLFW_TRUE;
if (!_glfw.wgl.extensionsLoaded)
loadWGLExtensions();
if (ctxconfig->share)
share = ctxconfig->share->context.wgl.handle;
@@ -452,24 +509,59 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
return GLFW_FALSE;
}
if (!choosePixelFormat(window, fbconfig, &pixelFormat))
pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
if (!pixelFormat)
return GLFW_FALSE;
if (!DescribePixelFormat(window->context.wgl.dc,
pixelFormat, sizeof(pfd), &pfd))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve PFD for selected pixel format");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve PFD for selected pixel format");
return GLFW_FALSE;
}
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to set selected pixel format");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to set selected pixel format");
return GLFW_FALSE;
}
if (ctxconfig->client == GLFW_OPENGL_API)
{
if (ctxconfig->forward)
{
if (!_glfw.wgl.ARB_create_context)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
return GLFW_FALSE;
}
}
if (ctxconfig->profile)
{
if (!_glfw.wgl.ARB_create_context_profile)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
return GLFW_FALSE;
}
}
}
else
{
if (!_glfw.wgl.ARB_create_context ||
!_glfw.wgl.ARB_create_context_profile ||
!_glfw.wgl.EXT_create_context_es2_profile)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
return GLFW_FALSE;
}
}
if (_glfw.wgl.ARB_create_context)
{
int index = 0, mask = 0, flags = 0;
@@ -489,8 +581,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
if (ctxconfig->debug)
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
if (ctxconfig->noerror)
flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
if (ctxconfig->robustness)
{
@@ -498,13 +588,13 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
{
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
{
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_NO_RESET_NOTIFICATION_ARB);
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_NO_RESET_NOTIFICATION_ARB);
}
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
{
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_LOSE_CONTEXT_ON_RESET_ARB);
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_LOSE_CONTEXT_ON_RESET_ARB);
}
flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
@@ -517,41 +607,88 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
{
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
{
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
}
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
{
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
}
}
}
if (ctxconfig->noerror)
{
if (_glfw.wgl.ARB_create_context_no_error)
setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
}
// NOTE: Only request an explicitly versioned context when necessary, as
// explicitly requesting version 1.0 does not always return the
// highest version supported by the driver
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
setWGLattrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
setWGLattrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
}
if (flags)
setWGLattrib(WGL_CONTEXT_FLAGS_ARB, flags);
setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
if (mask)
setWGLattrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
setWGLattrib(0, 0);
setAttrib(0, 0);
window->context.wgl.handle =
_glfw.wgl.CreateContextAttribsARB(window->context.wgl.dc,
share, attribs);
if (!window->context.wgl.handle)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: Failed to create OpenGL context");
const DWORD error = GetLastError();
if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB))
{
if (ctxconfig->client == GLFW_OPENGL_API)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: Driver does not support OpenGL version %i.%i",
ctxconfig->major,
ctxconfig->minor);
}
else
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: Driver does not support OpenGL ES version %i.%i",
ctxconfig->major,
ctxconfig->minor);
}
}
else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB))
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: Driver does not support the requested OpenGL profile");
}
else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB))
{
_glfwInputError(GLFW_INVALID_VALUE,
"WGL: The share context is not compatible with the requested context");
}
else
{
if (ctxconfig->client == GLFW_OPENGL_API)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: Failed to create OpenGL context");
}
else
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: Failed to create OpenGL ES context");
}
}
return GLFW_FALSE;
}
}
@@ -560,8 +697,8 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
if (!window->context.wgl.handle)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: Failed to create OpenGL context");
_glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
"WGL: Failed to create OpenGL context");
return GLFW_FALSE;
}
@@ -569,120 +706,24 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
{
if (!wglShareLists(share, window->context.wgl.handle))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to enable sharing with specified OpenGL context");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to enable sharing with specified OpenGL context");
return GLFW_FALSE;
}
}
}
window->context.makeCurrent = makeContextCurrent;
window->context.swapBuffers = swapBuffers;
window->context.swapInterval = swapInterval;
window->context.extensionSupported = extensionSupported;
window->context.getProcAddress = getProcAddress;
window->context.destroy = destroyContext;
window->context.makeCurrent = makeContextCurrentWGL;
window->context.swapBuffers = swapBuffersWGL;
window->context.swapInterval = swapIntervalWGL;
window->context.extensionSupported = extensionSupportedWGL;
window->context.getProcAddress = getProcAddressWGL;
window->context.destroy = destroyContextWGL;
return GLFW_TRUE;
}
#undef setWGLattrib
// Analyzes the specified context for possible recreation
//
int _glfwAnalyzeContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
GLFWbool required = GLFW_FALSE;
if (_glfw.wgl.extensionsLoaded)
return _GLFW_RECREATION_NOT_NEEDED;
makeContextCurrent(window);
loadExtensions();
if (ctxconfig->client == GLFW_OPENGL_API)
{
if (ctxconfig->forward)
{
if (!_glfw.wgl.ARB_create_context)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
return _GLFW_RECREATION_IMPOSSIBLE;
}
required = GLFW_TRUE;
}
if (ctxconfig->profile)
{
if (!_glfw.wgl.ARB_create_context_profile)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
return _GLFW_RECREATION_IMPOSSIBLE;
}
required = GLFW_TRUE;
}
if (ctxconfig->release)
{
if (_glfw.wgl.ARB_context_flush_control)
required = GLFW_TRUE;
}
}
else
{
if (!_glfw.wgl.ARB_create_context ||
!_glfw.wgl.ARB_create_context_profile ||
!_glfw.wgl.EXT_create_context_es2_profile)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
return _GLFW_RECREATION_IMPOSSIBLE;
}
required = GLFW_TRUE;
}
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
if (_glfw.wgl.ARB_create_context)
required = GLFW_TRUE;
}
if (ctxconfig->debug)
{
if (_glfw.wgl.ARB_create_context)
required = GLFW_TRUE;
}
if (fbconfig->samples > 0)
{
// MSAA is not a hard constraint, so do nothing if it's not supported
if (_glfw.wgl.ARB_multisample && _glfw.wgl.ARB_pixel_format)
required = GLFW_TRUE;
}
if (fbconfig->sRGB)
{
// sRGB is not a hard constraint, so do nothing if it's not supported
if ((_glfw.wgl.ARB_framebuffer_sRGB ||
_glfw.wgl.EXT_framebuffer_sRGB) &&
_glfw.wgl.ARB_pixel_format)
{
required = GLFW_TRUE;
}
}
if (required)
return _GLFW_RECREATION_REQUIRED;
return _GLFW_RECREATION_NOT_NEEDED;
}
#undef setAttrib
//////////////////////////////////////////////////////////////////////////
+24 -21
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 WGL - www.glfw.org
// GLFW 3.3 WGL - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -25,10 +25,6 @@
//
//========================================================================
#ifndef _glfw3_wgl_context_h_
#define _glfw3_wgl_context_h_
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
#define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
@@ -72,6 +68,13 @@
#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
#define WGL_COLORSPACE_EXT 0x309d
#define WGL_COLORSPACE_SRGB_EXT 0x3089
#define ERROR_INVALID_VERSION_ARB 0x2095
#define ERROR_INVALID_PROFILE_ARB 0x2096
#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
@@ -79,16 +82,18 @@ typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void);
typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC);
typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*);
typedef HGLRC (WINAPI * WGLCREATECONTEXT_T)(HDC);
typedef BOOL (WINAPI * WGLDELETECONTEXT_T)(HGLRC);
typedef PROC (WINAPI * WGLGETPROCADDRESS_T)(LPCSTR);
typedef BOOL (WINAPI * WGLMAKECURRENT_T)(HDC,HGLRC);
typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC,HGLRC);
typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC);
typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
// opengl32.dll function pointer typedefs
#define wglCreateContext _glfw.wgl.CreateContext
#define wglDeleteContext _glfw.wgl.DeleteContext
#define wglGetProcAddress _glfw.wgl.GetProcAddress
#define wglGetCurrentDC _glfw.wgl.GetCurrentDC
#define wglMakeCurrent _glfw.wgl.MakeCurrent
#define wglShareLists _glfw.wgl.ShareLists
@@ -110,17 +115,17 @@ typedef struct _GLFWcontextWGL
} _GLFWcontextWGL;
// WGL-specific global data
//
typedef struct _GLFWlibraryWGL
{
HINSTANCE instance;
WGLCREATECONTEXT_T CreateContext;
WGLDELETECONTEXT_T DeleteContext;
WGLGETPROCADDRESS_T GetProcAddress;
WGLMAKECURRENT_T MakeCurrent;
WGLSHARELISTS_T ShareLists;
PFN_wglCreateContext CreateContext;
PFN_wglDeleteContext DeleteContext;
PFN_wglGetProcAddress GetProcAddress;
PFN_wglGetCurrentDC GetCurrentDC;
PFN_wglMakeCurrent MakeCurrent;
PFN_wglShareLists ShareLists;
GLFWbool extensionsLoaded;
@@ -130,6 +135,7 @@ typedef struct _GLFWlibraryWGL
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
GLFWbool EXT_swap_control;
GLFWbool EXT_colorspace;
GLFWbool ARB_multisample;
GLFWbool ARB_framebuffer_sRGB;
GLFWbool EXT_framebuffer_sRGB;
@@ -138,6 +144,7 @@ typedef struct _GLFWlibraryWGL
GLFWbool ARB_create_context_profile;
GLFWbool EXT_create_context_es2_profile;
GLFWbool ARB_create_context_robustness;
GLFWbool ARB_create_context_no_error;
GLFWbool ARB_context_flush_control;
} _GLFWlibraryWGL;
@@ -148,8 +155,4 @@ void _glfwTerminateWGL(void);
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig);
int _glfwAnalyzeContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig);
#endif // _glfw3_wgl_context_h_
+195 -158
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 Win32 - www.glfw.org
// GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -30,20 +30,21 @@
#include <stdlib.h>
#include <malloc.h>
#include <initguid.h>
DEFINE_GUID(GUID_DEVINTERFACE_HID,0x4d1e55b2,0xf16f,0x11cf,0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30);
static const GUID _glfw_GUID_DEVINTERFACE_HID = {0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
#define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
// Applications exporting this symbol with this value will be automatically
// directed to the high-performance GPU on Nvidia Optimus systems with
// up-to-date drivers
// Executables (but not DLLs) exporting this symbol with this value will be
// automatically directed to the high-performance GPU on Nvidia Optimus systems
// with up-to-date drivers
//
__declspec(dllexport) DWORD NvOptimusEnablement = 1;
// Applications exporting this symbol with this value will be automatically
// directed to the high-performance GPU on AMD PowerXpress systems with
// up-to-date drivers
// Executables (but not DLLs) exporting this symbol with this value will be
// automatically directed to the high-performance GPU on AMD PowerXpress systems
// with up-to-date drivers
//
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
@@ -67,29 +68,29 @@ static GLFWbool loadLibraries(void)
_glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
if (!_glfw.win32.winmm.instance)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll");
return GLFW_FALSE;
}
_glfw.win32.winmm.timeGetTime = (TIMEGETTIME_T)
_glfw.win32.winmm.GetTime = (PFN_timeGetTime)
GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
_glfw.win32.user32.instance = LoadLibraryA("user32.dll");
if (!_glfw.win32.user32.instance)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll");
return GLFW_FALSE;
}
_glfw.win32.user32.SetProcessDPIAware = (SETPROCESSDPIAWARE_T)
_glfw.win32.user32.SetProcessDPIAware = (PFN_SetProcessDPIAware)
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
_glfw.win32.user32.ChangeWindowMessageFilterEx = (CHANGEWINDOWMESSAGEFILTEREX_T)
_glfw.win32.user32.ChangeWindowMessageFilterEx = (PFN_ChangeWindowMessageFilterEx)
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
if (_glfw.win32.dinput8.instance)
{
_glfw.win32.dinput8.DirectInput8Create = (DIRECTINPUT8CREATE_T)
_glfw.win32.dinput8.Create = (PFN_DirectInput8Create)
GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
}
@@ -110,9 +111,9 @@ static GLFWbool loadLibraries(void)
_glfw.win32.xinput.instance = LoadLibraryA(names[i]);
if (_glfw.win32.xinput.instance)
{
_glfw.win32.xinput.XInputGetCapabilities = (XINPUTGETCAPABILITIES_T)
_glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities)
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
_glfw.win32.xinput.XInputGetState = (XINPUTGETSTATE_T)
_glfw.win32.xinput.GetState = (PFN_XInputGetState)
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
break;
@@ -123,16 +124,16 @@ static GLFWbool loadLibraries(void)
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
if (_glfw.win32.dwmapi.instance)
{
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T)
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
_glfw.win32.dwmapi.DwmFlush = (DWMFLUSH_T)
_glfw.win32.dwmapi.DwmFlush = (PFN_DwmFlush)
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
}
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
if (_glfw.win32.shcore.instance)
{
_glfw.win32.shcore.SetProcessDpiAwareness = (SETPROCESSDPIAWARENESS_T)
_glfw.win32.shcore.SetProcessDpiAwareness = (PFN_SetProcessDpiAwareness)
GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
}
@@ -168,135 +169,135 @@ static void createKeyTables(void)
{
int scancode;
memset(_glfw.win32.publicKeys, -1, sizeof(_glfw.win32.publicKeys));
memset(_glfw.win32.nativeKeys, -1, sizeof(_glfw.win32.nativeKeys));
memset(_glfw.win32.keycodes, -1, sizeof(_glfw.win32.keycodes));
memset(_glfw.win32.scancodes, -1, sizeof(_glfw.win32.scancodes));
_glfw.win32.publicKeys[0x00B] = GLFW_KEY_0;
_glfw.win32.publicKeys[0x002] = GLFW_KEY_1;
_glfw.win32.publicKeys[0x003] = GLFW_KEY_2;
_glfw.win32.publicKeys[0x004] = GLFW_KEY_3;
_glfw.win32.publicKeys[0x005] = GLFW_KEY_4;
_glfw.win32.publicKeys[0x006] = GLFW_KEY_5;
_glfw.win32.publicKeys[0x007] = GLFW_KEY_6;
_glfw.win32.publicKeys[0x008] = GLFW_KEY_7;
_glfw.win32.publicKeys[0x009] = GLFW_KEY_8;
_glfw.win32.publicKeys[0x00A] = GLFW_KEY_9;
_glfw.win32.publicKeys[0x01E] = GLFW_KEY_A;
_glfw.win32.publicKeys[0x030] = GLFW_KEY_B;
_glfw.win32.publicKeys[0x02E] = GLFW_KEY_C;
_glfw.win32.publicKeys[0x020] = GLFW_KEY_D;
_glfw.win32.publicKeys[0x012] = GLFW_KEY_E;
_glfw.win32.publicKeys[0x021] = GLFW_KEY_F;
_glfw.win32.publicKeys[0x022] = GLFW_KEY_G;
_glfw.win32.publicKeys[0x023] = GLFW_KEY_H;
_glfw.win32.publicKeys[0x017] = GLFW_KEY_I;
_glfw.win32.publicKeys[0x024] = GLFW_KEY_J;
_glfw.win32.publicKeys[0x025] = GLFW_KEY_K;
_glfw.win32.publicKeys[0x026] = GLFW_KEY_L;
_glfw.win32.publicKeys[0x032] = GLFW_KEY_M;
_glfw.win32.publicKeys[0x031] = GLFW_KEY_N;
_glfw.win32.publicKeys[0x018] = GLFW_KEY_O;
_glfw.win32.publicKeys[0x019] = GLFW_KEY_P;
_glfw.win32.publicKeys[0x010] = GLFW_KEY_Q;
_glfw.win32.publicKeys[0x013] = GLFW_KEY_R;
_glfw.win32.publicKeys[0x01F] = GLFW_KEY_S;
_glfw.win32.publicKeys[0x014] = GLFW_KEY_T;
_glfw.win32.publicKeys[0x016] = GLFW_KEY_U;
_glfw.win32.publicKeys[0x02F] = GLFW_KEY_V;
_glfw.win32.publicKeys[0x011] = GLFW_KEY_W;
_glfw.win32.publicKeys[0x02D] = GLFW_KEY_X;
_glfw.win32.publicKeys[0x015] = GLFW_KEY_Y;
_glfw.win32.publicKeys[0x02C] = GLFW_KEY_Z;
_glfw.win32.keycodes[0x00B] = GLFW_KEY_0;
_glfw.win32.keycodes[0x002] = GLFW_KEY_1;
_glfw.win32.keycodes[0x003] = GLFW_KEY_2;
_glfw.win32.keycodes[0x004] = GLFW_KEY_3;
_glfw.win32.keycodes[0x005] = GLFW_KEY_4;
_glfw.win32.keycodes[0x006] = GLFW_KEY_5;
_glfw.win32.keycodes[0x007] = GLFW_KEY_6;
_glfw.win32.keycodes[0x008] = GLFW_KEY_7;
_glfw.win32.keycodes[0x009] = GLFW_KEY_8;
_glfw.win32.keycodes[0x00A] = GLFW_KEY_9;
_glfw.win32.keycodes[0x01E] = GLFW_KEY_A;
_glfw.win32.keycodes[0x030] = GLFW_KEY_B;
_glfw.win32.keycodes[0x02E] = GLFW_KEY_C;
_glfw.win32.keycodes[0x020] = GLFW_KEY_D;
_glfw.win32.keycodes[0x012] = GLFW_KEY_E;
_glfw.win32.keycodes[0x021] = GLFW_KEY_F;
_glfw.win32.keycodes[0x022] = GLFW_KEY_G;
_glfw.win32.keycodes[0x023] = GLFW_KEY_H;
_glfw.win32.keycodes[0x017] = GLFW_KEY_I;
_glfw.win32.keycodes[0x024] = GLFW_KEY_J;
_glfw.win32.keycodes[0x025] = GLFW_KEY_K;
_glfw.win32.keycodes[0x026] = GLFW_KEY_L;
_glfw.win32.keycodes[0x032] = GLFW_KEY_M;
_glfw.win32.keycodes[0x031] = GLFW_KEY_N;
_glfw.win32.keycodes[0x018] = GLFW_KEY_O;
_glfw.win32.keycodes[0x019] = GLFW_KEY_P;
_glfw.win32.keycodes[0x010] = GLFW_KEY_Q;
_glfw.win32.keycodes[0x013] = GLFW_KEY_R;
_glfw.win32.keycodes[0x01F] = GLFW_KEY_S;
_glfw.win32.keycodes[0x014] = GLFW_KEY_T;
_glfw.win32.keycodes[0x016] = GLFW_KEY_U;
_glfw.win32.keycodes[0x02F] = GLFW_KEY_V;
_glfw.win32.keycodes[0x011] = GLFW_KEY_W;
_glfw.win32.keycodes[0x02D] = GLFW_KEY_X;
_glfw.win32.keycodes[0x015] = GLFW_KEY_Y;
_glfw.win32.keycodes[0x02C] = GLFW_KEY_Z;
_glfw.win32.publicKeys[0x028] = GLFW_KEY_APOSTROPHE;
_glfw.win32.publicKeys[0x02B] = GLFW_KEY_BACKSLASH;
_glfw.win32.publicKeys[0x033] = GLFW_KEY_COMMA;
_glfw.win32.publicKeys[0x00D] = GLFW_KEY_EQUAL;
_glfw.win32.publicKeys[0x029] = GLFW_KEY_GRAVE_ACCENT;
_glfw.win32.publicKeys[0x01A] = GLFW_KEY_LEFT_BRACKET;
_glfw.win32.publicKeys[0x00C] = GLFW_KEY_MINUS;
_glfw.win32.publicKeys[0x034] = GLFW_KEY_PERIOD;
_glfw.win32.publicKeys[0x01B] = GLFW_KEY_RIGHT_BRACKET;
_glfw.win32.publicKeys[0x027] = GLFW_KEY_SEMICOLON;
_glfw.win32.publicKeys[0x035] = GLFW_KEY_SLASH;
_glfw.win32.publicKeys[0x056] = GLFW_KEY_WORLD_2;
_glfw.win32.keycodes[0x028] = GLFW_KEY_APOSTROPHE;
_glfw.win32.keycodes[0x02B] = GLFW_KEY_BACKSLASH;
_glfw.win32.keycodes[0x033] = GLFW_KEY_COMMA;
_glfw.win32.keycodes[0x00D] = GLFW_KEY_EQUAL;
_glfw.win32.keycodes[0x029] = GLFW_KEY_GRAVE_ACCENT;
_glfw.win32.keycodes[0x01A] = GLFW_KEY_LEFT_BRACKET;
_glfw.win32.keycodes[0x00C] = GLFW_KEY_MINUS;
_glfw.win32.keycodes[0x034] = GLFW_KEY_PERIOD;
_glfw.win32.keycodes[0x01B] = GLFW_KEY_RIGHT_BRACKET;
_glfw.win32.keycodes[0x027] = GLFW_KEY_SEMICOLON;
_glfw.win32.keycodes[0x035] = GLFW_KEY_SLASH;
_glfw.win32.keycodes[0x056] = GLFW_KEY_WORLD_2;
_glfw.win32.publicKeys[0x00E] = GLFW_KEY_BACKSPACE;
_glfw.win32.publicKeys[0x153] = GLFW_KEY_DELETE;
_glfw.win32.publicKeys[0x14F] = GLFW_KEY_END;
_glfw.win32.publicKeys[0x01C] = GLFW_KEY_ENTER;
_glfw.win32.publicKeys[0x001] = GLFW_KEY_ESCAPE;
_glfw.win32.publicKeys[0x147] = GLFW_KEY_HOME;
_glfw.win32.publicKeys[0x152] = GLFW_KEY_INSERT;
_glfw.win32.publicKeys[0x15D] = GLFW_KEY_MENU;
_glfw.win32.publicKeys[0x151] = GLFW_KEY_PAGE_DOWN;
_glfw.win32.publicKeys[0x149] = GLFW_KEY_PAGE_UP;
_glfw.win32.publicKeys[0x045] = GLFW_KEY_PAUSE;
_glfw.win32.publicKeys[0x146] = GLFW_KEY_PAUSE;
_glfw.win32.publicKeys[0x039] = GLFW_KEY_SPACE;
_glfw.win32.publicKeys[0x00F] = GLFW_KEY_TAB;
_glfw.win32.publicKeys[0x03A] = GLFW_KEY_CAPS_LOCK;
_glfw.win32.publicKeys[0x145] = GLFW_KEY_NUM_LOCK;
_glfw.win32.publicKeys[0x046] = GLFW_KEY_SCROLL_LOCK;
_glfw.win32.publicKeys[0x03B] = GLFW_KEY_F1;
_glfw.win32.publicKeys[0x03C] = GLFW_KEY_F2;
_glfw.win32.publicKeys[0x03D] = GLFW_KEY_F3;
_glfw.win32.publicKeys[0x03E] = GLFW_KEY_F4;
_glfw.win32.publicKeys[0x03F] = GLFW_KEY_F5;
_glfw.win32.publicKeys[0x040] = GLFW_KEY_F6;
_glfw.win32.publicKeys[0x041] = GLFW_KEY_F7;
_glfw.win32.publicKeys[0x042] = GLFW_KEY_F8;
_glfw.win32.publicKeys[0x043] = GLFW_KEY_F9;
_glfw.win32.publicKeys[0x044] = GLFW_KEY_F10;
_glfw.win32.publicKeys[0x057] = GLFW_KEY_F11;
_glfw.win32.publicKeys[0x058] = GLFW_KEY_F12;
_glfw.win32.publicKeys[0x064] = GLFW_KEY_F13;
_glfw.win32.publicKeys[0x065] = GLFW_KEY_F14;
_glfw.win32.publicKeys[0x066] = GLFW_KEY_F15;
_glfw.win32.publicKeys[0x067] = GLFW_KEY_F16;
_glfw.win32.publicKeys[0x068] = GLFW_KEY_F17;
_glfw.win32.publicKeys[0x069] = GLFW_KEY_F18;
_glfw.win32.publicKeys[0x06A] = GLFW_KEY_F19;
_glfw.win32.publicKeys[0x06B] = GLFW_KEY_F20;
_glfw.win32.publicKeys[0x06C] = GLFW_KEY_F21;
_glfw.win32.publicKeys[0x06D] = GLFW_KEY_F22;
_glfw.win32.publicKeys[0x06E] = GLFW_KEY_F23;
_glfw.win32.publicKeys[0x076] = GLFW_KEY_F24;
_glfw.win32.publicKeys[0x038] = GLFW_KEY_LEFT_ALT;
_glfw.win32.publicKeys[0x01D] = GLFW_KEY_LEFT_CONTROL;
_glfw.win32.publicKeys[0x02A] = GLFW_KEY_LEFT_SHIFT;
_glfw.win32.publicKeys[0x15B] = GLFW_KEY_LEFT_SUPER;
_glfw.win32.publicKeys[0x137] = GLFW_KEY_PRINT_SCREEN;
_glfw.win32.publicKeys[0x138] = GLFW_KEY_RIGHT_ALT;
_glfw.win32.publicKeys[0x11D] = GLFW_KEY_RIGHT_CONTROL;
_glfw.win32.publicKeys[0x036] = GLFW_KEY_RIGHT_SHIFT;
_glfw.win32.publicKeys[0x15C] = GLFW_KEY_RIGHT_SUPER;
_glfw.win32.publicKeys[0x150] = GLFW_KEY_DOWN;
_glfw.win32.publicKeys[0x14B] = GLFW_KEY_LEFT;
_glfw.win32.publicKeys[0x14D] = GLFW_KEY_RIGHT;
_glfw.win32.publicKeys[0x148] = GLFW_KEY_UP;
_glfw.win32.keycodes[0x00E] = GLFW_KEY_BACKSPACE;
_glfw.win32.keycodes[0x153] = GLFW_KEY_DELETE;
_glfw.win32.keycodes[0x14F] = GLFW_KEY_END;
_glfw.win32.keycodes[0x01C] = GLFW_KEY_ENTER;
_glfw.win32.keycodes[0x001] = GLFW_KEY_ESCAPE;
_glfw.win32.keycodes[0x147] = GLFW_KEY_HOME;
_glfw.win32.keycodes[0x152] = GLFW_KEY_INSERT;
_glfw.win32.keycodes[0x15D] = GLFW_KEY_MENU;
_glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN;
_glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP;
_glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE;
_glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE;
_glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE;
_glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB;
_glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK;
_glfw.win32.keycodes[0x145] = GLFW_KEY_NUM_LOCK;
_glfw.win32.keycodes[0x046] = GLFW_KEY_SCROLL_LOCK;
_glfw.win32.keycodes[0x03B] = GLFW_KEY_F1;
_glfw.win32.keycodes[0x03C] = GLFW_KEY_F2;
_glfw.win32.keycodes[0x03D] = GLFW_KEY_F3;
_glfw.win32.keycodes[0x03E] = GLFW_KEY_F4;
_glfw.win32.keycodes[0x03F] = GLFW_KEY_F5;
_glfw.win32.keycodes[0x040] = GLFW_KEY_F6;
_glfw.win32.keycodes[0x041] = GLFW_KEY_F7;
_glfw.win32.keycodes[0x042] = GLFW_KEY_F8;
_glfw.win32.keycodes[0x043] = GLFW_KEY_F9;
_glfw.win32.keycodes[0x044] = GLFW_KEY_F10;
_glfw.win32.keycodes[0x057] = GLFW_KEY_F11;
_glfw.win32.keycodes[0x058] = GLFW_KEY_F12;
_glfw.win32.keycodes[0x064] = GLFW_KEY_F13;
_glfw.win32.keycodes[0x065] = GLFW_KEY_F14;
_glfw.win32.keycodes[0x066] = GLFW_KEY_F15;
_glfw.win32.keycodes[0x067] = GLFW_KEY_F16;
_glfw.win32.keycodes[0x068] = GLFW_KEY_F17;
_glfw.win32.keycodes[0x069] = GLFW_KEY_F18;
_glfw.win32.keycodes[0x06A] = GLFW_KEY_F19;
_glfw.win32.keycodes[0x06B] = GLFW_KEY_F20;
_glfw.win32.keycodes[0x06C] = GLFW_KEY_F21;
_glfw.win32.keycodes[0x06D] = GLFW_KEY_F22;
_glfw.win32.keycodes[0x06E] = GLFW_KEY_F23;
_glfw.win32.keycodes[0x076] = GLFW_KEY_F24;
_glfw.win32.keycodes[0x038] = GLFW_KEY_LEFT_ALT;
_glfw.win32.keycodes[0x01D] = GLFW_KEY_LEFT_CONTROL;
_glfw.win32.keycodes[0x02A] = GLFW_KEY_LEFT_SHIFT;
_glfw.win32.keycodes[0x15B] = GLFW_KEY_LEFT_SUPER;
_glfw.win32.keycodes[0x137] = GLFW_KEY_PRINT_SCREEN;
_glfw.win32.keycodes[0x138] = GLFW_KEY_RIGHT_ALT;
_glfw.win32.keycodes[0x11D] = GLFW_KEY_RIGHT_CONTROL;
_glfw.win32.keycodes[0x036] = GLFW_KEY_RIGHT_SHIFT;
_glfw.win32.keycodes[0x15C] = GLFW_KEY_RIGHT_SUPER;
_glfw.win32.keycodes[0x150] = GLFW_KEY_DOWN;
_glfw.win32.keycodes[0x14B] = GLFW_KEY_LEFT;
_glfw.win32.keycodes[0x14D] = GLFW_KEY_RIGHT;
_glfw.win32.keycodes[0x148] = GLFW_KEY_UP;
_glfw.win32.publicKeys[0x052] = GLFW_KEY_KP_0;
_glfw.win32.publicKeys[0x04F] = GLFW_KEY_KP_1;
_glfw.win32.publicKeys[0x050] = GLFW_KEY_KP_2;
_glfw.win32.publicKeys[0x051] = GLFW_KEY_KP_3;
_glfw.win32.publicKeys[0x04B] = GLFW_KEY_KP_4;
_glfw.win32.publicKeys[0x04C] = GLFW_KEY_KP_5;
_glfw.win32.publicKeys[0x04D] = GLFW_KEY_KP_6;
_glfw.win32.publicKeys[0x047] = GLFW_KEY_KP_7;
_glfw.win32.publicKeys[0x048] = GLFW_KEY_KP_8;
_glfw.win32.publicKeys[0x049] = GLFW_KEY_KP_9;
_glfw.win32.publicKeys[0x04E] = GLFW_KEY_KP_ADD;
_glfw.win32.publicKeys[0x053] = GLFW_KEY_KP_DECIMAL;
_glfw.win32.publicKeys[0x135] = GLFW_KEY_KP_DIVIDE;
_glfw.win32.publicKeys[0x11C] = GLFW_KEY_KP_ENTER;
_glfw.win32.publicKeys[0x037] = GLFW_KEY_KP_MULTIPLY;
_glfw.win32.publicKeys[0x04A] = GLFW_KEY_KP_SUBTRACT;
_glfw.win32.keycodes[0x052] = GLFW_KEY_KP_0;
_glfw.win32.keycodes[0x04F] = GLFW_KEY_KP_1;
_glfw.win32.keycodes[0x050] = GLFW_KEY_KP_2;
_glfw.win32.keycodes[0x051] = GLFW_KEY_KP_3;
_glfw.win32.keycodes[0x04B] = GLFW_KEY_KP_4;
_glfw.win32.keycodes[0x04C] = GLFW_KEY_KP_5;
_glfw.win32.keycodes[0x04D] = GLFW_KEY_KP_6;
_glfw.win32.keycodes[0x047] = GLFW_KEY_KP_7;
_glfw.win32.keycodes[0x048] = GLFW_KEY_KP_8;
_glfw.win32.keycodes[0x049] = GLFW_KEY_KP_9;
_glfw.win32.keycodes[0x04E] = GLFW_KEY_KP_ADD;
_glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL;
_glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE;
_glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER;
_glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY;
_glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT;
for (scancode = 0; scancode < 512; scancode++)
{
if (_glfw.win32.publicKeys[scancode] > 0)
_glfw.win32.nativeKeys[_glfw.win32.publicKeys[scancode]] = scancode;
if (_glfw.win32.keycodes[scancode] > 0)
_glfw.win32.scancodes[_glfw.win32.keycodes[scancode]] = scancode;
}
}
@@ -304,21 +305,26 @@ static void createKeyTables(void)
//
static HWND createHelperWindow(void)
{
MSG msg;
HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
_GLFW_WNDCLASSNAME,
L"GLFW helper window",
L"GLFW message window",
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
0, 0, 1, 1,
HWND_MESSAGE, NULL,
NULL, NULL,
GetModuleHandleW(NULL),
NULL);
if (!window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to create helper window");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create helper window");
return NULL;
}
// HACK: The first call to ShowWindow is ignored if the parent process
// passed along a STARTUPINFO, so clear that flag with a no-op call
ShowWindow(window, SW_HIDE);
// Register for HID device notifications
{
DEV_BROADCAST_DEVICEINTERFACE_W dbi;
@@ -332,6 +338,12 @@ static HWND createHelperWindow(void)
DEVICE_NOTIFY_WINDOW_HANDLE);
}
while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return window;
}
@@ -349,12 +361,18 @@ WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
if (!length)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string from UTF-8");
return NULL;
}
target = calloc(length, sizeof(WCHAR));
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string from UTF-8");
free(target);
return NULL;
}
@@ -371,12 +389,18 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
if (!length)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string to UTF-8");
return NULL;
}
target = calloc(length, sizeof(char));
target = calloc(length, 1);
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length, NULL, NULL))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string to UTF-8");
free(target);
return NULL;
}
@@ -384,6 +408,27 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
return target;
}
// Reports the specified error, appending information about the last Win32 error
//
void _glfwInputErrorWin32(int error, const char* description)
{
WCHAR buffer[1024] = L"";
char message[2048] = "";
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL,
GetLastError() & 0xffff,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
buffer,
sizeof(buffer),
NULL);
WideCharToMultiByte(CP_UTF8, 0, buffer, -1, message, sizeof(message), NULL, NULL);
_glfwInputError(error, "%s: %s", description, message);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
@@ -391,9 +436,6 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
int _glfwPlatformInit(void)
{
if (!_glfwInitThreadLocalStorageWin32())
return GLFW_FALSE;
// To make SetForegroundWindow work as we want, we need to fiddle
// with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
// as possible in the hope of still being the foreground process)
@@ -419,15 +461,10 @@ int _glfwPlatformInit(void)
if (!_glfw.win32.helperWindowHandle)
return GLFW_FALSE;
_glfwPlatformPollEvents();
if (!_glfwInitWGL())
return GLFW_FALSE;
_glfwInitEGL();
_glfwInitTimerWin32();
_glfwInitJoysticksWin32();
_glfwPollMonitorsWin32();
return GLFW_TRUE;
}
@@ -444,12 +481,12 @@ void _glfwPlatformTerminate(void)
SPIF_SENDCHANGE);
free(_glfw.win32.clipboardString);
free(_glfw.win32.rawInput);
_glfwTerminateWGL();
_glfwTerminateEGL();
_glfwTerminateJoysticksWin32();
_glfwTerminateThreadLocalStorageWin32();
freeLibraries();
}
+307 -307
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.1 Win32 - www.glfw.org
// GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -27,13 +27,9 @@
#include "internal.h"
#include <stdio.h>
#include <math.h>
#include <initguid.h>
#define _GLFW_PRESENCE_ONLY 1
#define _GLFW_UPDATE_STATE 2
#define _GLFW_TYPE_AXIS 0
#define _GLFW_TYPE_SLIDER 1
#define _GLFW_TYPE_BUTTON 2
@@ -52,18 +48,29 @@ typedef struct _GLFWobjenumWin32
int povCount;
} _GLFWobjenumWin32;
// Define only the necessary GUIDs (it's bad enough that we're exporting these)
// Define local copies of the necessary GUIDs
//
DEFINE_GUID(IID_IDirectInput8W,0xbf798031,0x483a,0x4da2,0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00);
DEFINE_GUID(GUID_XAxis,0xa36d02e0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_YAxis,0xa36d02e1,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_ZAxis,0xa36d02e2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_RxAxis,0xa36d02f4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_RyAxis,0xa36d02f5,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_RzAxis,0xa36d02e3,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_Slider,0xa36d02e4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_Button,0xa36d02f0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
DEFINE_GUID(GUID_POV,0xa36d02f2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
static const GUID _glfw_IID_IDirectInput8W = {0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
static const GUID _glfw_GUID_XAxis = {0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_YAxis = {0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_ZAxis = {0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_RxAxis = {0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_RyAxis = {0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_RzAxis = {0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_Slider = {0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_Button = {0xa36d02f0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_POV = {0xa36d02f2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
#define IID_IDirectInput8W _glfw_IID_IDirectInput8W
#define GUID_XAxis _glfw_GUID_XAxis
#define GUID_YAxis _glfw_GUID_YAxis
#define GUID_ZAxis _glfw_GUID_ZAxis
#define GUID_RxAxis _glfw_GUID_RxAxis
#define GUID_RyAxis _glfw_GUID_RyAxis
#define GUID_RzAxis _glfw_GUID_RzAxis
#define GUID_Slider _glfw_GUID_Slider
#define GUID_Button _glfw_GUID_Button
#define GUID_POV _glfw_GUID_POV
// Object data array for our clone of c_dfDIJoystick
// Generated with https://github.com/elmindreda/c_dfDIJoystick2
@@ -149,9 +156,9 @@ static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
case XINPUT_DEVSUBTYPE_GAMEPAD:
{
if (xic->Flags & XINPUT_CAPS_WIRELESS)
return "Wireless Xbox 360 Controller";
return "Wireless Xbox Controller";
else
return "Xbox 360 Controller";
return "Xbox Controller";
}
}
@@ -176,7 +183,7 @@ static int compareJoystickObjects(const void* first, const void* second)
//
static GLFWbool supportsXInput(const GUID* guid)
{
UINT i, count;
UINT i, count = 0;
RAWINPUTDEVICELIST* ridl;
GLFWbool result = GLFW_FALSE;
@@ -185,7 +192,7 @@ static GLFWbool supportsXInput(const GUID* guid)
ridl = calloc(count, sizeof(RAWINPUTDEVICELIST));
if (GetRawInputDeviceList(ridl, &count, sizeof(RAWINPUTDEVICELIST)) == -1)
if (GetRawInputDeviceList(ridl, &count, sizeof(RAWINPUTDEVICELIST)) == (UINT) -1)
{
free(ridl);
return GLFW_FALSE;
@@ -211,7 +218,7 @@ static GLFWbool supportsXInput(const GUID* guid)
continue;
}
if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) != guid->Data1)
if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) != (LONG) guid->Data1)
continue;
memset(name, 0, sizeof(name));
@@ -238,25 +245,20 @@ static GLFWbool supportsXInput(const GUID* guid)
// Frees all resources associated with the specified joystick
//
static void closeJoystick(_GLFWjoystickWin32* js)
static void closeJoystick(_GLFWjoystick* js)
{
if (js->device)
if (js->win32.device)
{
IDirectInputDevice8_Unacquire(js->device);
IDirectInputDevice8_Release(js->device);
IDirectInputDevice8_Unacquire(js->win32.device);
IDirectInputDevice8_Release(js->win32.device);
}
free(js->name);
free(js->axes);
free(js->buttons);
free(js->objects);
memset(js, 0, sizeof(_GLFWjoystickWin32));
_glfwInputJoystickChange((int) (js - _glfw.win32_js), GLFW_DISCONNECTED);
_glfwFreeJoystick(js);
_glfwInputJoystick(js, GLFW_DISCONNECTED);
}
// DirectInput device object enumeration callback
// Insights gleaned from SDL2
// Insights gleaned from SDL
//
static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
void* user)
@@ -332,28 +334,23 @@ static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
//
static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
{
int joy = 0;
int jid = 0;
DIDEVCAPS dc;
DIPROPDWORD dipd;
IDirectInputDevice8* device;
_GLFWobjenumWin32 data;
_GLFWjoystickWin32* js;
_GLFWjoystick* js;
char guid[33];
char name[256];
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (memcmp(&_glfw.win32_js[joy].guid, &di->guidInstance, sizeof(GUID)) == 0)
if (!_glfw.joysticks[jid].present)
continue;
if (memcmp(&_glfw.joysticks[jid].win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
return DIENUM_CONTINUE;
}
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
if (!_glfw.win32_js[joy].present)
break;
}
if (joy > GLFW_JOYSTICK_LAST)
return DIENUM_STOP;
if (supportsXInput(&di->guidProduct))
return DIENUM_CONTINUE;
@@ -362,14 +359,14 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
&device,
NULL)))
{
_glfwInputError(GLFW_PLATFORM_ERROR, "DI: Failed to create device");
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create device");
return DIENUM_CONTINUE;
}
if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to set device data format");
"Win32: Failed to set device data format");
IDirectInputDevice8_Release(device);
return DIENUM_CONTINUE;
@@ -381,7 +378,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to query device capabilities");
"Win32: Failed to query device capabilities");
IDirectInputDevice8_Release(device);
return DIENUM_CONTINUE;
@@ -398,7 +395,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
&dipd.diph)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to set device axis mode");
"Win32: Failed to set device axis mode");
IDirectInputDevice8_Release(device);
return DIENUM_CONTINUE;
@@ -415,7 +412,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to enumerate device objects");
"Win32: Failed to enumerate device objects");
IDirectInputDevice8_Release(device);
free(data.objects);
@@ -426,224 +423,54 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
sizeof(_GLFWjoyobjectWin32),
compareJoystickObjects);
js = _glfw.win32_js + joy;
js->device = device;
js->guid = di->guidInstance;
js->axisCount = data.axisCount + data.sliderCount;
js->axes = calloc(js->axisCount, sizeof(float));
js->buttonCount += data.buttonCount + data.povCount * 4;
js->buttons = calloc(js->buttonCount, 1);
js->objects = data.objects;
js->objectCount = data.objectCount;
js->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName);
js->present = GLFW_TRUE;
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
return DIENUM_CONTINUE;
}
// Attempt to open the specified joystick device
// TODO: Pack state arrays for non-gamepad devices
//
static GLFWbool openXinputDevice(DWORD index)
{
int joy;
XINPUT_CAPABILITIES xic;
_GLFWjoystickWin32* js;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
if (!WideCharToMultiByte(CP_UTF8, 0,
di->tszInstanceName, -1,
name, sizeof(name),
NULL, NULL))
{
if (_glfw.win32_js[joy].present &&
_glfw.win32_js[joy].device == NULL &&
_glfw.win32_js[joy].index == index)
{
return GLFW_FALSE;
}
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert joystick name to UTF-8");
IDirectInputDevice8_Release(device);
free(data.objects);
return DIENUM_STOP;
}
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
// Generate a joystick GUID that matches the SDL 2.0.5+ one
if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
{
if (!_glfw.win32_js[joy].present)
break;
}
if (joy > GLFW_JOYSTICK_LAST)
return GLFW_FALSE;
if (_glfw_XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
return GLFW_FALSE;
js = _glfw.win32_js + joy;
js->axisCount = 6;
js->axes = calloc(js->axisCount, sizeof(float));
js->buttonCount = 14;
js->buttons = calloc(js->buttonCount, 1);
js->present = GLFW_TRUE;
js->name = strdup(getDeviceDescription(&xic));
js->index = index;
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
return GLFW_TRUE;
}
// Polls for and processes events the specified joystick
//
static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode)
{
if (!js->present)
return GLFW_FALSE;
if (js->device)
{
int i, j, ai = 0, bi = 0;
HRESULT result;
DIJOYSTATE state;
IDirectInputDevice8_Poll(js->device);
result = IDirectInputDevice8_GetDeviceState(js->device,
sizeof(state),
&state);
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
{
IDirectInputDevice8_Acquire(js->device);
IDirectInputDevice8_Poll(js->device);
result = IDirectInputDevice8_GetDeviceState(js->device,
sizeof(state),
&state);
}
if (FAILED(result))
{
closeJoystick(js);
return GLFW_FALSE;
}
if (mode == _GLFW_PRESENCE_ONLY)
return GLFW_TRUE;
for (i = 0; i < js->objectCount; i++)
{
const void* data = (char*) &state + js->objects[i].offset;
switch (js->objects[i].type)
{
case _GLFW_TYPE_AXIS:
case _GLFW_TYPE_SLIDER:
{
js->axes[ai++] = (*((LONG*) data) + 0.5f) / 32767.5f;
break;
}
case _GLFW_TYPE_BUTTON:
{
if (*((BYTE*) data) & 0x80)
js->buttons[bi++] = GLFW_PRESS;
else
js->buttons[bi++] = GLFW_RELEASE;
break;
}
case _GLFW_TYPE_POV:
{
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
// Screams of horror are appropriate at this point
int value = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
if (value < 0 || value > 8)
value = 8;
for (j = 0; j < 4; j++)
{
if (directions[value] & (1 << j))
js->buttons[bi++] = GLFW_PRESS;
else
js->buttons[bi++] = GLFW_RELEASE;
}
break;
}
}
}
return GLFW_TRUE;
sprintf(guid, "03000000%02x%02x0000%02x%02x000000000000",
(uint8_t) di->guidProduct.Data1,
(uint8_t) (di->guidProduct.Data1 >> 8),
(uint8_t) (di->guidProduct.Data1 >> 16),
(uint8_t) (di->guidProduct.Data1 >> 24));
}
else
{
int i;
DWORD result;
XINPUT_STATE xis;
const WORD buttons[14] =
{
XINPUT_GAMEPAD_A,
XINPUT_GAMEPAD_B,
XINPUT_GAMEPAD_X,
XINPUT_GAMEPAD_Y,
XINPUT_GAMEPAD_LEFT_SHOULDER,
XINPUT_GAMEPAD_RIGHT_SHOULDER,
XINPUT_GAMEPAD_BACK,
XINPUT_GAMEPAD_START,
XINPUT_GAMEPAD_LEFT_THUMB,
XINPUT_GAMEPAD_RIGHT_THUMB,
XINPUT_GAMEPAD_DPAD_UP,
XINPUT_GAMEPAD_DPAD_RIGHT,
XINPUT_GAMEPAD_DPAD_DOWN,
XINPUT_GAMEPAD_DPAD_LEFT
};
result = _glfw_XInputGetState(js->index, &xis);
if (result != ERROR_SUCCESS)
{
if (result == ERROR_DEVICE_NOT_CONNECTED)
closeJoystick(js);
return GLFW_FALSE;
}
if (mode == _GLFW_PRESENCE_ONLY)
return GLFW_TRUE;
if (sqrt((double) (xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY)) >
(double) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
js->axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f;
js->axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f;
}
else
{
js->axes[0] = 0.f;
js->axes[1] = 0.f;
}
if (sqrt((double) (xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX +
xis.Gamepad.sThumbRY * xis.Gamepad.sThumbRY)) >
(double) XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
js->axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f;
js->axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f;
}
else
{
js->axes[2] = 0.f;
js->axes[3] = 0.f;
}
if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
js->axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f;
else
js->axes[4] = -1.f;
if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
js->axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
else
js->axes[5] = -1.f;
for (i = 0; i < 14; i++)
js->buttons[i] = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
return GLFW_TRUE;
sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
name[0], name[1], name[2], name[3],
name[4], name[5], name[6], name[7],
name[8], name[9], name[10]);
}
js = _glfwAllocJoystick(name, guid,
data.axisCount + data.sliderCount,
data.buttonCount,
data.povCount);
if (!js)
{
IDirectInputDevice8_Release(device);
free(data.objects);
return DIENUM_STOP;
}
js->win32.device = device;
js->win32.guid = di->guidInstance;
js->win32.objects = data.objects;
js->win32.objectCount = data.objectCount;
_glfwInputJoystick(js, GLFW_CONNECTED);
return DIENUM_CONTINUE;
}
@@ -657,14 +484,14 @@ void _glfwInitJoysticksWin32(void)
{
if (_glfw.win32.dinput8.instance)
{
if (FAILED(_glfw_DirectInput8Create(GetModuleHandle(NULL),
DIRECTINPUT_VERSION,
&IID_IDirectInput8W,
(void**) &_glfw.win32.dinput8.api,
NULL)))
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
DIRECTINPUT_VERSION,
&IID_IDirectInput8W,
(void**) &_glfw.win32.dinput8.api,
NULL)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"DI: Failed to create interface");
"Win32: Failed to create interface");
}
}
@@ -675,10 +502,10 @@ void _glfwInitJoysticksWin32(void)
//
void _glfwTerminateJoysticksWin32(void)
{
int joy;
int jid;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
closeJoystick(_glfw.win32_js + joy);
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
closeJoystick(_glfw.joysticks + jid);
if (_glfw.win32.dinput8.api)
IDirectInput8_Release(_glfw.win32.dinput8.api);
@@ -690,10 +517,43 @@ void _glfwDetectJoystickConnectionWin32(void)
{
if (_glfw.win32.xinput.instance)
{
DWORD i;
DWORD index;
for (i = 0; i < XUSER_MAX_COUNT; i++)
openXinputDevice(i);
for (index = 0; index < XUSER_MAX_COUNT; index++)
{
int jid;
char guid[33];
XINPUT_CAPABILITIES xic;
_GLFWjoystick* js;
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (_glfw.joysticks[jid].present &&
_glfw.joysticks[jid].win32.device == NULL &&
_glfw.joysticks[jid].win32.index == index)
{
break;
}
}
if (jid <= GLFW_JOYSTICK_LAST)
continue;
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
continue;
// Generate a joystick GUID that matches the SDL 2.0.5+ one
sprintf(guid, "78696e707574%02x000000000000000000",
xic.SubType & 0xff);
js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1);
if (!js)
continue;
js->win32.index = index;
_glfwInputJoystick(js, GLFW_CONNECTED);
}
}
if (_glfw.win32.dinput8.api)
@@ -715,10 +575,14 @@ void _glfwDetectJoystickConnectionWin32(void)
//
void _glfwDetectJoystickDisconnectionWin32(void)
{
int joy;
int jid;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
pollJoystickState(_glfw.win32_js + joy, _GLFW_PRESENCE_ONLY);
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{
_GLFWjoystick* js = _glfw.joysticks + jid;
if (js->present)
_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
}
}
@@ -726,38 +590,174 @@ void _glfwDetectJoystickDisconnectionWin32(void)
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformJoystickPresent(int joy)
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
{
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
return pollJoystickState(js, _GLFW_PRESENCE_ONLY);
if (js->win32.device)
{
int i, ai = 0, bi = 0, pi = 0;
HRESULT result;
DIJOYSTATE state;
IDirectInputDevice8_Poll(js->win32.device);
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
sizeof(state),
&state);
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
{
IDirectInputDevice8_Acquire(js->win32.device);
IDirectInputDevice8_Poll(js->win32.device);
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
sizeof(state),
&state);
}
if (FAILED(result))
{
closeJoystick(js);
return GLFW_FALSE;
}
if (mode == _GLFW_POLL_PRESENCE)
return GLFW_TRUE;
for (i = 0; i < js->win32.objectCount; i++)
{
const void* data = (char*) &state + js->win32.objects[i].offset;
switch (js->win32.objects[i].type)
{
case _GLFW_TYPE_AXIS:
case _GLFW_TYPE_SLIDER:
{
const float value = (*((LONG*) data) + 0.5f) / 32767.5f;
_glfwInputJoystickAxis(js, ai, value);
ai++;
break;
}
case _GLFW_TYPE_BUTTON:
{
const char value = (*((BYTE*) data) & 0x80) != 0;
_glfwInputJoystickButton(js, bi, value);
bi++;
break;
}
case _GLFW_TYPE_POV:
{
const int states[9] =
{
GLFW_HAT_UP,
GLFW_HAT_RIGHT_UP,
GLFW_HAT_RIGHT,
GLFW_HAT_RIGHT_DOWN,
GLFW_HAT_DOWN,
GLFW_HAT_LEFT_DOWN,
GLFW_HAT_LEFT,
GLFW_HAT_LEFT_UP,
GLFW_HAT_CENTERED
};
// Screams of horror are appropriate at this point
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
if (state < 0 || state > 8)
state = 8;
_glfwInputJoystickHat(js, pi, states[state]);
pi++;
break;
}
}
}
}
else
{
int i, dpad = 0;
DWORD result;
XINPUT_STATE xis;
float axes[6] = { 0.f, 0.f, 0.f, 0.f, -1.f, -1.f };
const WORD buttons[10] =
{
XINPUT_GAMEPAD_A,
XINPUT_GAMEPAD_B,
XINPUT_GAMEPAD_X,
XINPUT_GAMEPAD_Y,
XINPUT_GAMEPAD_LEFT_SHOULDER,
XINPUT_GAMEPAD_RIGHT_SHOULDER,
XINPUT_GAMEPAD_BACK,
XINPUT_GAMEPAD_START,
XINPUT_GAMEPAD_LEFT_THUMB,
XINPUT_GAMEPAD_RIGHT_THUMB
};
result = XInputGetState(js->win32.index, &xis);
if (result != ERROR_SUCCESS)
{
if (result == ERROR_DEVICE_NOT_CONNECTED)
closeJoystick(js);
return GLFW_FALSE;
}
if (mode == _GLFW_POLL_PRESENCE)
return GLFW_TRUE;
if ((float) xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
(float) xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY >
(float) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE *
XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f;
axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f;
}
if ((float) xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX +
(float) xis.Gamepad.sThumbRY * xis.Gamepad.sThumbRY >
(float) XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE *
XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f;
axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f;
}
if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f;
if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
for (i = 0; i < 6; i++)
_glfwInputJoystickAxis(js, i, axes[i]);
for (i = 0; i < 10; i++)
{
const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
_glfwInputJoystickButton(js, i, value);
}
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
dpad |= GLFW_HAT_UP;
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
dpad |= GLFW_HAT_RIGHT;
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
dpad |= GLFW_HAT_DOWN;
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
dpad |= GLFW_HAT_LEFT;
_glfwInputJoystickHat(js, 0, dpad);
}
return GLFW_TRUE;
}
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
void _glfwPlatformUpdateGamepadGUID(char* guid)
{
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
return NULL;
*count = js->axisCount;
return js->axes;
}
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
{
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
return NULL;
*count = js->buttonCount;
return js->buttons;
}
const char* _glfwPlatformGetJoystickName(int joy)
{
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
if (!pollJoystickState(js, _GLFW_PRESENCE_ONLY))
return NULL;
return js->name;
if (strcmp(guid + 20, "504944564944") == 0)
{
char original[33];
strcpy(original, guid);
sprintf(guid, "03000000%.4s0000%.4s000000000000",
original, original + 4);
}
}
+6 -14
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.2 Win32 - www.glfw.org
// GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -24,13 +24,12 @@
//
//========================================================================
#ifndef _glfw3_win32_joystick_h_
#define _glfw3_win32_joystick_h_
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickWin32 win32
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int dummy
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
_GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1]
#define _GLFW_PLATFORM_MAPPING_NAME "Windows"
// Spoo
// Joystick element (axis, button or slider)
//
typedef struct _GLFWjoyobjectWin32
{
@@ -42,14 +41,8 @@ typedef struct _GLFWjoyobjectWin32
//
typedef struct _GLFWjoystickWin32
{
GLFWbool present;
float* axes;
int axisCount;
unsigned char* buttons;
int buttonCount;
_GLFWjoyobjectWin32* objects;
int objectCount;
char* name;
IDirectInputDevice8W* device;
DWORD index;
GUID guid;
@@ -61,4 +54,3 @@ void _glfwTerminateJoysticksWin32(void);
void _glfwDetectJoystickConnectionWin32(void);
void _glfwDetectJoystickDisconnectionWin32(void);
#endif // _glfw3_win32_joystick_h_
+140 -97
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 Win32 - www.glfw.org
// GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -47,11 +47,7 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
else
name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
if (!name)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string to UTF-8");
return NULL;
}
dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
@@ -90,6 +86,116 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Poll for changes in the set of connected monitors
//
void _glfwPollMonitorsWin32(void)
{
int i, disconnectedCount;
_GLFWmonitor** disconnected = NULL;
DWORD adapterIndex, displayIndex;
DISPLAY_DEVICEW adapter, display;
_GLFWmonitor* monitor;
disconnectedCount = _glfw.monitorCount;
if (disconnectedCount)
{
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
memcpy(disconnected,
_glfw.monitors,
_glfw.monitorCount * sizeof(_GLFWmonitor*));
}
for (adapterIndex = 0; ; adapterIndex++)
{
int type = _GLFW_INSERT_LAST;
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
adapter.cb = sizeof(DISPLAY_DEVICEW);
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
break;
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
type = _GLFW_INSERT_FIRST;
for (displayIndex = 0; ; displayIndex++)
{
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
display.cb = sizeof(DISPLAY_DEVICEW);
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
break;
if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
for (i = 0; i < disconnectedCount; i++)
{
if (disconnected[i] &&
wcscmp(disconnected[i]->win32.displayName,
display.DeviceName) == 0)
{
disconnected[i] = NULL;
break;
}
}
if (i < disconnectedCount)
continue;
monitor = createMonitor(&adapter, &display);
if (!monitor)
{
free(disconnected);
return;
}
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
type = _GLFW_INSERT_LAST;
}
// HACK: If an active adapter does not have any display devices
// (as sometimes happens), add it directly as a monitor
if (displayIndex == 0)
{
for (i = 0; i < disconnectedCount; i++)
{
if (disconnected[i] &&
wcscmp(disconnected[i]->win32.adapterName,
adapter.DeviceName) == 0)
{
disconnected[i] = NULL;
break;
}
}
if (i < disconnectedCount)
continue;
monitor = createMonitor(&adapter, NULL);
if (!monitor)
{
free(disconnected);
return;
}
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
}
}
for (i = 0; i < disconnectedCount; i++)
{
if (disconnected[i])
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
}
free(disconnected);
}
// Change the current video mode
//
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
@@ -97,6 +203,7 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire
GLFWvidmode current;
const GLFWvidmode* best;
DEVMODEW dm;
LONG result;
best = _glfwChooseVideoMode(monitor, desired);
_glfwPlatformGetVideoMode(monitor, &current);
@@ -115,13 +222,34 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire
if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
dm.dmBitsPerPel = 32;
if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
&dm,
NULL,
CDS_FULLSCREEN,
NULL) != DISP_CHANGE_SUCCESSFUL)
result = ChangeDisplaySettingsExW(monitor->win32.adapterName,
&dm,
NULL,
CDS_FULLSCREEN,
NULL);
if (result != DISP_CHANGE_SUCCESSFUL)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to set video mode");
const char* description = "Unknown error";
if (result == DISP_CHANGE_BADDUALVIEW)
description = "The system uses DualView";
else if (result == DISP_CHANGE_BADFLAGS)
description = "Invalid flags";
else if (result == DISP_CHANGE_BADMODE)
description = "Graphics mode not supported";
else if (result == DISP_CHANGE_BADPARAM)
description = "Invalid parameter";
else if (result == DISP_CHANGE_FAILED)
description = "Graphics mode failed";
else if (result == DISP_CHANGE_NOTUPDATED)
description = "Failed to write to registry";
else if (result == DISP_CHANGE_RESTART)
description = "Computer restart required";
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to set video mode: %s",
description);
return GLFW_FALSE;
}
@@ -146,91 +274,6 @@ void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
{
int found = 0;
DWORD adapterIndex, displayIndex, primaryIndex = 0;
DISPLAY_DEVICEW adapter, display;
GLFWbool hasDisplays = GLFW_FALSE;
_GLFWmonitor** monitors = NULL;
*count = 0;
// HACK: Check if any active adapters have connected displays
// If not, this is a headless system or a VMware guest
for (adapterIndex = 0; ; adapterIndex++)
{
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
adapter.cb = sizeof(DISPLAY_DEVICEW);
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
break;
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
display.cb = sizeof(DISPLAY_DEVICEW);
if (EnumDisplayDevicesW(adapter.DeviceName, 0, &display, 0))
{
hasDisplays = GLFW_TRUE;
break;
}
}
for (adapterIndex = 0; ; adapterIndex++)
{
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
adapter.cb = sizeof(DISPLAY_DEVICEW);
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
break;
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
primaryIndex = found;
if (hasDisplays)
{
for (displayIndex = 0; ; displayIndex++)
{
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
display.cb = sizeof(DISPLAY_DEVICEW);
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
break;
found++;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
monitors[found - 1] = createMonitor(&adapter, &display);
}
}
else
{
found++;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
monitors[found - 1] = createMonitor(&adapter, NULL);
}
}
_GLFW_SWAP_POINTERS(monitors[0], monitors[primaryIndex]);
*count = found;
return monitors;
}
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
{
if (wcslen(first->win32.displayName))
return wcscmp(first->win32.displayName, second->win32.displayName) == 0;
else
return wcscmp(first->win32.adapterName, second->win32.adapterName) == 0;
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{
DEVMODEW settings;
+58 -53
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 Win32 - www.glfw.org
// GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -25,9 +25,6 @@
//
//========================================================================
#ifndef _glfw3_win32_platform_h_
#define _glfw3_win32_platform_h_
// We don't need all the fancy stuff
#ifndef NOMINMAX
#define NOMINMAX
@@ -161,33 +158,33 @@ typedef enum PROCESS_DPI_AWARENESS
#endif
// winmm.dll function pointer typedefs
typedef DWORD (WINAPI * TIMEGETTIME_T)(void);
#define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime
typedef DWORD (WINAPI * PFN_timeGetTime)(void);
#define timeGetTime _glfw.win32.winmm.GetTime
// xinput.dll function pointer typedefs
typedef DWORD (WINAPI * XINPUTGETCAPABILITIES_T)(DWORD,DWORD,XINPUT_CAPABILITIES*);
typedef DWORD (WINAPI * XINPUTGETSTATE_T)(DWORD,XINPUT_STATE*);
#define _glfw_XInputGetCapabilities _glfw.win32.xinput.XInputGetCapabilities
#define _glfw_XInputGetState _glfw.win32.xinput.XInputGetState
typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
#define XInputGetCapabilities _glfw.win32.xinput.GetCapabilities
#define XInputGetState _glfw.win32.xinput.GetState
// dinput8.dll function pointer typedefs
typedef HRESULT (WINAPI * DIRECTINPUT8CREATE_T)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
#define _glfw_DirectInput8Create _glfw.win32.dinput8.DirectInput8Create
typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
#define DirectInput8Create _glfw.win32.dinput8.Create
// user32.dll function pointer typedefs
typedef BOOL (WINAPI * SETPROCESSDPIAWARE_T)(void);
typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);
typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);
#define _glfw_SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware
#define _glfw_ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx
// dwmapi.dll function pointer typedefs
typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*);
typedef HRESULT (WINAPI * DWMFLUSH_T)(VOID);
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
#define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled
#define _glfw_DwmFlush _glfw.win32.dwmapi.DwmFlush
// shcore.dll function pointer typedefs
typedef HRESULT (WINAPI * SETPROCESSDPIAWARENESS_T)(PROCESS_DPI_AWARENESS);
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
#define _glfw_SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
@@ -207,6 +204,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
#include "win32_joystick.h"
#include "wgl_context.h"
#include "egl_context.h"
#include "osmesa_context.h"
#define _GLFW_WNDCLASSNAME L"GLFW30"
@@ -219,10 +217,11 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerWin32 win32
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32
#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsWin32 win32
#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexWin32 win32
// Win32-specific per-window data
@@ -235,65 +234,67 @@ typedef struct _GLFWwindowWin32
GLFWbool cursorTracked;
GLFWbool iconified;
GLFWbool maximized;
// The last received cursor position, regardless of source
int lastCursorPosX, lastCursorPosY;
} _GLFWwindowWin32;
// Win32-specific global data
//
typedef struct _GLFWlibraryWin32
{
HWND helperWindowHandle;
DWORD foregroundLockTimeout;
int acquiredMonitorCount;
char* clipboardString;
char keyName[64];
short int publicKeys[512];
short int nativeKeys[GLFW_KEY_LAST + 1];
short int keycodes[512];
short int scancodes[GLFW_KEY_LAST + 1];
// Where to place the cursor when re-enabled
double restoreCursorPosX, restoreCursorPosY;
// The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow;
RAWINPUT* rawInput;
int rawInputSize;
struct {
HINSTANCE instance;
TIMEGETTIME_T timeGetTime;
HINSTANCE instance;
PFN_timeGetTime GetTime;
} winmm;
struct {
HINSTANCE instance;
DIRECTINPUT8CREATE_T DirectInput8Create;
IDirectInput8W* api;
HINSTANCE instance;
PFN_DirectInput8Create Create;
IDirectInput8W* api;
} dinput8;
struct {
HINSTANCE instance;
XINPUTGETCAPABILITIES_T XInputGetCapabilities;
XINPUTGETSTATE_T XInputGetState;
HINSTANCE instance;
PFN_XInputGetCapabilities GetCapabilities;
PFN_XInputGetState GetState;
} xinput;
struct {
HINSTANCE instance;
SETPROCESSDPIAWARE_T SetProcessDPIAware;
CHANGEWINDOWMESSAGEFILTEREX_T ChangeWindowMessageFilterEx;
HINSTANCE instance;
PFN_SetProcessDPIAware SetProcessDPIAware;
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx;
} user32;
struct {
HINSTANCE instance;
DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled;
DWMFLUSH_T DwmFlush;
HINSTANCE instance;
PFN_DwmIsCompositionEnabled DwmIsCompositionEnabled;
PFN_DwmFlush DwmFlush;
} dwmapi;
struct {
HINSTANCE instance;
SETPROCESSDPIAWARENESS_T SetProcessDpiAwareness;
HINSTANCE instance;
PFN_SetProcessDpiAwareness SetProcessDpiAwareness;
} shcore;
} _GLFWlibraryWin32;
// Win32-specific per-monitor data
//
typedef struct _GLFWmonitorWin32
@@ -308,48 +309,52 @@ typedef struct _GLFWmonitorWin32
} _GLFWmonitorWin32;
// Win32-specific per-cursor data
//
typedef struct _GLFWcursorWin32
{
HCURSOR handle;
HCURSOR handle;
} _GLFWcursorWin32;
// Win32-specific global timer data
//
typedef struct _GLFWtimeWin32
typedef struct _GLFWtimerWin32
{
GLFWbool hasPC;
uint64_t frequency;
} _GLFWtimeWin32;
} _GLFWtimerWin32;
// Win32-specific global TLS data
// Win32-specific thread local storage data
//
typedef struct _GLFWtlsWin32
{
GLFWbool allocated;
DWORD context;
GLFWbool allocated;
DWORD index;
} _GLFWtlsWin32;
// Win32-specific mutex data
//
typedef struct _GLFWmutexWin32
{
GLFWbool allocated;
CRITICAL_SECTION section;
} _GLFWmutexWin32;
GLFWbool _glfwRegisterWindowClassWin32(void);
void _glfwUnregisterWindowClassWin32(void);
GLFWbool _glfwInitThreadLocalStorageWin32(void);
void _glfwTerminateThreadLocalStorageWin32(void);
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
void _glfwInputErrorWin32(int error, const char* description);
void _glfwInitTimerWin32(void);
void _glfwPollMonitorsWin32(void);
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
#endif // _glfw3_win32_platform_h_
+97
View File
@@ -0,0 +1,97 @@
//========================================================================
// GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
#include <assert.h>
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
{
assert(tls->win32.allocated == GLFW_FALSE);
tls->win32.index = TlsAlloc();
if (tls->win32.index == TLS_OUT_OF_INDEXES)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to allocate TLS index");
return GLFW_FALSE;
}
tls->win32.allocated = GLFW_TRUE;
return GLFW_TRUE;
}
void _glfwPlatformDestroyTls(_GLFWtls* tls)
{
if (tls->win32.allocated)
TlsFree(tls->win32.index);
memset(tls, 0, sizeof(_GLFWtls));
}
void* _glfwPlatformGetTls(_GLFWtls* tls)
{
assert(tls->win32.allocated == GLFW_TRUE);
return TlsGetValue(tls->win32.index);
}
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
{
assert(tls->win32.allocated == GLFW_TRUE);
TlsSetValue(tls->win32.index, value);
}
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
{
assert(mutex->win32.allocated == GLFW_FALSE);
InitializeCriticalSection(&mutex->win32.section);
return mutex->win32.allocated = GLFW_TRUE;
}
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
{
if (mutex->win32.allocated)
DeleteCriticalSection(&mutex->win32.section);
memset(mutex, 0, sizeof(_GLFWmutex));
}
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
{
assert(mutex->win32.allocated == GLFW_TRUE);
EnterCriticalSection(&mutex->win32.section);
}
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
{
assert(mutex->win32.allocated == GLFW_TRUE);
LeaveCriticalSection(&mutex->win32.section);
}
+9 -9
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 Win32 - www.glfw.org
// GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -40,13 +40,13 @@ void _glfwInitTimerWin32(void)
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
{
_glfw.win32_time.hasPC = GLFW_TRUE;
_glfw.win32_time.frequency = frequency;
_glfw.timer.win32.hasPC = GLFW_TRUE;
_glfw.timer.win32.frequency = frequency;
}
else
{
_glfw.win32_time.hasPC = GLFW_FALSE;
_glfw.win32_time.frequency = 1000;
_glfw.timer.win32.hasPC = GLFW_FALSE;
_glfw.timer.win32.frequency = 1000;
}
}
@@ -57,18 +57,18 @@ void _glfwInitTimerWin32(void)
uint64_t _glfwPlatformGetTimerValue(void)
{
if (_glfw.win32_time.hasPC)
if (_glfw.timer.win32.hasPC)
{
uint64_t value;
QueryPerformanceCounter((LARGE_INTEGER*) &value);
return value;
}
else
return (uint64_t) _glfw_timeGetTime();
return (uint64_t) timeGetTime();
}
uint64_t _glfwPlatformGetTimerFrequency(void)
{
return _glfw.win32_time.frequency;
return _glfw.timer.win32.frequency;
}
+306 -231
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 Win32 - www.glfw.org
// GLFW 3.3 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -46,9 +46,11 @@ static DWORD getWindowStyle(const _GLFWwindow* window)
style |= WS_POPUP;
else
{
style |= WS_SYSMENU | WS_MINIMIZEBOX;
if (window->decorated)
{
style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
style |= WS_CAPTION;
if (window->resizable)
style |= WS_MAXIMIZEBOX | WS_THICKFRAME;
@@ -131,16 +133,16 @@ static HICON createIcon(const GLFWimage* image,
if (!color)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to create RGBA bitmap");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create RGBA bitmap");
return NULL;
}
mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
if (!mask)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to create mask bitmap");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create mask bitmap");
DeleteObject(color);
return NULL;
}
@@ -170,9 +172,15 @@ static HICON createIcon(const GLFWimage* image,
if (!handle)
{
if (icon)
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create icon");
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create icon");
}
else
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create cursor");
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create cursor");
}
}
return handle;
@@ -278,6 +286,26 @@ static void updateClipRect(_GLFWwindow* window)
ClipCursor(NULL);
}
// Update native window styles to match attributes
//
static void updateWindowStyles(const _GLFWwindow* window)
{
RECT rect;
DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
style &= ~(WS_OVERLAPPEDWINDOW | WS_POPUP);
style |= getWindowStyle(window);
GetClientRect(window->win32.handle, &rect);
AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window));
ClientToScreen(window->win32.handle, (POINT*) &rect.left);
ClientToScreen(window->win32.handle, (POINT*) &rect.right);
SetWindowLongW(window->win32.handle, GWL_STYLE, style);
SetWindowPos(window->win32.handle, HWND_TOP,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
}
// Translates a GLFW standard cursor to a resource ID
//
static LPWSTR translateCursorShape(int shape)
@@ -341,20 +369,19 @@ static int getAsyncKeyMods(void)
//
static int translateKey(WPARAM wParam, LPARAM lParam)
{
// The Ctrl keys require special handling
if (wParam == VK_CONTROL)
{
// The CTRL keys require special handling
MSG next;
DWORD time;
// Is this an extended key (i.e. right key)?
// Right side keys have the extended key bit set
if (lParam & 0x01000000)
return GLFW_KEY_RIGHT_CONTROL;
// Here is a trick: "Alt Gr" sends LCTRL, then RALT. We only
// want the RALT message, so we try to see if the next message
// is a RALT message. In that case, this is a false LCTRL!
// 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))
@@ -368,8 +395,7 @@ static int translateKey(WPARAM wParam, LPARAM lParam)
(next.lParam & 0x01000000) &&
next.time == time)
{
// Next message is a RALT down message, which
// means that this is not a proper LCTRL message
// Next message is Right Alt down so discard this
return _GLFW_KEY_INVALID;
}
}
@@ -385,7 +411,7 @@ static int translateKey(WPARAM wParam, LPARAM lParam)
return _GLFW_KEY_INVALID;
}
return _glfw.win32.publicKeys[HIWORD(lParam) & 0x1FF];
return _glfw.win32.keycodes[HIWORD(lParam) & 0x1FF];
}
// Make the specified window and its video mode active on its monitor
@@ -396,6 +422,11 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
GLFWbool status;
int xpos, ypos;
if (!_glfw.win32.acquiredMonitorCount)
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
if (!window->monitor->window)
_glfw.win32.acquiredMonitorCount++;
status = _glfwSetVideoModeWin32(window->monitor, &window->videoMode);
_glfwPlatformGetVideoMode(window->monitor, &mode);
@@ -405,7 +436,7 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
xpos, ypos, mode.width, mode.height,
SWP_NOACTIVATE | SWP_NOCOPYBITS);
_glfwInputMonitorWindowChange(window->monitor, window);
_glfwInputMonitorWindow(window->monitor, window);
return status;
}
@@ -416,7 +447,11 @@ static void releaseMonitor(_GLFWwindow* window)
if (window->monitor->window != window)
return;
_glfwInputMonitorWindowChange(window->monitor, NULL);
_glfw.win32.acquiredMonitorCount--;
if (!_glfw.win32.acquiredMonitorCount)
SetThreadExecutionState(ES_CONTINUOUS);
_glfwInputMonitorWindow(window->monitor, NULL);
_glfwRestoreVideoModeWin32(window->monitor);
}
@@ -432,30 +467,23 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
switch (uMsg)
{
case WM_DISPLAYCHANGE:
_glfwPollMonitorsWin32();
break;
case WM_DEVICECHANGE:
{
if (wParam == DBT_DEVNODES_CHANGED)
{
_glfwInputMonitorChange();
return TRUE;
}
else if (wParam == DBT_DEVICEARRIVAL)
if (wParam == DBT_DEVICEARRIVAL)
{
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
if (dbh)
{
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
_glfwDetectJoystickConnectionWin32();
}
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
_glfwDetectJoystickConnectionWin32();
}
else if (wParam == DBT_DEVICEREMOVECOMPLETE)
{
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
if (dbh)
{
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
_glfwDetectJoystickDisconnectionWin32();
}
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
_glfwDetectJoystickDisconnectionWin32();
}
break;
@@ -552,14 +580,15 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (action == GLFW_RELEASE && wParam == VK_SHIFT)
{
// Release both Shift keys on Shift up event, as only one event
// is sent even if both keys are released
// HACK: Release both Shift keys on Shift up event, as when both
// are pressed the first release does not emit any event
// NOTE: The other half of this is in _glfwPlatformPollEvents
_glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods);
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods);
}
else if (wParam == VK_SNAPSHOT)
{
// Key down is not reported for the Print Screen key
// HACK: Key down is not reported for the Print Screen key
_glfwInputKey(window, key, scancode, GLFW_PRESS, mods);
_glfwInputKey(window, key, scancode, GLFW_RELEASE, mods);
}
@@ -578,7 +607,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MBUTTONUP:
case WM_XBUTTONUP:
{
int button, action;
int i, button, action;
if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
button = GLFW_MOUSE_BUTTON_LEFT;
@@ -595,16 +624,30 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
uMsg == WM_MBUTTONDOWN || uMsg == WM_XBUTTONDOWN)
{
action = GLFW_PRESS;
SetCapture(hWnd);
}
else
{
action = GLFW_RELEASE;
ReleaseCapture();
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
{
if (window->mouseButtons[i] == GLFW_PRESS)
break;
}
if (i > GLFW_MOUSE_BUTTON_LAST)
SetCapture(hWnd);
_glfwInputMouseClick(window, button, action, getKeyMods());
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
{
if (window->mouseButtons[i] == GLFW_PRESS)
break;
}
if (i > GLFW_MOUSE_BUTTON_LAST)
ReleaseCapture();
if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP)
return TRUE;
@@ -616,20 +659,11 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
const int x = GET_X_LPARAM(lParam);
const int y = GET_Y_LPARAM(lParam);
// Disabled cursor motion input is provided by WM_INPUT
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
const int dx = x - window->win32.lastCursorPosX;
const int dy = y - window->win32.lastCursorPosY;
break;
if (_glfw.win32.disabledCursorWindow != window)
break;
_glfwInputCursorPos(window,
window->virtualCursorPosX + dx,
window->virtualCursorPosY + dy);
}
else
_glfwInputCursorPos(window, x, y);
_glfwInputCursorPos(window, x, y);
window->win32.lastCursorPosX = x;
window->win32.lastCursorPosY = y;
@@ -650,6 +684,56 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
return 0;
}
case WM_INPUT:
{
UINT size;
HRAWINPUT ri = (HRAWINPUT) lParam;
RAWINPUT* data;
int dx, dy;
// Only process input when disabled cursor mode is applied
if (_glfw.win32.disabledCursorWindow != window)
break;
GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
if (size > (UINT) _glfw.win32.rawInputSize)
{
free(_glfw.win32.rawInput);
_glfw.win32.rawInput = calloc(size, 1);
_glfw.win32.rawInputSize = size;
}
size = _glfw.win32.rawInputSize;
if (GetRawInputData(ri, RID_INPUT,
_glfw.win32.rawInput, &size,
sizeof(RAWINPUTHEADER)) == (UINT) -1)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to retrieve raw input data");
break;
}
data = _glfw.win32.rawInput;
if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
{
dx = data->data.mouse.lLastX - window->win32.lastCursorPosX;
dy = data->data.mouse.lLastY - window->win32.lastCursorPosY;
}
else
{
dx = data->data.mouse.lLastX;
dy = data->data.mouse.lLastY;
}
_glfwInputCursorPos(window,
window->virtualCursorPosX + dx,
window->virtualCursorPosY + dy);
window->win32.lastCursorPosX += dx;
window->win32.lastCursorPosY += dy;
break;
}
case WM_MOUSELEAVE:
{
window->win32.cursorTracked = GLFW_FALSE;
@@ -666,7 +750,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MOUSEHWHEEL:
{
// This message is only sent on Windows Vista and later
// NOTE: The X-axis is inverted for consistency with OS X and X11.
// NOTE: The X-axis is inverted for consistency with macOS and X11
_glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
return 0;
}
@@ -691,36 +775,33 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_SIZE:
{
const GLFWbool iconified =
!window->win32.iconified && wParam == SIZE_MINIMIZED;
const GLFWbool restored =
window->win32.iconified &&
(wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED);
const GLFWbool iconified = wParam == SIZE_MINIMIZED;
const GLFWbool maximized = wParam == SIZE_MAXIMIZED ||
(window->win32.maximized &&
wParam != SIZE_RESTORED);
if (_glfw.win32.disabledCursorWindow == window)
updateClipRect(window);
if (iconified)
_glfwInputWindowIconify(window, GLFW_TRUE);
else if (restored)
_glfwInputWindowIconify(window, GLFW_FALSE);
if (window->win32.iconified != iconified)
_glfwInputWindowIconify(window, iconified);
if (window->win32.maximized != maximized)
_glfwInputWindowMaximize(window, maximized);
_glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));
_glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));
if (iconified)
if (window->monitor && window->win32.iconified != iconified)
{
window->win32.iconified = GLFW_TRUE;
if (window->monitor)
if (iconified)
releaseMonitor(window);
}
else if (restored)
{
window->win32.iconified = GLFW_FALSE;
if (window->monitor)
else
acquireMonitor(window);
}
window->win32.iconified = iconified;
window->win32.maximized = maximized;
return 0;
}
@@ -850,9 +931,10 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
// Creates the GLFW window and rendering context
// Creates the GLFW window
//
static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
static int createNativeWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig)
{
int xpos, ypos, fullWidth, fullHeight;
WCHAR* wideTitle;
@@ -865,7 +947,7 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
// NOTE: This window placement is temporary and approximate, as the
// correct position and size cannot be known until the monitor
// video mode has been set
// video mode has been picked in _glfwSetVideoModeWin32
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
_glfwPlatformGetVideoMode(window->monitor, &mode);
fullWidth = mode.width;
@@ -886,11 +968,7 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
if (!wideTitle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert window title to UTF-16");
return GLFW_FALSE;
}
window->win32.handle = CreateWindowExW(exStyle,
_GLFW_WNDCLASSNAME,
@@ -907,7 +985,8 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
if (!window->win32.handle)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create window");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create window");
return GLFW_FALSE;
}
@@ -928,21 +1007,6 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
return GLFW_TRUE;
}
// Destroys the GLFW window and rendering context
//
static void destroyWindow(_GLFWwindow* window)
{
if (_glfw.win32.disabledCursorWindow == window)
_glfw.win32.disabledCursorWindow = NULL;
if (window->win32.handle)
{
RemovePropW(window->win32.handle, L"GLFW");
DestroyWindow(window->win32.handle);
window->win32.handle = NULL;
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
@@ -976,8 +1040,8 @@ GLFWbool _glfwRegisterWindowClassWin32(void)
if (!RegisterClassExW(&wc))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to register window class");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to register window class");
return GLFW_FALSE;
}
@@ -1001,63 +1065,32 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
int status;
if (!createWindow(window, wndconfig))
if (!createNativeWindow(window, wndconfig))
return GLFW_FALSE;
if (ctxconfig->client != GLFW_NO_API)
{
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
{
if (!_glfwInitWGL())
return GLFW_FALSE;
if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
status = _glfwAnalyzeContextWGL(window, ctxconfig, fbconfig);
if (status == _GLFW_RECREATION_IMPOSSIBLE)
return GLFW_FALSE;
if (status == _GLFW_RECREATION_REQUIRED)
{
// Some window hints require us to re-create the context using WGL
// extensions retrieved through the current context, as we cannot
// check for WGL extensions or retrieve WGL entry points before we
// have a current context (actually until we have implicitly loaded
// the vendor ICD)
// Yes, this is strange, and yes, this is the proper way on WGL
// As Windows only allows you to set the pixel format once for
// a window, we need to destroy the current window and create a new
// one to be able to use the new pixel format
// Technically, it may be possible to keep the old window around if
// we're just creating an OpenGL 3.0+ context with the same pixel
// format, but it's not worth the added code complexity
// First we clear the current context (the one we just created)
// This is usually done by glfwDestroyWindow, but as we're not doing
// full GLFW window destruction, it's duplicated here
window->context.makeCurrent(NULL);
// Next destroy the Win32 window and WGL context (without resetting
// or destroying the GLFW window object)
window->context.destroy(window);
destroyWindow(window);
// ...and then create them again, this time with better APIs
if (!createWindow(window, wndconfig))
return GLFW_FALSE;
if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
}
else
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
{
if (!_glfwInitEGL())
return GLFW_FALSE;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{
if (!_glfwInitOSMesa())
return GLFW_FALSE;
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
}
if (window->monitor)
@@ -1067,7 +1100,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!acquireMonitor(window))
return GLFW_FALSE;
centerCursor(window);
if (wndconfig->centerCursor)
centerCursor(window);
}
return GLFW_TRUE;
@@ -1078,10 +1112,18 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
if (window->monitor)
releaseMonitor(window);
if (window->context.client != GLFW_NO_API)
if (window->context.destroy)
window->context.destroy(window);
destroyWindow(window);
if (_glfw.win32.disabledCursorWindow == window)
_glfw.win32.disabledCursorWindow = NULL;
if (window->win32.handle)
{
RemovePropW(window->win32.handle, L"GLFW");
DestroyWindow(window->win32.handle);
window->win32.handle = NULL;
}
if (window->win32.bigIcon)
DestroyIcon(window->win32.bigIcon);
@@ -1094,11 +1136,7 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
{
WCHAR* wideTitle = _glfwCreateWideStringFromUTF8Win32(title);
if (!wideTitle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert window title to UTF-16");
return;
}
SetWindowTextW(window->win32.handle, wideTitle);
free(wideTitle);
@@ -1278,6 +1316,11 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
ShowWindow(window->win32.handle, SW_HIDE);
}
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
{
FlashWindow(window->win32.handle, TRUE);
}
void _glfwPlatformFocusWindow(_GLFWwindow* window)
{
BringWindowToTop(window->win32.handle);
@@ -1285,6 +1328,12 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
SetFocus(window->win32.handle);
}
void _glfwPlatformDragWindow(_GLFWwindow* window)
{
ReleaseCapture();
SendMessage(window->win32.handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
@@ -1391,6 +1440,23 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return IsZoomed(window->win32.handle);
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
updateWindowStyles(window);
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
updateWindowStyles(window);
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
const HWND after = enabled ? HWND_TOPMOST : HWND_NOTOPMOST;
SetWindowPos(window->win32.handle, after, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}
void _glfwPlatformPollEvents(void)
{
MSG msg;
@@ -1401,9 +1467,9 @@ void _glfwPlatformPollEvents(void)
{
if (msg.message == WM_QUIT)
{
// Treat WM_QUIT as a close on all windows
// While GLFW does not itself post WM_QUIT, other processes may post
// it to this one, for example Task Manager
// NOTE: While GLFW does not itself post WM_QUIT, other processes
// may post it to this one, for example Task Manager
// HACK: Treat WM_QUIT as a close on all windows
window = _glfw.windowListHead;
while (window)
@@ -1422,25 +1488,28 @@ void _glfwPlatformPollEvents(void)
handle = GetActiveWindow();
if (handle)
{
// LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix)
// This is the only async event handling in GLFW, but it solves some
// nasty problems
// 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");
if (window)
{
const int mods = getAsyncKeyMods();
const GLFWbool lshift = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;
const GLFWbool rshift = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;
// Get current state of left and right shift keys
const int lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;
const int rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;
// See if this differs from our belief of what has happened
// (we only have to check for lost key up events)
if (!lshiftDown && window->keys[GLFW_KEY_LEFT_SHIFT] == 1)
_glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, 0, GLFW_RELEASE, mods);
if (!rshiftDown && window->keys[GLFW_KEY_RIGHT_SHIFT] == 1)
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, 0, GLFW_RELEASE, mods);
if (!lshift && window->keys[GLFW_KEY_LEFT_SHIFT] == GLFW_PRESS)
{
const int mods = getAsyncKeyMods();
const int scancode = _glfw.win32.scancodes[GLFW_KEY_LEFT_SHIFT];
_glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, GLFW_RELEASE, mods);
}
else if (!rshift && window->keys[GLFW_KEY_RIGHT_SHIFT] == GLFW_PRESS)
{
const int mods = getAsyncKeyMods();
const int scancode = _glfw.win32.scancodes[GLFW_KEY_RIGHT_SHIFT];
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, GLFW_RELEASE, mods);
}
}
}
@@ -1476,8 +1545,7 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
void _glfwPlatformPostEmptyEvent(void)
{
_GLFWwindow* window = _glfw.windowListHead;
PostMessage(window->win32.handle, WM_NULL, 0, 0);
PostMessage(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
}
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
@@ -1511,36 +1579,46 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
if (mode == GLFW_CURSOR_DISABLED)
{
const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };
_glfw.win32.disabledCursorWindow = window;
_glfwPlatformGetCursorPos(window,
&_glfw.win32.restoreCursorPosX,
&_glfw.win32.restoreCursorPosY);
centerCursor(window);
updateClipRect(window);
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to register raw input device");
}
}
else if (_glfw.win32.disabledCursorWindow == window)
{
const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL };
_glfw.win32.disabledCursorWindow = NULL;
updateClipRect(NULL);
_glfwPlatformSetCursorPos(window,
_glfw.win32.restoreCursorPosX,
_glfw.win32.restoreCursorPosY);
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to remove raw input device");
}
}
if (cursorInClientArea(window))
updateCursorImage(window);
}
const char* _glfwPlatformGetKeyName(int key, int scancode)
const char* _glfwPlatformGetScancodeName(int scancode)
{
WCHAR name[16];
if (key != GLFW_KEY_UNKNOWN)
scancode = _glfw.win32.nativeKeys[key];
if (!_glfwIsPrintable(_glfw.win32.publicKeys[scancode]))
return NULL;
if (!GetKeyNameTextW(scancode << 16, name, sizeof(name) / sizeof(WCHAR)))
return NULL;
@@ -1555,6 +1633,11 @@ const char* _glfwPlatformGetKeyName(int key, int scancode)
return _glfw.win32.keyName;
}
int _glfwPlatformGetKeyScancode(int key)
{
return _glfw.win32.scancodes[key];
}
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot)
@@ -1572,8 +1655,8 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
CopyCursor(LoadCursorW(NULL, translateCursorShape(shape)));
if (!cursor->win32.handle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to create standard cursor");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create standard cursor");
return GLFW_FALSE;
}
@@ -1594,101 +1677,93 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
{
WCHAR* wideString;
HANDLE stringHandle;
size_t wideSize;
int characterCount;
HANDLE object;
WCHAR* buffer;
wideString = _glfwCreateWideStringFromUTF8Win32(string);
if (!wideString)
characterCount = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
if (!characterCount)
return;
object = GlobalAlloc(GMEM_MOVEABLE, characterCount * sizeof(WCHAR));
if (!object)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string to UTF-16");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to allocate global handle for clipboard");
return;
}
wideSize = (wcslen(wideString) + 1) * sizeof(WCHAR);
stringHandle = GlobalAlloc(GMEM_MOVEABLE, wideSize);
if (!stringHandle)
buffer = GlobalLock(object);
if (!buffer)
{
free(wideString);
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to allocate global handle for clipboard");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to lock global handle");
GlobalFree(object);
return;
}
memcpy(GlobalLock(stringHandle), wideString, wideSize);
GlobalUnlock(stringHandle);
MultiByteToWideChar(CP_UTF8, 0, string, -1, buffer, characterCount);
GlobalUnlock(object);
if (!OpenClipboard(_glfw.win32.helperWindowHandle))
{
GlobalFree(stringHandle);
free(wideString);
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to open clipboard");
GlobalFree(object);
return;
}
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, stringHandle);
SetClipboardData(CF_UNICODETEXT, object);
CloseClipboard();
free(wideString);
}
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
{
HANDLE stringHandle;
HANDLE object;
WCHAR* buffer;
if (!OpenClipboard(_glfw.win32.helperWindowHandle))
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard");
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to open clipboard");
return NULL;
}
stringHandle = GetClipboardData(CF_UNICODETEXT);
if (!stringHandle)
object = GetClipboardData(CF_UNICODETEXT);
if (!object)
{
_glfwInputErrorWin32(GLFW_FORMAT_UNAVAILABLE,
"Win32: Failed to convert clipboard to string");
CloseClipboard();
return NULL;
}
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"Win32: Failed to convert clipboard to string");
buffer = GlobalLock(object);
if (!buffer)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to lock global handle");
CloseClipboard();
return NULL;
}
free(_glfw.win32.clipboardString);
_glfw.win32.clipboardString =
_glfwCreateUTF8FromWideStringWin32(GlobalLock(stringHandle));
_glfw.win32.clipboardString = _glfwCreateUTF8FromWideStringWin32(buffer);
GlobalUnlock(stringHandle);
GlobalUnlock(object);
CloseClipboard();
if (!_glfw.win32.clipboardString)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert wide string to UTF-8");
return NULL;
}
return _glfw.win32.clipboardString;
}
char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
{
char** extensions;
if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_win32_surface)
return;
*count = 0;
if (!_glfw.vk.KHR_win32_surface)
return NULL;
extensions = calloc(2, sizeof(char*));
extensions[0] = strdup("VK_KHR_surface");
extensions[1] = strdup("VK_KHR_win32_surface");
*count = 2;
return extensions;
extensions[0] = "VK_KHR_surface";
extensions[1] = "VK_KHR_win32_surface";
}
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+145 -31
View File
@@ -1,8 +1,8 @@
//========================================================================
// GLFW 3.2 - www.glfw.org
// GLFW 3.3 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
//
// This software is provided 'as-is', without any express or implied
@@ -40,30 +40,26 @@
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
{
if (focused)
{
if (window->callbacks.focus)
window->callbacks.focus((GLFWwindow*) window, focused);
}
else
{
int i;
if (window->callbacks.focus)
window->callbacks.focus((GLFWwindow*) window, focused);
if (window->callbacks.focus)
window->callbacks.focus((GLFWwindow*) window, focused);
if (!focused)
{
int key, button;
// Release all pressed keyboard keys
for (i = 0; i <= GLFW_KEY_LAST; i++)
for (key = 0; key <= GLFW_KEY_LAST; key++)
{
if (window->keys[i] == GLFW_PRESS)
_glfwInputKey(window, i, 0, GLFW_RELEASE, 0);
if (window->keys[key] == GLFW_PRESS)
{
const int scancode = _glfwPlatformGetKeyScancode(key);
_glfwInputKey(window, key, scancode, GLFW_RELEASE, 0);
}
}
// Release all pressed mouse buttons
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
for (button = 0; button <= GLFW_MOUSE_BUTTON_LAST; button++)
{
if (window->mouseButtons[i] == GLFW_PRESS)
_glfwInputMouseClick(window, i, GLFW_RELEASE, 0);
if (window->mouseButtons[button] == GLFW_PRESS)
_glfwInputMouseClick(window, button, GLFW_RELEASE, 0);
}
}
}
@@ -86,6 +82,12 @@ void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
window->callbacks.iconify((GLFWwindow*) window, iconified);
}
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
{
if (window->callbacks.maximize)
window->callbacks.maximize((GLFWwindow*) window, maximized);
}
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
{
if (window->callbacks.fbsize)
@@ -100,7 +102,7 @@ void _glfwInputWindowDamage(_GLFWwindow* window)
void _glfwInputWindowCloseRequest(_GLFWwindow* window)
{
window->closed = GLFW_TRUE;
window->shouldClose = GLFW_TRUE;
if (window->callbacks.close)
window->callbacks.close((GLFWwindow*) window);
@@ -128,6 +130,8 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
_GLFWwindow* previous;
assert(title != NULL);
assert(width >= 0);
assert(height >= 0);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
@@ -151,7 +155,8 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
if (ctxconfig.share)
{
if (ctxconfig.share->context.client == GLFW_NO_API)
if (ctxconfig.client == GLFW_NO_API ||
ctxconfig.share->context.client == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL;
@@ -187,7 +192,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->denom = GLFW_DONT_CARE;
// Save the currently current context so it can be restored later
previous = _glfwPlatformGetCurrentContext();
previous = _glfwPlatformGetTls(&_glfw.contextSlot);
if (ctxconfig.client != GLFW_NO_API)
glfwMakeContextCurrent(NULL);
@@ -232,15 +237,15 @@ void glfwDefaultWindowHints(void)
{
_GLFW_REQUIRE_INIT();
memset(&_glfw.hints, 0, sizeof(_glfw.hints));
// The default is OpenGL with minimum version 1.0
memset(&_glfw.hints.context, 0, sizeof(_glfw.hints.context));
_glfw.hints.context.client = GLFW_OPENGL_API;
_glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
_glfw.hints.context.major = 1;
_glfw.hints.context.minor = 0;
// The default is a focused, visible, resizable window with decorations
memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
_glfw.hints.window.resizable = GLFW_TRUE;
_glfw.hints.window.visible = GLFW_TRUE;
_glfw.hints.window.decorated = GLFW_TRUE;
@@ -249,6 +254,7 @@ void glfwDefaultWindowHints(void)
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
// double buffered
memset(&_glfw.hints.framebuffer, 0, sizeof(_glfw.hints.framebuffer));
_glfw.hints.framebuffer.redBits = 8;
_glfw.hints.framebuffer.greenBits = 8;
_glfw.hints.framebuffer.blueBits = 8;
@@ -259,6 +265,9 @@ void glfwDefaultWindowHints(void)
// The default is to select the highest available refresh rate
_glfw.hints.refreshRate = GLFW_DONT_CARE;
// The default is to use full Retina resolution framebuffers
_glfw.hints.window.ns.retina = GLFW_TRUE;
}
GLFWAPI void glfwWindowHint(int hint, int value)
@@ -333,6 +342,18 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_VISIBLE:
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
break;
case GLFW_COCOA_RETINA_FRAMEBUFFER:
_glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
break;
case GLFW_COCOA_FRAME_AUTOSAVE:
_glfw.hints.window.ns.frame = value ? GLFW_TRUE : GLFW_FALSE;
break;
case GLFW_COCOA_GRAPHICS_SWITCHING:
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
break;
case GLFW_CENTER_CURSOR:
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
break;
case GLFW_CLIENT_API:
_glfw.hints.context.client = value;
break;
@@ -367,7 +388,7 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.refreshRate = value;
break;
default:
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint %i", hint);
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
break;
}
}
@@ -387,7 +408,7 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
// The window's context must not be current on another thread when the
// window is destroyed
if (window == _glfwPlatformGetCurrentContext())
if (window == _glfwPlatformGetTls(&_glfw.contextSlot))
glfwMakeContextCurrent(NULL);
_glfwPlatformDestroyWindow(window);
@@ -411,7 +432,7 @@ GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle)
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(0);
return window->closed;
return window->shouldClose;
}
GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
@@ -420,14 +441,13 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
assert(window != NULL);
_GLFW_REQUIRE_INIT();
window->closed = value;
window->shouldClose = value;
}
GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(title != NULL);
_GLFW_REQUIRE_INIT();
@@ -491,6 +511,8 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(width >= 0);
assert(height >= 0);
_GLFW_REQUIRE_INIT();
@@ -549,6 +571,8 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(numer != 0);
assert(denom != 0);
_GLFW_REQUIRE_INIT();
@@ -627,7 +651,13 @@ GLFWAPI void glfwRestoreWindow(GLFWwindow* handle)
GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT();
if (window->monitor)
return;
_glfwPlatformMaximizeWindow(window);
}
@@ -645,6 +675,16 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle)
_glfwPlatformFocusWindow(window);
}
GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT();
_glfwPlatformRequestWindowAttention(window);
}
GLFWAPI void glfwHideWindow(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
@@ -668,6 +708,16 @@ GLFWAPI void glfwFocusWindow(GLFWwindow* handle)
_glfwPlatformFocusWindow(window);
}
GLFWAPI void glfwDragWindow(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT();
_glfwPlatformDragWindow(window);
}
GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
@@ -691,6 +741,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return window->decorated;
case GLFW_FLOATING:
return window->floating;
case GLFW_AUTO_ICONIFY:
return window->autoIconify;
case GLFW_CLIENT_API:
return window->context.client;
case GLFW_CONTEXT_CREATION_API:
@@ -715,10 +767,56 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return window->context.noerror;
}
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute %i", attrib);
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
return 0;
}
GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT();
value = value ? GLFW_TRUE : GLFW_FALSE;
switch (attrib)
{
case GLFW_RESIZABLE:
if (window->resizable != value)
{
window->resizable = value;
if (!window->monitor)
_glfwPlatformSetWindowResizable(window, value);
}
return;
case GLFW_DECORATED:
if (window->decorated != value)
{
window->decorated = value;
if (!window->monitor)
_glfwPlatformSetWindowDecorated(window, value);
}
return;
case GLFW_FLOATING:
if (window->floating != value)
{
window->floating = value;
if (!window->monitor)
_glfwPlatformSetWindowFloating(window, value);
}
return;
case GLFW_AUTO_ICONIFY:
window->autoIconify = value;
return;
}
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
}
GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
@@ -737,6 +835,8 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
_GLFWwindow* window = (_GLFWwindow*) wh;
_GLFWmonitor* monitor = (_GLFWmonitor*) mh;
assert(window != NULL);
assert(width >= 0);
assert(height >= 0);
_GLFW_REQUIRE_INIT();
@@ -849,6 +949,17 @@ GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
return cbfun;
}
GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle,
GLFWwindowmaximizefun cbfun)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.maximize, cbfun);
return cbfun;
}
GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
GLFWframebuffersizefun cbfun)
{
@@ -879,6 +990,9 @@ GLFWAPI void glfwWaitEvents(void)
GLFWAPI void glfwWaitEventsTimeout(double timeout)
{
_GLFW_REQUIRE_INIT();
assert(timeout == timeout);
assert(timeout >= 0.0);
assert(timeout <= DBL_MAX);
if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
{
+259 -174
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.2 Wayland - www.glfw.org
// GLFW 3.3 Wayland - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
@@ -109,6 +109,8 @@ static void pointerHandleButton(void* data,
if (!window)
return;
_glfw.wl.pointerSerial = serial;
/* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
* codes. */
glfwButton = button - BTN_LEFT;
@@ -128,7 +130,7 @@ static void pointerHandleAxis(void* data,
wl_fixed_t value)
{
_GLFWwindow* window = _glfw.wl.pointerFocus;
double scroll_factor;
double scrollFactor;
double x, y;
if (!window)
@@ -137,17 +139,17 @@ static void pointerHandleAxis(void* data,
/* Wayland scroll events are in pointer motion coordinate space (think
* two finger scroll). The factor 10 is commonly used to convert to
* "scroll step means 1.0. */
scroll_factor = 1.0/10.0;
scrollFactor = 1.0/10.0;
switch (axis)
{
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
x = wl_fixed_to_double(value) * scroll_factor;
x = wl_fixed_to_double(value) * scrollFactor;
y = 0.0;
break;
case WL_POINTER_AXIS_VERTICAL_SCROLL:
x = 0.0;
y = wl_fixed_to_double(value) * scroll_factor;
y = wl_fixed_to_double(value) * scrollFactor;
break;
default:
break;
@@ -172,7 +174,10 @@ static void keyboardHandleKeymap(void* data,
{
struct xkb_keymap* keymap;
struct xkb_state* state;
struct xkb_compose_table* composeTable;
struct xkb_compose_state* composeState;
char* mapStr;
const char* locale;
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
{
@@ -186,10 +191,10 @@ static void keyboardHandleKeymap(void* data,
return;
}
keymap = xkb_map_new_from_string(_glfw.wl.xkb.context,
mapStr,
XKB_KEYMAP_FORMAT_TEXT_V1,
0);
keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
mapStr,
XKB_KEYMAP_FORMAT_TEXT_V1,
0);
munmap(mapStr, size);
close(fd);
@@ -205,23 +210,52 @@ static void keyboardHandleKeymap(void* data,
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create XKB state");
xkb_map_unref(keymap);
xkb_keymap_unref(keymap);
return;
}
// Look up the preferred locale, falling back to "C" as default.
locale = getenv("LC_ALL");
if (!locale)
locale = getenv("LC_CTYPE");
if (!locale)
locale = getenv("LANG");
if (!locale)
locale = "C";
composeTable =
xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
XKB_COMPOSE_COMPILE_NO_FLAGS);
if (composeTable)
{
composeState =
xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
xkb_compose_table_unref(composeTable);
if (composeState)
_glfw.wl.xkb.composeState = composeState;
else
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create XKB compose state");
}
else
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create XKB compose table");
}
xkb_keymap_unref(_glfw.wl.xkb.keymap);
xkb_state_unref(_glfw.wl.xkb.state);
_glfw.wl.xkb.keymap = keymap;
_glfw.wl.xkb.state = state;
_glfw.wl.xkb.control_mask =
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Control");
_glfw.wl.xkb.alt_mask =
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
_glfw.wl.xkb.shift_mask =
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
_glfw.wl.xkb.super_mask =
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
_glfw.wl.xkb.controlMask =
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");
_glfw.wl.xkb.altMask =
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
_glfw.wl.xkb.shiftMask =
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
_glfw.wl.xkb.superMask =
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
}
static void keyboardHandleEnter(void* data,
@@ -252,12 +286,55 @@ static void keyboardHandleLeave(void* data,
static int toGLFWKeyCode(uint32_t key)
{
if (key < sizeof(_glfw.wl.publicKeys) / sizeof(_glfw.wl.publicKeys[0]))
return _glfw.wl.publicKeys[key];
if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
return _glfw.wl.keycodes[key];
return GLFW_KEY_UNKNOWN;
}
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
{
if (sym == XKB_KEY_NoSymbol)
return sym;
if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
!= XKB_COMPOSE_FEED_ACCEPTED)
return sym;
switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState))
{
case XKB_COMPOSE_COMPOSED:
return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState);
case XKB_COMPOSE_COMPOSING:
case XKB_COMPOSE_CANCELLED:
return XKB_KEY_NoSymbol;
case XKB_COMPOSE_NOTHING:
default:
return sym;
}
}
static void inputChar(_GLFWwindow* window, uint32_t key)
{
uint32_t code, numSyms;
long cp;
const xkb_keysym_t *syms;
xkb_keysym_t sym;
code = key + 8;
numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
if (numSyms == 1)
{
sym = composeSymbol(syms[0]);
cp = _glfwKeySym2Unicode(sym);
if (cp != -1)
{
const int mods = _glfw.wl.xkb.modifiers;
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
_glfwInputChar(window, cp, mods, plain);
}
}
}
static void keyboardHandleKey(void* data,
struct wl_keyboard* keyboard,
uint32_t serial,
@@ -265,11 +342,8 @@ static void keyboardHandleKey(void* data,
uint32_t key,
uint32_t state)
{
uint32_t code, num_syms;
long cp;
int keyCode;
int action;
const xkb_keysym_t *syms;
_GLFWwindow* window = _glfw.wl.keyboardFocus;
if (!window)
@@ -282,19 +356,8 @@ static void keyboardHandleKey(void* data,
_glfwInputKey(window, keyCode, key, action,
_glfw.wl.xkb.modifiers);
code = key + 8;
num_syms = xkb_key_get_syms(_glfw.wl.xkb.state, code, &syms);
if (num_syms == 1)
{
cp = _glfwKeySym2Unicode(syms[0]);
if (cp != -1)
{
const int mods = _glfw.wl.xkb.modifiers;
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
_glfwInputChar(window, cp, mods, plain);
}
}
if (action == GLFW_PRESS)
inputChar(window, key);
}
static void keyboardHandleModifiers(void* data,
@@ -320,15 +383,17 @@ static void keyboardHandleModifiers(void* data,
group);
mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
XKB_STATE_DEPRESSED |
XKB_STATE_LATCHED);
if (mask & _glfw.wl.xkb.control_mask)
XKB_STATE_MODS_DEPRESSED |
XKB_STATE_LAYOUT_DEPRESSED |
XKB_STATE_MODS_LATCHED |
XKB_STATE_LAYOUT_LATCHED);
if (mask & _glfw.wl.xkb.controlMask)
modifiers |= GLFW_MOD_CONTROL;
if (mask & _glfw.wl.xkb.alt_mask)
if (mask & _glfw.wl.xkb.altMask)
modifiers |= GLFW_MOD_ALT;
if (mask & _glfw.wl.xkb.shift_mask)
if (mask & _glfw.wl.xkb.shiftMask)
modifiers |= GLFW_MOD_SHIFT;
if (mask & _glfw.wl.xkb.super_mask)
if (mask & _glfw.wl.xkb.superMask)
modifiers |= GLFW_MOD_SUPER;
_glfw.wl.xkb.modifiers = modifiers;
}
@@ -380,10 +445,10 @@ static void registryHandleGlobal(void* data,
{
if (strcmp(interface, "wl_compositor") == 0)
{
_glfw.wl.wl_compositor_version = min(3, version);
_glfw.wl.compositorVersion = min(3, version);
_glfw.wl.compositor =
wl_registry_bind(registry, name, &wl_compositor_interface,
_glfw.wl.wl_compositor_version);
_glfw.wl.compositorVersion);
}
else if (strcmp(interface, "wl_shm") == 0)
{
@@ -440,124 +505,134 @@ static const struct wl_registry_listener registryListener = {
//
static void createKeyTables(void)
{
memset(_glfw.wl.publicKeys, -1, sizeof(_glfw.wl.publicKeys));
int scancode;
_glfw.wl.publicKeys[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
_glfw.wl.publicKeys[KEY_1] = GLFW_KEY_1;
_glfw.wl.publicKeys[KEY_2] = GLFW_KEY_2;
_glfw.wl.publicKeys[KEY_3] = GLFW_KEY_3;
_glfw.wl.publicKeys[KEY_4] = GLFW_KEY_4;
_glfw.wl.publicKeys[KEY_5] = GLFW_KEY_5;
_glfw.wl.publicKeys[KEY_6] = GLFW_KEY_6;
_glfw.wl.publicKeys[KEY_7] = GLFW_KEY_7;
_glfw.wl.publicKeys[KEY_8] = GLFW_KEY_8;
_glfw.wl.publicKeys[KEY_9] = GLFW_KEY_9;
_glfw.wl.publicKeys[KEY_0] = GLFW_KEY_0;
_glfw.wl.publicKeys[KEY_MINUS] = GLFW_KEY_MINUS;
_glfw.wl.publicKeys[KEY_EQUAL] = GLFW_KEY_EQUAL;
_glfw.wl.publicKeys[KEY_Q] = GLFW_KEY_Q;
_glfw.wl.publicKeys[KEY_W] = GLFW_KEY_W;
_glfw.wl.publicKeys[KEY_E] = GLFW_KEY_E;
_glfw.wl.publicKeys[KEY_R] = GLFW_KEY_R;
_glfw.wl.publicKeys[KEY_T] = GLFW_KEY_T;
_glfw.wl.publicKeys[KEY_Y] = GLFW_KEY_Y;
_glfw.wl.publicKeys[KEY_U] = GLFW_KEY_U;
_glfw.wl.publicKeys[KEY_I] = GLFW_KEY_I;
_glfw.wl.publicKeys[KEY_O] = GLFW_KEY_O;
_glfw.wl.publicKeys[KEY_P] = GLFW_KEY_P;
_glfw.wl.publicKeys[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
_glfw.wl.publicKeys[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
_glfw.wl.publicKeys[KEY_A] = GLFW_KEY_A;
_glfw.wl.publicKeys[KEY_S] = GLFW_KEY_S;
_glfw.wl.publicKeys[KEY_D] = GLFW_KEY_D;
_glfw.wl.publicKeys[KEY_F] = GLFW_KEY_F;
_glfw.wl.publicKeys[KEY_G] = GLFW_KEY_G;
_glfw.wl.publicKeys[KEY_H] = GLFW_KEY_H;
_glfw.wl.publicKeys[KEY_J] = GLFW_KEY_J;
_glfw.wl.publicKeys[KEY_K] = GLFW_KEY_K;
_glfw.wl.publicKeys[KEY_L] = GLFW_KEY_L;
_glfw.wl.publicKeys[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
_glfw.wl.publicKeys[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
_glfw.wl.publicKeys[KEY_Z] = GLFW_KEY_Z;
_glfw.wl.publicKeys[KEY_X] = GLFW_KEY_X;
_glfw.wl.publicKeys[KEY_C] = GLFW_KEY_C;
_glfw.wl.publicKeys[KEY_V] = GLFW_KEY_V;
_glfw.wl.publicKeys[KEY_B] = GLFW_KEY_B;
_glfw.wl.publicKeys[KEY_N] = GLFW_KEY_N;
_glfw.wl.publicKeys[KEY_M] = GLFW_KEY_M;
_glfw.wl.publicKeys[KEY_COMMA] = GLFW_KEY_COMMA;
_glfw.wl.publicKeys[KEY_DOT] = GLFW_KEY_PERIOD;
_glfw.wl.publicKeys[KEY_SLASH] = GLFW_KEY_SLASH;
_glfw.wl.publicKeys[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
_glfw.wl.publicKeys[KEY_ESC] = GLFW_KEY_ESCAPE;
_glfw.wl.publicKeys[KEY_TAB] = GLFW_KEY_TAB;
_glfw.wl.publicKeys[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
_glfw.wl.publicKeys[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
_glfw.wl.publicKeys[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
_glfw.wl.publicKeys[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
_glfw.wl.publicKeys[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
_glfw.wl.publicKeys[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
_glfw.wl.publicKeys[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
_glfw.wl.publicKeys[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
_glfw.wl.publicKeys[KEY_MENU] = GLFW_KEY_MENU;
_glfw.wl.publicKeys[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
_glfw.wl.publicKeys[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
_glfw.wl.publicKeys[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
_glfw.wl.publicKeys[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
_glfw.wl.publicKeys[KEY_PAUSE] = GLFW_KEY_PAUSE;
_glfw.wl.publicKeys[KEY_DELETE] = GLFW_KEY_DELETE;
_glfw.wl.publicKeys[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
_glfw.wl.publicKeys[KEY_ENTER] = GLFW_KEY_ENTER;
_glfw.wl.publicKeys[KEY_HOME] = GLFW_KEY_HOME;
_glfw.wl.publicKeys[KEY_END] = GLFW_KEY_END;
_glfw.wl.publicKeys[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
_glfw.wl.publicKeys[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
_glfw.wl.publicKeys[KEY_INSERT] = GLFW_KEY_INSERT;
_glfw.wl.publicKeys[KEY_LEFT] = GLFW_KEY_LEFT;
_glfw.wl.publicKeys[KEY_RIGHT] = GLFW_KEY_RIGHT;
_glfw.wl.publicKeys[KEY_DOWN] = GLFW_KEY_DOWN;
_glfw.wl.publicKeys[KEY_UP] = GLFW_KEY_UP;
_glfw.wl.publicKeys[KEY_F1] = GLFW_KEY_F1;
_glfw.wl.publicKeys[KEY_F2] = GLFW_KEY_F2;
_glfw.wl.publicKeys[KEY_F3] = GLFW_KEY_F3;
_glfw.wl.publicKeys[KEY_F4] = GLFW_KEY_F4;
_glfw.wl.publicKeys[KEY_F5] = GLFW_KEY_F5;
_glfw.wl.publicKeys[KEY_F6] = GLFW_KEY_F6;
_glfw.wl.publicKeys[KEY_F7] = GLFW_KEY_F7;
_glfw.wl.publicKeys[KEY_F8] = GLFW_KEY_F8;
_glfw.wl.publicKeys[KEY_F9] = GLFW_KEY_F9;
_glfw.wl.publicKeys[KEY_F10] = GLFW_KEY_F10;
_glfw.wl.publicKeys[KEY_F11] = GLFW_KEY_F11;
_glfw.wl.publicKeys[KEY_F12] = GLFW_KEY_F12;
_glfw.wl.publicKeys[KEY_F13] = GLFW_KEY_F13;
_glfw.wl.publicKeys[KEY_F14] = GLFW_KEY_F14;
_glfw.wl.publicKeys[KEY_F15] = GLFW_KEY_F15;
_glfw.wl.publicKeys[KEY_F16] = GLFW_KEY_F16;
_glfw.wl.publicKeys[KEY_F17] = GLFW_KEY_F17;
_glfw.wl.publicKeys[KEY_F18] = GLFW_KEY_F18;
_glfw.wl.publicKeys[KEY_F19] = GLFW_KEY_F19;
_glfw.wl.publicKeys[KEY_F20] = GLFW_KEY_F20;
_glfw.wl.publicKeys[KEY_F21] = GLFW_KEY_F21;
_glfw.wl.publicKeys[KEY_F22] = GLFW_KEY_F22;
_glfw.wl.publicKeys[KEY_F23] = GLFW_KEY_F23;
_glfw.wl.publicKeys[KEY_F24] = GLFW_KEY_F24;
_glfw.wl.publicKeys[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
_glfw.wl.publicKeys[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
_glfw.wl.publicKeys[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
_glfw.wl.publicKeys[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
_glfw.wl.publicKeys[KEY_KP0] = GLFW_KEY_KP_0;
_glfw.wl.publicKeys[KEY_KP1] = GLFW_KEY_KP_1;
_glfw.wl.publicKeys[KEY_KP2] = GLFW_KEY_KP_2;
_glfw.wl.publicKeys[KEY_KP3] = GLFW_KEY_KP_3;
_glfw.wl.publicKeys[KEY_KP4] = GLFW_KEY_KP_4;
_glfw.wl.publicKeys[KEY_KP5] = GLFW_KEY_KP_5;
_glfw.wl.publicKeys[KEY_KP6] = GLFW_KEY_KP_6;
_glfw.wl.publicKeys[KEY_KP7] = GLFW_KEY_KP_7;
_glfw.wl.publicKeys[KEY_KP8] = GLFW_KEY_KP_8;
_glfw.wl.publicKeys[KEY_KP9] = GLFW_KEY_KP_9;
_glfw.wl.publicKeys[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
_glfw.wl.publicKeys[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
_glfw.wl.publicKeys[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));
memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));
_glfw.wl.keycodes[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
_glfw.wl.keycodes[KEY_1] = GLFW_KEY_1;
_glfw.wl.keycodes[KEY_2] = GLFW_KEY_2;
_glfw.wl.keycodes[KEY_3] = GLFW_KEY_3;
_glfw.wl.keycodes[KEY_4] = GLFW_KEY_4;
_glfw.wl.keycodes[KEY_5] = GLFW_KEY_5;
_glfw.wl.keycodes[KEY_6] = GLFW_KEY_6;
_glfw.wl.keycodes[KEY_7] = GLFW_KEY_7;
_glfw.wl.keycodes[KEY_8] = GLFW_KEY_8;
_glfw.wl.keycodes[KEY_9] = GLFW_KEY_9;
_glfw.wl.keycodes[KEY_0] = GLFW_KEY_0;
_glfw.wl.keycodes[KEY_SPACE] = GLFW_KEY_SPACE;
_glfw.wl.keycodes[KEY_MINUS] = GLFW_KEY_MINUS;
_glfw.wl.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
_glfw.wl.keycodes[KEY_Q] = GLFW_KEY_Q;
_glfw.wl.keycodes[KEY_W] = GLFW_KEY_W;
_glfw.wl.keycodes[KEY_E] = GLFW_KEY_E;
_glfw.wl.keycodes[KEY_R] = GLFW_KEY_R;
_glfw.wl.keycodes[KEY_T] = GLFW_KEY_T;
_glfw.wl.keycodes[KEY_Y] = GLFW_KEY_Y;
_glfw.wl.keycodes[KEY_U] = GLFW_KEY_U;
_glfw.wl.keycodes[KEY_I] = GLFW_KEY_I;
_glfw.wl.keycodes[KEY_O] = GLFW_KEY_O;
_glfw.wl.keycodes[KEY_P] = GLFW_KEY_P;
_glfw.wl.keycodes[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
_glfw.wl.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
_glfw.wl.keycodes[KEY_A] = GLFW_KEY_A;
_glfw.wl.keycodes[KEY_S] = GLFW_KEY_S;
_glfw.wl.keycodes[KEY_D] = GLFW_KEY_D;
_glfw.wl.keycodes[KEY_F] = GLFW_KEY_F;
_glfw.wl.keycodes[KEY_G] = GLFW_KEY_G;
_glfw.wl.keycodes[KEY_H] = GLFW_KEY_H;
_glfw.wl.keycodes[KEY_J] = GLFW_KEY_J;
_glfw.wl.keycodes[KEY_K] = GLFW_KEY_K;
_glfw.wl.keycodes[KEY_L] = GLFW_KEY_L;
_glfw.wl.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
_glfw.wl.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
_glfw.wl.keycodes[KEY_Z] = GLFW_KEY_Z;
_glfw.wl.keycodes[KEY_X] = GLFW_KEY_X;
_glfw.wl.keycodes[KEY_C] = GLFW_KEY_C;
_glfw.wl.keycodes[KEY_V] = GLFW_KEY_V;
_glfw.wl.keycodes[KEY_B] = GLFW_KEY_B;
_glfw.wl.keycodes[KEY_N] = GLFW_KEY_N;
_glfw.wl.keycodes[KEY_M] = GLFW_KEY_M;
_glfw.wl.keycodes[KEY_COMMA] = GLFW_KEY_COMMA;
_glfw.wl.keycodes[KEY_DOT] = GLFW_KEY_PERIOD;
_glfw.wl.keycodes[KEY_SLASH] = GLFW_KEY_SLASH;
_glfw.wl.keycodes[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
_glfw.wl.keycodes[KEY_ESC] = GLFW_KEY_ESCAPE;
_glfw.wl.keycodes[KEY_TAB] = GLFW_KEY_TAB;
_glfw.wl.keycodes[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
_glfw.wl.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
_glfw.wl.keycodes[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
_glfw.wl.keycodes[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
_glfw.wl.keycodes[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
_glfw.wl.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
_glfw.wl.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
_glfw.wl.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
_glfw.wl.keycodes[KEY_MENU] = GLFW_KEY_MENU;
_glfw.wl.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
_glfw.wl.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
_glfw.wl.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
_glfw.wl.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
_glfw.wl.keycodes[KEY_PAUSE] = GLFW_KEY_PAUSE;
_glfw.wl.keycodes[KEY_DELETE] = GLFW_KEY_DELETE;
_glfw.wl.keycodes[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
_glfw.wl.keycodes[KEY_ENTER] = GLFW_KEY_ENTER;
_glfw.wl.keycodes[KEY_HOME] = GLFW_KEY_HOME;
_glfw.wl.keycodes[KEY_END] = GLFW_KEY_END;
_glfw.wl.keycodes[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
_glfw.wl.keycodes[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
_glfw.wl.keycodes[KEY_INSERT] = GLFW_KEY_INSERT;
_glfw.wl.keycodes[KEY_LEFT] = GLFW_KEY_LEFT;
_glfw.wl.keycodes[KEY_RIGHT] = GLFW_KEY_RIGHT;
_glfw.wl.keycodes[KEY_DOWN] = GLFW_KEY_DOWN;
_glfw.wl.keycodes[KEY_UP] = GLFW_KEY_UP;
_glfw.wl.keycodes[KEY_F1] = GLFW_KEY_F1;
_glfw.wl.keycodes[KEY_F2] = GLFW_KEY_F2;
_glfw.wl.keycodes[KEY_F3] = GLFW_KEY_F3;
_glfw.wl.keycodes[KEY_F4] = GLFW_KEY_F4;
_glfw.wl.keycodes[KEY_F5] = GLFW_KEY_F5;
_glfw.wl.keycodes[KEY_F6] = GLFW_KEY_F6;
_glfw.wl.keycodes[KEY_F7] = GLFW_KEY_F7;
_glfw.wl.keycodes[KEY_F8] = GLFW_KEY_F8;
_glfw.wl.keycodes[KEY_F9] = GLFW_KEY_F9;
_glfw.wl.keycodes[KEY_F10] = GLFW_KEY_F10;
_glfw.wl.keycodes[KEY_F11] = GLFW_KEY_F11;
_glfw.wl.keycodes[KEY_F12] = GLFW_KEY_F12;
_glfw.wl.keycodes[KEY_F13] = GLFW_KEY_F13;
_glfw.wl.keycodes[KEY_F14] = GLFW_KEY_F14;
_glfw.wl.keycodes[KEY_F15] = GLFW_KEY_F15;
_glfw.wl.keycodes[KEY_F16] = GLFW_KEY_F16;
_glfw.wl.keycodes[KEY_F17] = GLFW_KEY_F17;
_glfw.wl.keycodes[KEY_F18] = GLFW_KEY_F18;
_glfw.wl.keycodes[KEY_F19] = GLFW_KEY_F19;
_glfw.wl.keycodes[KEY_F20] = GLFW_KEY_F20;
_glfw.wl.keycodes[KEY_F21] = GLFW_KEY_F21;
_glfw.wl.keycodes[KEY_F22] = GLFW_KEY_F22;
_glfw.wl.keycodes[KEY_F23] = GLFW_KEY_F23;
_glfw.wl.keycodes[KEY_F24] = GLFW_KEY_F24;
_glfw.wl.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
_glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
_glfw.wl.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
_glfw.wl.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
_glfw.wl.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
_glfw.wl.keycodes[KEY_KP1] = GLFW_KEY_KP_1;
_glfw.wl.keycodes[KEY_KP2] = GLFW_KEY_KP_2;
_glfw.wl.keycodes[KEY_KP3] = GLFW_KEY_KP_3;
_glfw.wl.keycodes[KEY_KP4] = GLFW_KEY_KP_4;
_glfw.wl.keycodes[KEY_KP5] = GLFW_KEY_KP_5;
_glfw.wl.keycodes[KEY_KP6] = GLFW_KEY_KP_6;
_glfw.wl.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
_glfw.wl.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
_glfw.wl.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
_glfw.wl.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
_glfw.wl.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
_glfw.wl.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
for (scancode = 0; scancode < 256; scancode++)
{
if (_glfw.wl.keycodes[scancode] > 0)
_glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode;
}
}
@@ -578,9 +653,6 @@ int _glfwPlatformInit(void)
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
_glfw.wl.monitors = calloc(4, sizeof(_GLFWmonitor*));
_glfw.wl.monitorsSize = 4;
createKeyTables();
_glfw.wl.xkb.context = xkb_context_new(0);
@@ -597,12 +669,6 @@ int _glfwPlatformInit(void)
// Sync so we got all initial output events
wl_display_roundtrip(_glfw.wl.display);
if (!_glfwInitThreadLocalStoragePOSIX())
return GLFW_FALSE;
if (!_glfwInitEGL())
return GLFW_FALSE;
if (!_glfwInitJoysticksLinux())
return GLFW_FALSE;
@@ -628,18 +694,39 @@ void _glfwPlatformTerminate(void)
{
_glfwTerminateEGL();
_glfwTerminateJoysticksLinux();
_glfwTerminateThreadLocalStoragePOSIX();
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
xkb_keymap_unref(_glfw.wl.xkb.keymap);
xkb_state_unref(_glfw.wl.xkb.state);
xkb_context_unref(_glfw.wl.xkb.context);
if (_glfw.wl.cursorTheme)
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
if (_glfw.wl.cursorSurface)
wl_surface_destroy(_glfw.wl.cursorSurface);
if (_glfw.wl.compositor)
wl_compositor_destroy(_glfw.wl.compositor);
if (_glfw.wl.shm)
wl_shm_destroy(_glfw.wl.shm);
if (_glfw.wl.shell)
wl_shell_destroy(_glfw.wl.shell);
if (_glfw.wl.pointer)
wl_pointer_destroy(_glfw.wl.pointer);
if (_glfw.wl.keyboard)
wl_keyboard_destroy(_glfw.wl.keyboard);
if (_glfw.wl.seat)
wl_seat_destroy(_glfw.wl.seat);
if (_glfw.wl.relativePointerManager)
zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
if (_glfw.wl.pointerConstraints)
zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);
if (_glfw.wl.registry)
wl_registry_destroy(_glfw.wl.registry);
if (_glfw.wl.display)
{
wl_display_flush(_glfw.wl.display);
if (_glfw.wl.display)
wl_display_disconnect(_glfw.wl.display);
}
}
const char* _glfwPlatformGetVersionString(void)
@@ -650,9 +737,7 @@ const char* _glfwPlatformGetVersionString(void)
#else
" gettimeofday"
#endif
#if defined(__linux__)
" /dev/js"
#endif
#if defined(_GLFW_BUILD_DLL)
" shared"
#endif

Some files were not shown because too many files have changed in this diff Show More