diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 53c3a6c3c..672264dc6 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,35 +1,118 @@ # 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 an input or event bug](#reporting-an-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, Correct (Compilable), +Example](http://www.sscce.org/) 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. + +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 +121,42 @@ __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. + +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), 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 +165,44 @@ __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. + +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 an 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 +210,137 @@ 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. + +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. + + +#### 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. ## 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. + +__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`. + +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. diff --git a/.gitignore b/.gitignore index 7a365a5da..b6c256cb9 100644 --- a/.gitignore +++ b/.gitignore @@ -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 @@ -67,6 +67,7 @@ tests/empty tests/events tests/gamma tests/glfwinfo +tests/icon tests/iconify tests/joysticks tests/monitors @@ -75,6 +76,7 @@ tests/reopen tests/sharing tests/tearing tests/threads +tests/timeout tests/title tests/version tests/vulkan diff --git a/CMake/modules/FindVulkan.cmake b/CMake/modules/FindVulkan.cmake index 75cc25c79..d3a664a8b 100644 --- a/CMake/modules/FindVulkan.cmake +++ b/CMake/modules/FindVulkan.cmake @@ -12,6 +12,9 @@ if (WIN32) find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS "$ENV{VULKAN_SDK}/Bin" "$ENV{VK_SDK_PATH}/Bin") + find_library(VULKAN_STATIC_LIBRARY NAMES vkstatic.1 HINTS + "$ENV{VULKAN_SDK}/Bin" + "$ENV{VK_SDK_PATH}/Bin") else() find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS "$ENV{VULKAN_SDK}/Bin32" @@ -27,5 +30,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) diff --git a/CMakeLists.txt b/CMakeLists.txt index 02040dd06..0a67af3a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ if (NOT CMAKE_VERSION VERSION_LESS "3.0") 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,6 +25,7 @@ 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 (WIN32) @@ -57,7 +58,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) @@ -90,6 +95,15 @@ if (MSVC) endif() if (MINGW) + # Workaround for legacy MinGW not providing XInput and DirectInput + include(CheckIncludeFile) + + check_include_file(dinput.h DINPUT_H_FOUND) + check_include_file(xinput.h XINPUT_H_FOUND) + if (NOT DINPUT_H_FOUND OR NOT XINPUT_H_FOUND) + list(APPEND glfw_INCLUDE_DIRS "${GLFW_SOURCE_DIR}/deps/mingw") + endif() + # Enable link-time exploit mitigation features enabled by default on MSVC include(CheckCCompilerFlag) @@ -139,6 +153,21 @@ 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}) + 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 #-------------------------------------------------------------------- @@ -244,7 +273,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) @@ -299,20 +328,17 @@ if (_GLFW_COCOA) find_library(IOKIT_FRAMEWORK IOKit) find_library(CORE_FOUNDATION_FRAMEWORK CoreFoundation) find_library(CORE_VIDEO_FRAMEWORK CoreVideo) - find_library(CARBON_FRAMEWORK Carbon) mark_as_advanced(COCOA_FRAMEWORK IOKIT_FRAMEWORK CORE_FOUNDATION_FRAMEWORK - CORE_VIDEO_FRAMEWORK - CARBON_FRAMEWORK) + CORE_VIDEO_FRAMEWORK) list(APPEND glfw_LIBRARIES "${COCOA_FRAMEWORK}" "${IOKIT_FRAMEWORK}" "${CORE_FOUNDATION_FRAMEWORK}" - "${CORE_VIDEO_FRAMEWORK}" - "${CARBON_FRAMEWORK}") + "${CORE_VIDEO_FRAMEWORK}") set(glfw_PKG_DEPS "") - set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework CoreVideo -framework Carbon") + set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework CoreVideo") endif() #-------------------------------------------------------------------- diff --git a/COPYING.txt b/COPYING.txt index b30c70158..ad16462a9 100644 --- a/COPYING.txt +++ b/COPYING.txt @@ -1,5 +1,5 @@ Copyright (c) 2002-2006 Marcus Geelnard -Copyright (c) 2006-2010 Camilla Berglund +Copyright (c) 2006-2016 Camilla Berglund This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/README.md b/README.md index aa72d5e70..bb59180bd 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,25 @@ [![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 is _not yet described_. +GLFW is licensed under the [zlib/libpng +license](https://opensource.org/licenses/Zlib). + +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. + +This is a development branch for version 3.3, which is _not yet described_. If you are new to GLFW, you may find the [tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW @@ -20,37 +31,43 @@ 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 OS X 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 also [pre-compiled Windows +binaries](http://www.glfw.org/download.html) available for all compilers +supported on that platform. + +See the [compilation guide](http://www.glfw.org/docs/latest/compile.html) in the +documentation for more information. ## Using GLFW -See the -[Building programs that use GLFW](http://www.glfw.org/docs/latest/build.html) -guide in the GLFW documentation. +See the [building application guide](http://www.glfw.org/docs/latest/build.html) +guide in the documentation for more information. -## Reporting bugs +## System requirements -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. +GLFW supports Windows XP and later, OS X 10.7 Lion and later, and Linux and +other Unix-like systems with the X Window System. Experimental implementations +for the Wayland protocol and the Mir display server are available but not yet +officially supported. -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. - -This will help both us and other people experiencing the same bug. +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 examples and test programs depend on a number of tiny libraries. These are located in the `deps/` directory. @@ -69,94 +86,37 @@ The Vulkan example additionally requires the Vulkan SDK to be installed, or it will not be included in the build. The documentation is generated with [Doxygen](http://doxygen.org/). If CMake -does not find Doxygen, the documentation will not be generated. +does not find Doxygen, the documentation will not be generated when you build. + + +## 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_CONTEXT_NO_ERROR` context hint for `GL_KHR_no_error` support - - Added `GLFW_INCLUDE_VULKAN` for including the Vulkan header - - Added `GLFW_CONTEXT_CREATION_API`, `GLFW_NATIVE_CONTEXT_API` and - `GLFW_EGL_CONTEXT_API` for run-time context creation API selection - - Added `GLFW_TRUE` and `GLFW_FALSE` as client API independent boolean values - - Added 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 +- Bugfix: Calling `glfwMaximizeWindow` on a full screen window was not ignored ## 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 @@ -199,8 +159,10 @@ skills. - heromyth - Lucas Hinderberger - Paul Holden + - Warren Hu - IntellectualKitty - Aaron Jacobs + - Erik S. V. Jansson - Toni Jovanoski - Arseny Kapoulkine - Osman Keskin @@ -240,6 +202,7 @@ skills. - Emmanuel Gil Peyrot - Cyril Pichard - Pieroman + - Philip Rideout - Jorge Rodriguez - Ed Ropple - Aleksey Rybalkin @@ -254,6 +217,7 @@ skills. - Dmitri Shuralyov - Daniel Skorupski - Bradley Smith + - Patrick Snape - Julian Squires - Johannes Stein - Justin Stoecker @@ -261,10 +225,11 @@ skills. - Nathan Sweet - TTK-Bandit - Sergey Tikhomirov - - A. Tombs + - Arthur Tombs - Ioannis Tsakpinis - Samuli Tuomola - urraka + - Elias Vanderstuyft - Jari Vetoniemi - Ricardo Vieira - Nicholas Vitovitch diff --git a/deps/linmath.h b/deps/linmath.h index 985e9f92e..5732a76af 100644 --- a/deps/linmath.h +++ b/deps/linmath.h @@ -3,7 +3,7 @@ #include -#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; + 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); diff --git a/deps/mingw/_mingw_dxhelper.h b/deps/mingw/_mingw_dxhelper.h new file mode 100644 index 000000000..849e29146 --- /dev/null +++ b/deps/mingw/_mingw_dxhelper.h @@ -0,0 +1,117 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ + +#if defined(_MSC_VER) && !defined(_MSC_EXTENSIONS) +#define NONAMELESSUNION 1 +#endif +#if defined(NONAMELESSSTRUCT) && \ + !defined(NONAMELESSUNION) +#define NONAMELESSUNION 1 +#endif +#if defined(NONAMELESSUNION) && \ + !defined(NONAMELESSSTRUCT) +#define NONAMELESSSTRUCT 1 +#endif +#if !defined(__GNU_EXTENSION) +#if defined(__GNUC__) || defined(__GNUG__) +#define __GNU_EXTENSION __extension__ +#else +#define __GNU_EXTENSION +#endif +#endif /* __extension__ */ + +#ifndef __ANONYMOUS_DEFINED +#define __ANONYMOUS_DEFINED +#if defined(__GNUC__) || defined(__GNUG__) +#define _ANONYMOUS_UNION __extension__ +#define _ANONYMOUS_STRUCT __extension__ +#else +#define _ANONYMOUS_UNION +#define _ANONYMOUS_STRUCT +#endif +#ifndef NONAMELESSUNION +#define _UNION_NAME(x) +#define _STRUCT_NAME(x) +#else /* NONAMELESSUNION */ +#define _UNION_NAME(x) x +#define _STRUCT_NAME(x) x +#endif +#endif /* __ANONYMOUS_DEFINED */ + +#ifndef DUMMYUNIONNAME +# ifdef NONAMELESSUNION +# define DUMMYUNIONNAME u +# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */ +# define DUMMYUNIONNAME2 u2 +# define DUMMYUNIONNAME3 u3 +# define DUMMYUNIONNAME4 u4 +# define DUMMYUNIONNAME5 u5 +# define DUMMYUNIONNAME6 u6 +# define DUMMYUNIONNAME7 u7 +# define DUMMYUNIONNAME8 u8 +# define DUMMYUNIONNAME9 u9 +# else /* NONAMELESSUNION */ +# define DUMMYUNIONNAME +# define DUMMYUNIONNAME1 /* Wine uses this variant */ +# define DUMMYUNIONNAME2 +# define DUMMYUNIONNAME3 +# define DUMMYUNIONNAME4 +# define DUMMYUNIONNAME5 +# define DUMMYUNIONNAME6 +# define DUMMYUNIONNAME7 +# define DUMMYUNIONNAME8 +# define DUMMYUNIONNAME9 +# endif +#endif /* DUMMYUNIONNAME */ + +#if !defined(DUMMYUNIONNAME1) /* MinGW does not define this one */ +# ifdef NONAMELESSUNION +# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */ +# else +# define DUMMYUNIONNAME1 /* Wine uses this variant */ +# endif +#endif /* DUMMYUNIONNAME1 */ + +#ifndef DUMMYSTRUCTNAME +# ifdef NONAMELESSUNION +# define DUMMYSTRUCTNAME s +# define DUMMYSTRUCTNAME1 s1 /* Wine uses this variant */ +# define DUMMYSTRUCTNAME2 s2 +# define DUMMYSTRUCTNAME3 s3 +# define DUMMYSTRUCTNAME4 s4 +# define DUMMYSTRUCTNAME5 s5 +# else +# define DUMMYSTRUCTNAME +# define DUMMYSTRUCTNAME1 /* Wine uses this variant */ +# define DUMMYSTRUCTNAME2 +# define DUMMYSTRUCTNAME3 +# define DUMMYSTRUCTNAME4 +# define DUMMYSTRUCTNAME5 +# endif +#endif /* DUMMYSTRUCTNAME */ + +/* These are for compatibility with the Wine source tree */ + +#ifndef WINELIB_NAME_AW +# ifdef __MINGW_NAME_AW +# define WINELIB_NAME_AW __MINGW_NAME_AW +# else +# ifdef UNICODE +# define WINELIB_NAME_AW(func) func##W +# else +# define WINELIB_NAME_AW(func) func##A +# endif +# endif +#endif /* WINELIB_NAME_AW */ + +#ifndef DECL_WINELIB_TYPE_AW +# ifdef __MINGW_TYPEDEF_AW +# define DECL_WINELIB_TYPE_AW __MINGW_TYPEDEF_AW +# else +# define DECL_WINELIB_TYPE_AW(type) typedef WINELIB_NAME_AW(type) type; +# endif +#endif /* DECL_WINELIB_TYPE_AW */ + diff --git a/deps/mingw/dinput.h b/deps/mingw/dinput.h new file mode 100644 index 000000000..b5754802b --- /dev/null +++ b/deps/mingw/dinput.h @@ -0,0 +1,2467 @@ +/* + * Copyright (C) the Wine project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __DINPUT_INCLUDED__ +#define __DINPUT_INCLUDED__ + +#define COM_NO_WINDOWS_H +#include +#include <_mingw_dxhelper.h> + +#ifndef DIRECTINPUT_VERSION +#define DIRECTINPUT_VERSION 0x0800 +#endif + +/* Classes */ +DEFINE_GUID(CLSID_DirectInput, 0x25E609E0,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(CLSID_DirectInputDevice, 0x25E609E1,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +DEFINE_GUID(CLSID_DirectInput8, 0x25E609E4,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(CLSID_DirectInputDevice8, 0x25E609E5,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/* Interfaces */ +DEFINE_GUID(IID_IDirectInputA, 0x89521360,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputW, 0x89521361,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInput2A, 0x5944E662,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInput2W, 0x5944E663,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInput7A, 0x9A4CB684,0x236D,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInput7W, 0x9A4CB685,0x236D,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInput8A, 0xBF798030,0x483A,0x4DA2,0xAA,0x99,0x5D,0x64,0xED,0x36,0x97,0x00); +DEFINE_GUID(IID_IDirectInput8W, 0xBF798031,0x483A,0x4DA2,0xAA,0x99,0x5D,0x64,0xED,0x36,0x97,0x00); +DEFINE_GUID(IID_IDirectInputDeviceA, 0x5944E680,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDeviceW, 0x5944E681,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDevice2A, 0x5944E682,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDevice2W, 0x5944E683,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDevice7A, 0x57D7C6BC,0x2356,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInputDevice7W, 0x57D7C6BD,0x2356,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInputDevice8A, 0x54D41080,0xDC15,0x4833,0xA4,0x1B,0x74,0x8F,0x73,0xA3,0x81,0x79); +DEFINE_GUID(IID_IDirectInputDevice8W, 0x54D41081,0xDC15,0x4833,0xA4,0x1B,0x74,0x8F,0x73,0xA3,0x81,0x79); +DEFINE_GUID(IID_IDirectInputEffect, 0xE7E1F7C0,0x88D2,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); + +/* Predefined object types */ +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_Key, 0x55728220,0xD33C,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_POV, 0xA36D02F2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Unknown,0xA36D02F3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/* Predefined product GUIDs */ +DEFINE_GUID(GUID_SysMouse, 0x6F1D2B60,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysKeyboard, 0x6F1D2B61,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Joystick, 0x6F1D2B70,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysMouseEm, 0x6F1D2B80,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysMouseEm2, 0x6F1D2B81,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysKeyboardEm, 0x6F1D2B82,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysKeyboardEm2,0x6F1D2B83,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/* predefined forcefeedback effects */ +DEFINE_GUID(GUID_ConstantForce, 0x13541C20,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_RampForce, 0x13541C21,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Square, 0x13541C22,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Sine, 0x13541C23,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Triangle, 0x13541C24,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_SawtoothUp, 0x13541C25,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_SawtoothDown, 0x13541C26,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Spring, 0x13541C27,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Damper, 0x13541C28,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Inertia, 0x13541C29,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Friction, 0x13541C2A,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_CustomForce, 0x13541C2B,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); + +typedef struct IDirectInputA *LPDIRECTINPUTA; +typedef struct IDirectInputW *LPDIRECTINPUTW; +typedef struct IDirectInput2A *LPDIRECTINPUT2A; +typedef struct IDirectInput2W *LPDIRECTINPUT2W; +typedef struct IDirectInput7A *LPDIRECTINPUT7A; +typedef struct IDirectInput7W *LPDIRECTINPUT7W; +#if DIRECTINPUT_VERSION >= 0x0800 +typedef struct IDirectInput8A *LPDIRECTINPUT8A; +typedef struct IDirectInput8W *LPDIRECTINPUT8W; +#endif /* DI8 */ +typedef struct IDirectInputDeviceA *LPDIRECTINPUTDEVICEA; +typedef struct IDirectInputDeviceW *LPDIRECTINPUTDEVICEW; +#if DIRECTINPUT_VERSION >= 0x0500 +typedef struct IDirectInputDevice2A *LPDIRECTINPUTDEVICE2A; +typedef struct IDirectInputDevice2W *LPDIRECTINPUTDEVICE2W; +#endif /* DI5 */ +#if DIRECTINPUT_VERSION >= 0x0700 +typedef struct IDirectInputDevice7A *LPDIRECTINPUTDEVICE7A; +typedef struct IDirectInputDevice7W *LPDIRECTINPUTDEVICE7W; +#endif /* DI7 */ +#if DIRECTINPUT_VERSION >= 0x0800 +typedef struct IDirectInputDevice8A *LPDIRECTINPUTDEVICE8A; +typedef struct IDirectInputDevice8W *LPDIRECTINPUTDEVICE8W; +#endif /* DI8 */ +#if DIRECTINPUT_VERSION >= 0x0500 +typedef struct IDirectInputEffect *LPDIRECTINPUTEFFECT; +#endif /* DI5 */ +typedef struct SysKeyboardA *LPSYSKEYBOARDA; +typedef struct SysMouseA *LPSYSMOUSEA; + +#define IID_IDirectInput WINELIB_NAME_AW(IID_IDirectInput) +#define IDirectInput WINELIB_NAME_AW(IDirectInput) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUT) +#define IID_IDirectInput2 WINELIB_NAME_AW(IID_IDirectInput2) +#define IDirectInput2 WINELIB_NAME_AW(IDirectInput2) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUT2) +#define IID_IDirectInput7 WINELIB_NAME_AW(IID_IDirectInput7) +#define IDirectInput7 WINELIB_NAME_AW(IDirectInput7) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUT7) +#if DIRECTINPUT_VERSION >= 0x0800 +#define IID_IDirectInput8 WINELIB_NAME_AW(IID_IDirectInput8) +#define IDirectInput8 WINELIB_NAME_AW(IDirectInput8) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUT8) +#endif /* DI8 */ +#define IID_IDirectInputDevice WINELIB_NAME_AW(IID_IDirectInputDevice) +#define IDirectInputDevice WINELIB_NAME_AW(IDirectInputDevice) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUTDEVICE) +#if DIRECTINPUT_VERSION >= 0x0500 +#define IID_IDirectInputDevice2 WINELIB_NAME_AW(IID_IDirectInputDevice2) +#define IDirectInputDevice2 WINELIB_NAME_AW(IDirectInputDevice2) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUTDEVICE2) +#endif /* DI5 */ +#if DIRECTINPUT_VERSION >= 0x0700 +#define IID_IDirectInputDevice7 WINELIB_NAME_AW(IID_IDirectInputDevice7) +#define IDirectInputDevice7 WINELIB_NAME_AW(IDirectInputDevice7) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUTDEVICE7) +#endif /* DI7 */ +#if DIRECTINPUT_VERSION >= 0x0800 +#define IID_IDirectInputDevice8 WINELIB_NAME_AW(IID_IDirectInputDevice8) +#define IDirectInputDevice8 WINELIB_NAME_AW(IDirectInputDevice8) +DECL_WINELIB_TYPE_AW(LPDIRECTINPUTDEVICE8) +#endif /* DI8 */ + +#define DI_OK S_OK +#define DI_NOTATTACHED S_FALSE +#define DI_BUFFEROVERFLOW S_FALSE +#define DI_PROPNOEFFECT S_FALSE +#define DI_NOEFFECT S_FALSE +#define DI_POLLEDDEVICE ((HRESULT)0x00000002L) +#define DI_DOWNLOADSKIPPED ((HRESULT)0x00000003L) +#define DI_EFFECTRESTARTED ((HRESULT)0x00000004L) +#define DI_TRUNCATED ((HRESULT)0x00000008L) +#define DI_SETTINGSNOTSAVED ((HRESULT)0x0000000BL) +#define DI_TRUNCATEDANDRESTARTED ((HRESULT)0x0000000CL) +#define DI_WRITEPROTECT ((HRESULT)0x00000013L) + +#define DIERR_OLDDIRECTINPUTVERSION \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_OLD_WIN_VERSION) +#define DIERR_BETADIRECTINPUTVERSION \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_RMODE_APP) +#define DIERR_BADDRIVERVER \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BAD_DRIVER_LEVEL) +#define DIERR_DEVICENOTREG REGDB_E_CLASSNOTREG +#define DIERR_NOTFOUND \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND) +#define DIERR_OBJECTNOTFOUND \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND) +#define DIERR_INVALIDPARAM E_INVALIDARG +#define DIERR_NOINTERFACE E_NOINTERFACE +#define DIERR_GENERIC E_FAIL +#define DIERR_OUTOFMEMORY E_OUTOFMEMORY +#define DIERR_UNSUPPORTED E_NOTIMPL +#define DIERR_NOTINITIALIZED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_READY) +#define DIERR_ALREADYINITIALIZED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_ALREADY_INITIALIZED) +#define DIERR_NOAGGREGATION CLASS_E_NOAGGREGATION +#define DIERR_OTHERAPPHASPRIO E_ACCESSDENIED +#define DIERR_INPUTLOST \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_READ_FAULT) +#define DIERR_ACQUIRED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BUSY) +#define DIERR_NOTACQUIRED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_INVALID_ACCESS) +#define DIERR_READONLY E_ACCESSDENIED +#define DIERR_HANDLEEXISTS E_ACCESSDENIED +#ifndef E_PENDING +#define E_PENDING 0x8000000AL +#endif +#define DIERR_INSUFFICIENTPRIVS 0x80040200L +#define DIERR_DEVICEFULL 0x80040201L +#define DIERR_MOREDATA 0x80040202L +#define DIERR_NOTDOWNLOADED 0x80040203L +#define DIERR_HASEFFECTS 0x80040204L +#define DIERR_NOTEXCLUSIVEACQUIRED 0x80040205L +#define DIERR_INCOMPLETEEFFECT 0x80040206L +#define DIERR_NOTBUFFERED 0x80040207L +#define DIERR_EFFECTPLAYING 0x80040208L +#define DIERR_UNPLUGGED 0x80040209L +#define DIERR_REPORTFULL 0x8004020AL +#define DIERR_MAPFILEFAIL 0x8004020BL + +#define DIENUM_STOP 0 +#define DIENUM_CONTINUE 1 + +#define DIEDFL_ALLDEVICES 0x00000000 +#define DIEDFL_ATTACHEDONLY 0x00000001 +#define DIEDFL_FORCEFEEDBACK 0x00000100 +#define DIEDFL_INCLUDEALIASES 0x00010000 +#define DIEDFL_INCLUDEPHANTOMS 0x00020000 +#define DIEDFL_INCLUDEHIDDEN 0x00040000 + +#define DIDEVTYPE_DEVICE 1 +#define DIDEVTYPE_MOUSE 2 +#define DIDEVTYPE_KEYBOARD 3 +#define DIDEVTYPE_JOYSTICK 4 +#define DIDEVTYPE_HID 0x00010000 + +#define DI8DEVCLASS_ALL 0 +#define DI8DEVCLASS_DEVICE 1 +#define DI8DEVCLASS_POINTER 2 +#define DI8DEVCLASS_KEYBOARD 3 +#define DI8DEVCLASS_GAMECTRL 4 + +#define DI8DEVTYPE_DEVICE 0x11 +#define DI8DEVTYPE_MOUSE 0x12 +#define DI8DEVTYPE_KEYBOARD 0x13 +#define DI8DEVTYPE_JOYSTICK 0x14 +#define DI8DEVTYPE_GAMEPAD 0x15 +#define DI8DEVTYPE_DRIVING 0x16 +#define DI8DEVTYPE_FLIGHT 0x17 +#define DI8DEVTYPE_1STPERSON 0x18 +#define DI8DEVTYPE_DEVICECTRL 0x19 +#define DI8DEVTYPE_SCREENPOINTER 0x1A +#define DI8DEVTYPE_REMOTE 0x1B +#define DI8DEVTYPE_SUPPLEMENTAL 0x1C + +#define DIDEVTYPEMOUSE_UNKNOWN 1 +#define DIDEVTYPEMOUSE_TRADITIONAL 2 +#define DIDEVTYPEMOUSE_FINGERSTICK 3 +#define DIDEVTYPEMOUSE_TOUCHPAD 4 +#define DIDEVTYPEMOUSE_TRACKBALL 5 + +#define DIDEVTYPEKEYBOARD_UNKNOWN 0 +#define DIDEVTYPEKEYBOARD_PCXT 1 +#define DIDEVTYPEKEYBOARD_OLIVETTI 2 +#define DIDEVTYPEKEYBOARD_PCAT 3 +#define DIDEVTYPEKEYBOARD_PCENH 4 +#define DIDEVTYPEKEYBOARD_NOKIA1050 5 +#define DIDEVTYPEKEYBOARD_NOKIA9140 6 +#define DIDEVTYPEKEYBOARD_NEC98 7 +#define DIDEVTYPEKEYBOARD_NEC98LAPTOP 8 +#define DIDEVTYPEKEYBOARD_NEC98106 9 +#define DIDEVTYPEKEYBOARD_JAPAN106 10 +#define DIDEVTYPEKEYBOARD_JAPANAX 11 +#define DIDEVTYPEKEYBOARD_J3100 12 + +#define DIDEVTYPEJOYSTICK_UNKNOWN 1 +#define DIDEVTYPEJOYSTICK_TRADITIONAL 2 +#define DIDEVTYPEJOYSTICK_FLIGHTSTICK 3 +#define DIDEVTYPEJOYSTICK_GAMEPAD 4 +#define DIDEVTYPEJOYSTICK_RUDDER 5 +#define DIDEVTYPEJOYSTICK_WHEEL 6 +#define DIDEVTYPEJOYSTICK_HEADTRACKER 7 + +#define DI8DEVTYPEMOUSE_UNKNOWN 1 +#define DI8DEVTYPEMOUSE_TRADITIONAL 2 +#define DI8DEVTYPEMOUSE_FINGERSTICK 3 +#define DI8DEVTYPEMOUSE_TOUCHPAD 4 +#define DI8DEVTYPEMOUSE_TRACKBALL 5 +#define DI8DEVTYPEMOUSE_ABSOLUTE 6 + +#define DI8DEVTYPEKEYBOARD_UNKNOWN 0 +#define DI8DEVTYPEKEYBOARD_PCXT 1 +#define DI8DEVTYPEKEYBOARD_OLIVETTI 2 +#define DI8DEVTYPEKEYBOARD_PCAT 3 +#define DI8DEVTYPEKEYBOARD_PCENH 4 +#define DI8DEVTYPEKEYBOARD_NOKIA1050 5 +#define DI8DEVTYPEKEYBOARD_NOKIA9140 6 +#define DI8DEVTYPEKEYBOARD_NEC98 7 +#define DI8DEVTYPEKEYBOARD_NEC98LAPTOP 8 +#define DI8DEVTYPEKEYBOARD_NEC98106 9 +#define DI8DEVTYPEKEYBOARD_JAPAN106 10 +#define DI8DEVTYPEKEYBOARD_JAPANAX 11 +#define DI8DEVTYPEKEYBOARD_J3100 12 + +#define DI8DEVTYPE_LIMITEDGAMESUBTYPE 1 + +#define DI8DEVTYPEJOYSTICK_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEJOYSTICK_STANDARD 2 + +#define DI8DEVTYPEGAMEPAD_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEGAMEPAD_STANDARD 2 +#define DI8DEVTYPEGAMEPAD_TILT 3 + +#define DI8DEVTYPEDRIVING_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEDRIVING_COMBINEDPEDALS 2 +#define DI8DEVTYPEDRIVING_DUALPEDALS 3 +#define DI8DEVTYPEDRIVING_THREEPEDALS 4 +#define DI8DEVTYPEDRIVING_HANDHELD 5 + +#define DI8DEVTYPEFLIGHT_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEFLIGHT_STICK 2 +#define DI8DEVTYPEFLIGHT_YOKE 3 +#define DI8DEVTYPEFLIGHT_RC 4 + +#define DI8DEVTYPE1STPERSON_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPE1STPERSON_UNKNOWN 2 +#define DI8DEVTYPE1STPERSON_SIXDOF 3 +#define DI8DEVTYPE1STPERSON_SHOOTER 4 + +#define DI8DEVTYPESCREENPTR_UNKNOWN 2 +#define DI8DEVTYPESCREENPTR_LIGHTGUN 3 +#define DI8DEVTYPESCREENPTR_LIGHTPEN 4 +#define DI8DEVTYPESCREENPTR_TOUCH 5 + +#define DI8DEVTYPEREMOTE_UNKNOWN 2 + +#define DI8DEVTYPEDEVICECTRL_UNKNOWN 2 +#define DI8DEVTYPEDEVICECTRL_COMMSSELECTION 3 +#define DI8DEVTYPEDEVICECTRL_COMMSSELECTION_HARDWIRED 4 + +#define DI8DEVTYPESUPPLEMENTAL_UNKNOWN 2 +#define DI8DEVTYPESUPPLEMENTAL_2NDHANDCONTROLLER 3 +#define DI8DEVTYPESUPPLEMENTAL_HEADTRACKER 4 +#define DI8DEVTYPESUPPLEMENTAL_HANDTRACKER 5 +#define DI8DEVTYPESUPPLEMENTAL_SHIFTSTICKGATE 6 +#define DI8DEVTYPESUPPLEMENTAL_SHIFTER 7 +#define DI8DEVTYPESUPPLEMENTAL_THROTTLE 8 +#define DI8DEVTYPESUPPLEMENTAL_SPLITTHROTTLE 9 +#define DI8DEVTYPESUPPLEMENTAL_COMBINEDPEDALS 10 +#define DI8DEVTYPESUPPLEMENTAL_DUALPEDALS 11 +#define DI8DEVTYPESUPPLEMENTAL_THREEPEDALS 12 +#define DI8DEVTYPESUPPLEMENTAL_RUDDERPEDALS 13 + +#define GET_DIDEVICE_TYPE(dwDevType) LOBYTE(dwDevType) +#define GET_DIDEVICE_SUBTYPE(dwDevType) HIBYTE(dwDevType) + +typedef struct DIDEVICEOBJECTINSTANCE_DX3A { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + CHAR tszName[MAX_PATH]; +} DIDEVICEOBJECTINSTANCE_DX3A, *LPDIDEVICEOBJECTINSTANCE_DX3A; +typedef const DIDEVICEOBJECTINSTANCE_DX3A *LPCDIDEVICEOBJECTINSTANCE_DX3A; +typedef struct DIDEVICEOBJECTINSTANCE_DX3W { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + WCHAR tszName[MAX_PATH]; +} DIDEVICEOBJECTINSTANCE_DX3W, *LPDIDEVICEOBJECTINSTANCE_DX3W; +typedef const DIDEVICEOBJECTINSTANCE_DX3W *LPCDIDEVICEOBJECTINSTANCE_DX3W; + +DECL_WINELIB_TYPE_AW(DIDEVICEOBJECTINSTANCE_DX3) +DECL_WINELIB_TYPE_AW(LPDIDEVICEOBJECTINSTANCE_DX3) +DECL_WINELIB_TYPE_AW(LPCDIDEVICEOBJECTINSTANCE_DX3) + +typedef struct DIDEVICEOBJECTINSTANCEA { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + CHAR tszName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + DWORD dwFFMaxForce; + DWORD dwFFForceResolution; + WORD wCollectionNumber; + WORD wDesignatorIndex; + WORD wUsagePage; + WORD wUsage; + DWORD dwDimension; + WORD wExponent; + WORD wReserved; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEOBJECTINSTANCEA, *LPDIDEVICEOBJECTINSTANCEA; +typedef const DIDEVICEOBJECTINSTANCEA *LPCDIDEVICEOBJECTINSTANCEA; + +typedef struct DIDEVICEOBJECTINSTANCEW { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + WCHAR tszName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + DWORD dwFFMaxForce; + DWORD dwFFForceResolution; + WORD wCollectionNumber; + WORD wDesignatorIndex; + WORD wUsagePage; + WORD wUsage; + DWORD dwDimension; + WORD wExponent; + WORD wReserved; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEOBJECTINSTANCEW, *LPDIDEVICEOBJECTINSTANCEW; +typedef const DIDEVICEOBJECTINSTANCEW *LPCDIDEVICEOBJECTINSTANCEW; + +DECL_WINELIB_TYPE_AW(DIDEVICEOBJECTINSTANCE) +DECL_WINELIB_TYPE_AW(LPDIDEVICEOBJECTINSTANCE) +DECL_WINELIB_TYPE_AW(LPCDIDEVICEOBJECTINSTANCE) + +typedef struct DIDEVICEINSTANCE_DX3A { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + CHAR tszInstanceName[MAX_PATH]; + CHAR tszProductName[MAX_PATH]; +} DIDEVICEINSTANCE_DX3A, *LPDIDEVICEINSTANCE_DX3A; +typedef const DIDEVICEINSTANCE_DX3A *LPCDIDEVICEINSTANCE_DX3A; +typedef struct DIDEVICEINSTANCE_DX3W { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + WCHAR tszInstanceName[MAX_PATH]; + WCHAR tszProductName[MAX_PATH]; +} DIDEVICEINSTANCE_DX3W, *LPDIDEVICEINSTANCE_DX3W; +typedef const DIDEVICEINSTANCE_DX3W *LPCDIDEVICEINSTANCE_DX3W; + +DECL_WINELIB_TYPE_AW(DIDEVICEINSTANCE_DX3) +DECL_WINELIB_TYPE_AW(LPDIDEVICEINSTANCE_DX3) +DECL_WINELIB_TYPE_AW(LPCDIDEVICEINSTANCE_DX3) + +typedef struct DIDEVICEINSTANCEA { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + CHAR tszInstanceName[MAX_PATH]; + CHAR tszProductName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + GUID guidFFDriver; + WORD wUsagePage; + WORD wUsage; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEINSTANCEA, *LPDIDEVICEINSTANCEA; +typedef const DIDEVICEINSTANCEA *LPCDIDEVICEINSTANCEA; + +typedef struct DIDEVICEINSTANCEW { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + WCHAR tszInstanceName[MAX_PATH]; + WCHAR tszProductName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + GUID guidFFDriver; + WORD wUsagePage; + WORD wUsage; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEINSTANCEW, *LPDIDEVICEINSTANCEW; +typedef const DIDEVICEINSTANCEW *LPCDIDEVICEINSTANCEW; + +DECL_WINELIB_TYPE_AW(DIDEVICEINSTANCE) +DECL_WINELIB_TYPE_AW(LPDIDEVICEINSTANCE) +DECL_WINELIB_TYPE_AW(LPCDIDEVICEINSTANCE) + +typedef BOOL (CALLBACK *LPDIENUMDEVICESCALLBACKA)(LPCDIDEVICEINSTANCEA,LPVOID); +typedef BOOL (CALLBACK *LPDIENUMDEVICESCALLBACKW)(LPCDIDEVICEINSTANCEW,LPVOID); +DECL_WINELIB_TYPE_AW(LPDIENUMDEVICESCALLBACK) + +#define DIEDBS_MAPPEDPRI1 0x00000001 +#define DIEDBS_MAPPEDPRI2 0x00000002 +#define DIEDBS_RECENTDEVICE 0x00000010 +#define DIEDBS_NEWDEVICE 0x00000020 + +#define DIEDBSFL_ATTACHEDONLY 0x00000000 +#define DIEDBSFL_THISUSER 0x00000010 +#define DIEDBSFL_FORCEFEEDBACK DIEDFL_FORCEFEEDBACK +#define DIEDBSFL_AVAILABLEDEVICES 0x00001000 +#define DIEDBSFL_MULTIMICEKEYBOARDS 0x00002000 +#define DIEDBSFL_NONGAMINGDEVICES 0x00004000 +#define DIEDBSFL_VALID 0x00007110 + +#if DIRECTINPUT_VERSION >= 0x0800 +typedef BOOL (CALLBACK *LPDIENUMDEVICESBYSEMANTICSCBA)(LPCDIDEVICEINSTANCEA,LPDIRECTINPUTDEVICE8A,DWORD,DWORD,LPVOID); +typedef BOOL (CALLBACK *LPDIENUMDEVICESBYSEMANTICSCBW)(LPCDIDEVICEINSTANCEW,LPDIRECTINPUTDEVICE8W,DWORD,DWORD,LPVOID); +DECL_WINELIB_TYPE_AW(LPDIENUMDEVICESBYSEMANTICSCB) +#endif + +typedef BOOL (CALLBACK *LPDICONFIGUREDEVICESCALLBACK)(LPUNKNOWN,LPVOID); + +typedef BOOL (CALLBACK *LPDIENUMDEVICEOBJECTSCALLBACKA)(LPCDIDEVICEOBJECTINSTANCEA,LPVOID); +typedef BOOL (CALLBACK *LPDIENUMDEVICEOBJECTSCALLBACKW)(LPCDIDEVICEOBJECTINSTANCEW,LPVOID); +DECL_WINELIB_TYPE_AW(LPDIENUMDEVICEOBJECTSCALLBACK) + +#if DIRECTINPUT_VERSION >= 0x0500 +typedef BOOL (CALLBACK *LPDIENUMCREATEDEFFECTOBJECTSCALLBACK)(LPDIRECTINPUTEFFECT, LPVOID); +#endif + +#define DIK_ESCAPE 0x01 +#define DIK_1 0x02 +#define DIK_2 0x03 +#define DIK_3 0x04 +#define DIK_4 0x05 +#define DIK_5 0x06 +#define DIK_6 0x07 +#define DIK_7 0x08 +#define DIK_8 0x09 +#define DIK_9 0x0A +#define DIK_0 0x0B +#define DIK_MINUS 0x0C /* - on main keyboard */ +#define DIK_EQUALS 0x0D +#define DIK_BACK 0x0E /* backspace */ +#define DIK_TAB 0x0F +#define DIK_Q 0x10 +#define DIK_W 0x11 +#define DIK_E 0x12 +#define DIK_R 0x13 +#define DIK_T 0x14 +#define DIK_Y 0x15 +#define DIK_U 0x16 +#define DIK_I 0x17 +#define DIK_O 0x18 +#define DIK_P 0x19 +#define DIK_LBRACKET 0x1A +#define DIK_RBRACKET 0x1B +#define DIK_RETURN 0x1C /* Enter on main keyboard */ +#define DIK_LCONTROL 0x1D +#define DIK_A 0x1E +#define DIK_S 0x1F +#define DIK_D 0x20 +#define DIK_F 0x21 +#define DIK_G 0x22 +#define DIK_H 0x23 +#define DIK_J 0x24 +#define DIK_K 0x25 +#define DIK_L 0x26 +#define DIK_SEMICOLON 0x27 +#define DIK_APOSTROPHE 0x28 +#define DIK_GRAVE 0x29 /* accent grave */ +#define DIK_LSHIFT 0x2A +#define DIK_BACKSLASH 0x2B +#define DIK_Z 0x2C +#define DIK_X 0x2D +#define DIK_C 0x2E +#define DIK_V 0x2F +#define DIK_B 0x30 +#define DIK_N 0x31 +#define DIK_M 0x32 +#define DIK_COMMA 0x33 +#define DIK_PERIOD 0x34 /* . on main keyboard */ +#define DIK_SLASH 0x35 /* / on main keyboard */ +#define DIK_RSHIFT 0x36 +#define DIK_MULTIPLY 0x37 /* * on numeric keypad */ +#define DIK_LMENU 0x38 /* left Alt */ +#define DIK_SPACE 0x39 +#define DIK_CAPITAL 0x3A +#define DIK_F1 0x3B +#define DIK_F2 0x3C +#define DIK_F3 0x3D +#define DIK_F4 0x3E +#define DIK_F5 0x3F +#define DIK_F6 0x40 +#define DIK_F7 0x41 +#define DIK_F8 0x42 +#define DIK_F9 0x43 +#define DIK_F10 0x44 +#define DIK_NUMLOCK 0x45 +#define DIK_SCROLL 0x46 /* Scroll Lock */ +#define DIK_NUMPAD7 0x47 +#define DIK_NUMPAD8 0x48 +#define DIK_NUMPAD9 0x49 +#define DIK_SUBTRACT 0x4A /* - on numeric keypad */ +#define DIK_NUMPAD4 0x4B +#define DIK_NUMPAD5 0x4C +#define DIK_NUMPAD6 0x4D +#define DIK_ADD 0x4E /* + on numeric keypad */ +#define DIK_NUMPAD1 0x4F +#define DIK_NUMPAD2 0x50 +#define DIK_NUMPAD3 0x51 +#define DIK_NUMPAD0 0x52 +#define DIK_DECIMAL 0x53 /* . on numeric keypad */ +#define DIK_OEM_102 0x56 /* < > | on UK/Germany keyboards */ +#define DIK_F11 0x57 +#define DIK_F12 0x58 +#define DIK_F13 0x64 /* (NEC PC98) */ +#define DIK_F14 0x65 /* (NEC PC98) */ +#define DIK_F15 0x66 /* (NEC PC98) */ +#define DIK_KANA 0x70 /* (Japanese keyboard) */ +#define DIK_ABNT_C1 0x73 /* / ? on Portugese (Brazilian) keyboards */ +#define DIK_CONVERT 0x79 /* (Japanese keyboard) */ +#define DIK_NOCONVERT 0x7B /* (Japanese keyboard) */ +#define DIK_YEN 0x7D /* (Japanese keyboard) */ +#define DIK_ABNT_C2 0x7E /* Numpad . on Portugese (Brazilian) keyboards */ +#define DIK_NUMPADEQUALS 0x8D /* = on numeric keypad (NEC PC98) */ +#define DIK_CIRCUMFLEX 0x90 /* (Japanese keyboard) */ +#define DIK_AT 0x91 /* (NEC PC98) */ +#define DIK_COLON 0x92 /* (NEC PC98) */ +#define DIK_UNDERLINE 0x93 /* (NEC PC98) */ +#define DIK_KANJI 0x94 /* (Japanese keyboard) */ +#define DIK_STOP 0x95 /* (NEC PC98) */ +#define DIK_AX 0x96 /* (Japan AX) */ +#define DIK_UNLABELED 0x97 /* (J3100) */ +#define DIK_NEXTTRACK 0x99 /* Next Track */ +#define DIK_NUMPADENTER 0x9C /* Enter on numeric keypad */ +#define DIK_RCONTROL 0x9D +#define DIK_MUTE 0xA0 /* Mute */ +#define DIK_CALCULATOR 0xA1 /* Calculator */ +#define DIK_PLAYPAUSE 0xA2 /* Play / Pause */ +#define DIK_MEDIASTOP 0xA4 /* Media Stop */ +#define DIK_VOLUMEDOWN 0xAE /* Volume - */ +#define DIK_VOLUMEUP 0xB0 /* Volume + */ +#define DIK_WEBHOME 0xB2 /* Web home */ +#define DIK_NUMPADCOMMA 0xB3 /* , on numeric keypad (NEC PC98) */ +#define DIK_DIVIDE 0xB5 /* / on numeric keypad */ +#define DIK_SYSRQ 0xB7 +#define DIK_RMENU 0xB8 /* right Alt */ +#define DIK_PAUSE 0xC5 /* Pause */ +#define DIK_HOME 0xC7 /* Home on arrow keypad */ +#define DIK_UP 0xC8 /* UpArrow on arrow keypad */ +#define DIK_PRIOR 0xC9 /* PgUp on arrow keypad */ +#define DIK_LEFT 0xCB /* LeftArrow on arrow keypad */ +#define DIK_RIGHT 0xCD /* RightArrow on arrow keypad */ +#define DIK_END 0xCF /* End on arrow keypad */ +#define DIK_DOWN 0xD0 /* DownArrow on arrow keypad */ +#define DIK_NEXT 0xD1 /* PgDn on arrow keypad */ +#define DIK_INSERT 0xD2 /* Insert on arrow keypad */ +#define DIK_DELETE 0xD3 /* Delete on arrow keypad */ +#define DIK_LWIN 0xDB /* Left Windows key */ +#define DIK_RWIN 0xDC /* Right Windows key */ +#define DIK_APPS 0xDD /* AppMenu key */ +#define DIK_POWER 0xDE +#define DIK_SLEEP 0xDF +#define DIK_WAKE 0xE3 /* System Wake */ +#define DIK_WEBSEARCH 0xE5 /* Web Search */ +#define DIK_WEBFAVORITES 0xE6 /* Web Favorites */ +#define DIK_WEBREFRESH 0xE7 /* Web Refresh */ +#define DIK_WEBSTOP 0xE8 /* Web Stop */ +#define DIK_WEBFORWARD 0xE9 /* Web Forward */ +#define DIK_WEBBACK 0xEA /* Web Back */ +#define DIK_MYCOMPUTER 0xEB /* My Computer */ +#define DIK_MAIL 0xEC /* Mail */ +#define DIK_MEDIASELECT 0xED /* Media Select */ + +#define DIK_BACKSPACE DIK_BACK /* backspace */ +#define DIK_NUMPADSTAR DIK_MULTIPLY /* * on numeric keypad */ +#define DIK_LALT DIK_LMENU /* left Alt */ +#define DIK_CAPSLOCK DIK_CAPITAL /* CapsLock */ +#define DIK_NUMPADMINUS DIK_SUBTRACT /* - on numeric keypad */ +#define DIK_NUMPADPLUS DIK_ADD /* + on numeric keypad */ +#define DIK_NUMPADPERIOD DIK_DECIMAL /* . on numeric keypad */ +#define DIK_NUMPADSLASH DIK_DIVIDE /* / on numeric keypad */ +#define DIK_RALT DIK_RMENU /* right Alt */ +#define DIK_UPARROW DIK_UP /* UpArrow on arrow keypad */ +#define DIK_PGUP DIK_PRIOR /* PgUp on arrow keypad */ +#define DIK_LEFTARROW DIK_LEFT /* LeftArrow on arrow keypad */ +#define DIK_RIGHTARROW DIK_RIGHT /* RightArrow on arrow keypad */ +#define DIK_DOWNARROW DIK_DOWN /* DownArrow on arrow keypad */ +#define DIK_PGDN DIK_NEXT /* PgDn on arrow keypad */ + +#define DIDFT_ALL 0x00000000 +#define DIDFT_RELAXIS 0x00000001 +#define DIDFT_ABSAXIS 0x00000002 +#define DIDFT_AXIS 0x00000003 +#define DIDFT_PSHBUTTON 0x00000004 +#define DIDFT_TGLBUTTON 0x00000008 +#define DIDFT_BUTTON 0x0000000C +#define DIDFT_POV 0x00000010 +#define DIDFT_COLLECTION 0x00000040 +#define DIDFT_NODATA 0x00000080 +#define DIDFT_ANYINSTANCE 0x00FFFF00 +#define DIDFT_INSTANCEMASK DIDFT_ANYINSTANCE +#define DIDFT_MAKEINSTANCE(n) ((WORD)(n) << 8) +#define DIDFT_GETTYPE(n) LOBYTE(n) +#define DIDFT_GETINSTANCE(n) LOWORD((n) >> 8) +#define DIDFT_FFACTUATOR 0x01000000 +#define DIDFT_FFEFFECTTRIGGER 0x02000000 +#if DIRECTINPUT_VERSION >= 0x050a +#define DIDFT_OUTPUT 0x10000000 +#define DIDFT_VENDORDEFINED 0x04000000 +#define DIDFT_ALIAS 0x08000000 +#endif /* DI5a */ +#ifndef DIDFT_OPTIONAL +#define DIDFT_OPTIONAL 0x80000000 +#endif +#define DIDFT_ENUMCOLLECTION(n) ((WORD)(n) << 8) +#define DIDFT_NOCOLLECTION 0x00FFFF00 + +#define DIDF_ABSAXIS 0x00000001 +#define DIDF_RELAXIS 0x00000002 + +#define DIGDD_PEEK 0x00000001 + +#define DISEQUENCE_COMPARE(dwSq1,cmp,dwSq2) ((int)((dwSq1) - (dwSq2)) cmp 0) + +typedef struct DIDEVICEOBJECTDATA_DX3 { + DWORD dwOfs; + DWORD dwData; + DWORD dwTimeStamp; + DWORD dwSequence; +} DIDEVICEOBJECTDATA_DX3,*LPDIDEVICEOBJECTDATA_DX3; +typedef const DIDEVICEOBJECTDATA_DX3 *LPCDIDEVICEOBJECTDATA_DX3; + +typedef struct DIDEVICEOBJECTDATA { + DWORD dwOfs; + DWORD dwData; + DWORD dwTimeStamp; + DWORD dwSequence; +#if(DIRECTINPUT_VERSION >= 0x0800) + UINT_PTR uAppData; +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ +} DIDEVICEOBJECTDATA, *LPDIDEVICEOBJECTDATA; +typedef const DIDEVICEOBJECTDATA *LPCDIDEVICEOBJECTDATA; + +typedef struct _DIOBJECTDATAFORMAT { + const GUID *pguid; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; +} DIOBJECTDATAFORMAT, *LPDIOBJECTDATAFORMAT; +typedef const DIOBJECTDATAFORMAT *LPCDIOBJECTDATAFORMAT; + +typedef struct _DIDATAFORMAT { + DWORD dwSize; + DWORD dwObjSize; + DWORD dwFlags; + DWORD dwDataSize; + DWORD dwNumObjs; + LPDIOBJECTDATAFORMAT rgodf; +} DIDATAFORMAT, *LPDIDATAFORMAT; +typedef const DIDATAFORMAT *LPCDIDATAFORMAT; + +#if DIRECTINPUT_VERSION >= 0x0500 +#define DIDOI_FFACTUATOR 0x00000001 +#define DIDOI_FFEFFECTTRIGGER 0x00000002 +#define DIDOI_POLLED 0x00008000 +#define DIDOI_ASPECTPOSITION 0x00000100 +#define DIDOI_ASPECTVELOCITY 0x00000200 +#define DIDOI_ASPECTACCEL 0x00000300 +#define DIDOI_ASPECTFORCE 0x00000400 +#define DIDOI_ASPECTMASK 0x00000F00 +#endif /* DI5 */ +#if DIRECTINPUT_VERSION >= 0x050a +#define DIDOI_GUIDISUSAGE 0x00010000 +#endif /* DI5a */ + +typedef struct DIPROPHEADER { + DWORD dwSize; + DWORD dwHeaderSize; + DWORD dwObj; + DWORD dwHow; +} DIPROPHEADER,*LPDIPROPHEADER; +typedef const DIPROPHEADER *LPCDIPROPHEADER; + +#define DIPH_DEVICE 0 +#define DIPH_BYOFFSET 1 +#define DIPH_BYID 2 +#if DIRECTINPUT_VERSION >= 0x050a +#define DIPH_BYUSAGE 3 + +#define DIMAKEUSAGEDWORD(UsagePage, Usage) (DWORD)MAKELONG(Usage, UsagePage) +#endif /* DI5a */ + +typedef struct DIPROPDWORD { + DIPROPHEADER diph; + DWORD dwData; +} DIPROPDWORD, *LPDIPROPDWORD; +typedef const DIPROPDWORD *LPCDIPROPDWORD; + +typedef struct DIPROPRANGE { + DIPROPHEADER diph; + LONG lMin; + LONG lMax; +} DIPROPRANGE, *LPDIPROPRANGE; +typedef const DIPROPRANGE *LPCDIPROPRANGE; + +#define DIPROPRANGE_NOMIN ((LONG)0x80000000) +#define DIPROPRANGE_NOMAX ((LONG)0x7FFFFFFF) + +#if DIRECTINPUT_VERSION >= 0x050a +typedef struct DIPROPCAL { + DIPROPHEADER diph; + LONG lMin; + LONG lCenter; + LONG lMax; +} DIPROPCAL, *LPDIPROPCAL; +typedef const DIPROPCAL *LPCDIPROPCAL; + +typedef struct DIPROPCALPOV { + DIPROPHEADER diph; + LONG lMin[5]; + LONG lMax[5]; +} DIPROPCALPOV, *LPDIPROPCALPOV; +typedef const DIPROPCALPOV *LPCDIPROPCALPOV; + +typedef struct DIPROPGUIDANDPATH { + DIPROPHEADER diph; + GUID guidClass; + WCHAR wszPath[MAX_PATH]; +} DIPROPGUIDANDPATH, *LPDIPROPGUIDANDPATH; +typedef const DIPROPGUIDANDPATH *LPCDIPROPGUIDANDPATH; + +typedef struct DIPROPSTRING { + DIPROPHEADER diph; + WCHAR wsz[MAX_PATH]; +} DIPROPSTRING, *LPDIPROPSTRING; +typedef const DIPROPSTRING *LPCDIPROPSTRING; +#endif /* DI5a */ + +#if DIRECTINPUT_VERSION >= 0x0800 +typedef struct DIPROPPOINTER { + DIPROPHEADER diph; + UINT_PTR uData; +} DIPROPPOINTER, *LPDIPROPPOINTER; +typedef const DIPROPPOINTER *LPCDIPROPPOINTER; +#endif /* DI8 */ + +/* special property GUIDs */ +#ifdef __cplusplus +#define MAKEDIPROP(prop) (*(const GUID *)(prop)) +#else +#define MAKEDIPROP(prop) ((REFGUID)(prop)) +#endif +#define DIPROP_BUFFERSIZE MAKEDIPROP(1) +#define DIPROP_AXISMODE MAKEDIPROP(2) + +#define DIPROPAXISMODE_ABS 0 +#define DIPROPAXISMODE_REL 1 + +#define DIPROP_GRANULARITY MAKEDIPROP(3) +#define DIPROP_RANGE MAKEDIPROP(4) +#define DIPROP_DEADZONE MAKEDIPROP(5) +#define DIPROP_SATURATION MAKEDIPROP(6) +#define DIPROP_FFGAIN MAKEDIPROP(7) +#define DIPROP_FFLOAD MAKEDIPROP(8) +#define DIPROP_AUTOCENTER MAKEDIPROP(9) + +#define DIPROPAUTOCENTER_OFF 0 +#define DIPROPAUTOCENTER_ON 1 + +#define DIPROP_CALIBRATIONMODE MAKEDIPROP(10) + +#define DIPROPCALIBRATIONMODE_COOKED 0 +#define DIPROPCALIBRATIONMODE_RAW 1 + +#if DIRECTINPUT_VERSION >= 0x050a +#define DIPROP_CALIBRATION MAKEDIPROP(11) +#define DIPROP_GUIDANDPATH MAKEDIPROP(12) +#define DIPROP_INSTANCENAME MAKEDIPROP(13) +#define DIPROP_PRODUCTNAME MAKEDIPROP(14) +#endif + +#if DIRECTINPUT_VERSION >= 0x5B2 +#define DIPROP_JOYSTICKID MAKEDIPROP(15) +#define DIPROP_GETPORTDISPLAYNAME MAKEDIPROP(16) +#endif + +#if DIRECTINPUT_VERSION >= 0x0700 +#define DIPROP_PHYSICALRANGE MAKEDIPROP(18) +#define DIPROP_LOGICALRANGE MAKEDIPROP(19) +#endif + +#if(DIRECTINPUT_VERSION >= 0x0800) +#define DIPROP_KEYNAME MAKEDIPROP(20) +#define DIPROP_CPOINTS MAKEDIPROP(21) +#define DIPROP_APPDATA MAKEDIPROP(22) +#define DIPROP_SCANCODE MAKEDIPROP(23) +#define DIPROP_VIDPID MAKEDIPROP(24) +#define DIPROP_USERNAME MAKEDIPROP(25) +#define DIPROP_TYPENAME MAKEDIPROP(26) + +#define MAXCPOINTSNUM 8 + +typedef struct _CPOINT { + LONG lP; + DWORD dwLog; +} CPOINT, *PCPOINT; + +typedef struct DIPROPCPOINTS { + DIPROPHEADER diph; + DWORD dwCPointsNum; + CPOINT cp[MAXCPOINTSNUM]; +} DIPROPCPOINTS, *LPDIPROPCPOINTS; +typedef const DIPROPCPOINTS *LPCDIPROPCPOINTS; +#endif /* DI8 */ + + +typedef struct DIDEVCAPS_DX3 { + DWORD dwSize; + DWORD dwFlags; + DWORD dwDevType; + DWORD dwAxes; + DWORD dwButtons; + DWORD dwPOVs; +} DIDEVCAPS_DX3, *LPDIDEVCAPS_DX3; + +typedef struct DIDEVCAPS { + DWORD dwSize; + DWORD dwFlags; + DWORD dwDevType; + DWORD dwAxes; + DWORD dwButtons; + DWORD dwPOVs; +#if(DIRECTINPUT_VERSION >= 0x0500) + DWORD dwFFSamplePeriod; + DWORD dwFFMinTimeResolution; + DWORD dwFirmwareRevision; + DWORD dwHardwareRevision; + DWORD dwFFDriverVersion; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVCAPS,*LPDIDEVCAPS; + +#define DIDC_ATTACHED 0x00000001 +#define DIDC_POLLEDDEVICE 0x00000002 +#define DIDC_EMULATED 0x00000004 +#define DIDC_POLLEDDATAFORMAT 0x00000008 +#define DIDC_FORCEFEEDBACK 0x00000100 +#define DIDC_FFATTACK 0x00000200 +#define DIDC_FFFADE 0x00000400 +#define DIDC_SATURATION 0x00000800 +#define DIDC_POSNEGCOEFFICIENTS 0x00001000 +#define DIDC_POSNEGSATURATION 0x00002000 +#define DIDC_DEADBAND 0x00004000 +#define DIDC_STARTDELAY 0x00008000 +#define DIDC_ALIAS 0x00010000 +#define DIDC_PHANTOM 0x00020000 +#define DIDC_HIDDEN 0x00040000 + + +/* SetCooperativeLevel dwFlags */ +#define DISCL_EXCLUSIVE 0x00000001 +#define DISCL_NONEXCLUSIVE 0x00000002 +#define DISCL_FOREGROUND 0x00000004 +#define DISCL_BACKGROUND 0x00000008 +#define DISCL_NOWINKEY 0x00000010 + +#if (DIRECTINPUT_VERSION >= 0x0500) +/* Device FF flags */ +#define DISFFC_RESET 0x00000001 +#define DISFFC_STOPALL 0x00000002 +#define DISFFC_PAUSE 0x00000004 +#define DISFFC_CONTINUE 0x00000008 +#define DISFFC_SETACTUATORSON 0x00000010 +#define DISFFC_SETACTUATORSOFF 0x00000020 + +#define DIGFFS_EMPTY 0x00000001 +#define DIGFFS_STOPPED 0x00000002 +#define DIGFFS_PAUSED 0x00000004 +#define DIGFFS_ACTUATORSON 0x00000010 +#define DIGFFS_ACTUATORSOFF 0x00000020 +#define DIGFFS_POWERON 0x00000040 +#define DIGFFS_POWEROFF 0x00000080 +#define DIGFFS_SAFETYSWITCHON 0x00000100 +#define DIGFFS_SAFETYSWITCHOFF 0x00000200 +#define DIGFFS_USERFFSWITCHON 0x00000400 +#define DIGFFS_USERFFSWITCHOFF 0x00000800 +#define DIGFFS_DEVICELOST 0x80000000 + +/* Effect flags */ +#define DIEFT_ALL 0x00000000 + +#define DIEFT_CONSTANTFORCE 0x00000001 +#define DIEFT_RAMPFORCE 0x00000002 +#define DIEFT_PERIODIC 0x00000003 +#define DIEFT_CONDITION 0x00000004 +#define DIEFT_CUSTOMFORCE 0x00000005 +#define DIEFT_HARDWARE 0x000000FF +#define DIEFT_FFATTACK 0x00000200 +#define DIEFT_FFFADE 0x00000400 +#define DIEFT_SATURATION 0x00000800 +#define DIEFT_POSNEGCOEFFICIENTS 0x00001000 +#define DIEFT_POSNEGSATURATION 0x00002000 +#define DIEFT_DEADBAND 0x00004000 +#define DIEFT_STARTDELAY 0x00008000 +#define DIEFT_GETTYPE(n) LOBYTE(n) + +#define DIEFF_OBJECTIDS 0x00000001 +#define DIEFF_OBJECTOFFSETS 0x00000002 +#define DIEFF_CARTESIAN 0x00000010 +#define DIEFF_POLAR 0x00000020 +#define DIEFF_SPHERICAL 0x00000040 + +#define DIEP_DURATION 0x00000001 +#define DIEP_SAMPLEPERIOD 0x00000002 +#define DIEP_GAIN 0x00000004 +#define DIEP_TRIGGERBUTTON 0x00000008 +#define DIEP_TRIGGERREPEATINTERVAL 0x00000010 +#define DIEP_AXES 0x00000020 +#define DIEP_DIRECTION 0x00000040 +#define DIEP_ENVELOPE 0x00000080 +#define DIEP_TYPESPECIFICPARAMS 0x00000100 +#if(DIRECTINPUT_VERSION >= 0x0600) +#define DIEP_STARTDELAY 0x00000200 +#define DIEP_ALLPARAMS_DX5 0x000001FF +#define DIEP_ALLPARAMS 0x000003FF +#else +#define DIEP_ALLPARAMS 0x000001FF +#endif /* DIRECTINPUT_VERSION >= 0x0600 */ +#define DIEP_START 0x20000000 +#define DIEP_NORESTART 0x40000000 +#define DIEP_NODOWNLOAD 0x80000000 +#define DIEB_NOTRIGGER 0xFFFFFFFF + +#define DIES_SOLO 0x00000001 +#define DIES_NODOWNLOAD 0x80000000 + +#define DIEGES_PLAYING 0x00000001 +#define DIEGES_EMULATED 0x00000002 + +#define DI_DEGREES 100 +#define DI_FFNOMINALMAX 10000 +#define DI_SECONDS 1000000 + +typedef struct DICONSTANTFORCE { + LONG lMagnitude; +} DICONSTANTFORCE, *LPDICONSTANTFORCE; +typedef const DICONSTANTFORCE *LPCDICONSTANTFORCE; + +typedef struct DIRAMPFORCE { + LONG lStart; + LONG lEnd; +} DIRAMPFORCE, *LPDIRAMPFORCE; +typedef const DIRAMPFORCE *LPCDIRAMPFORCE; + +typedef struct DIPERIODIC { + DWORD dwMagnitude; + LONG lOffset; + DWORD dwPhase; + DWORD dwPeriod; +} DIPERIODIC, *LPDIPERIODIC; +typedef const DIPERIODIC *LPCDIPERIODIC; + +typedef struct DICONDITION { + LONG lOffset; + LONG lPositiveCoefficient; + LONG lNegativeCoefficient; + DWORD dwPositiveSaturation; + DWORD dwNegativeSaturation; + LONG lDeadBand; +} DICONDITION, *LPDICONDITION; +typedef const DICONDITION *LPCDICONDITION; + +typedef struct DICUSTOMFORCE { + DWORD cChannels; + DWORD dwSamplePeriod; + DWORD cSamples; + LPLONG rglForceData; +} DICUSTOMFORCE, *LPDICUSTOMFORCE; +typedef const DICUSTOMFORCE *LPCDICUSTOMFORCE; + +typedef struct DIENVELOPE { + DWORD dwSize; + DWORD dwAttackLevel; + DWORD dwAttackTime; + DWORD dwFadeLevel; + DWORD dwFadeTime; +} DIENVELOPE, *LPDIENVELOPE; +typedef const DIENVELOPE *LPCDIENVELOPE; + +typedef struct DIEFFECT_DX5 { + DWORD dwSize; + DWORD dwFlags; + DWORD dwDuration; + DWORD dwSamplePeriod; + DWORD dwGain; + DWORD dwTriggerButton; + DWORD dwTriggerRepeatInterval; + DWORD cAxes; + LPDWORD rgdwAxes; + LPLONG rglDirection; + LPDIENVELOPE lpEnvelope; + DWORD cbTypeSpecificParams; + LPVOID lpvTypeSpecificParams; +} DIEFFECT_DX5, *LPDIEFFECT_DX5; +typedef const DIEFFECT_DX5 *LPCDIEFFECT_DX5; + +typedef struct DIEFFECT { + DWORD dwSize; + DWORD dwFlags; + DWORD dwDuration; + DWORD dwSamplePeriod; + DWORD dwGain; + DWORD dwTriggerButton; + DWORD dwTriggerRepeatInterval; + DWORD cAxes; + LPDWORD rgdwAxes; + LPLONG rglDirection; + LPDIENVELOPE lpEnvelope; + DWORD cbTypeSpecificParams; + LPVOID lpvTypeSpecificParams; +#if(DIRECTINPUT_VERSION >= 0x0600) + DWORD dwStartDelay; +#endif /* DIRECTINPUT_VERSION >= 0x0600 */ +} DIEFFECT, *LPDIEFFECT; +typedef const DIEFFECT *LPCDIEFFECT; +typedef DIEFFECT DIEFFECT_DX6; +typedef LPDIEFFECT LPDIEFFECT_DX6; + +typedef struct DIEFFECTINFOA { + DWORD dwSize; + GUID guid; + DWORD dwEffType; + DWORD dwStaticParams; + DWORD dwDynamicParams; + CHAR tszName[MAX_PATH]; +} DIEFFECTINFOA, *LPDIEFFECTINFOA; +typedef const DIEFFECTINFOA *LPCDIEFFECTINFOA; + +typedef struct DIEFFECTINFOW { + DWORD dwSize; + GUID guid; + DWORD dwEffType; + DWORD dwStaticParams; + DWORD dwDynamicParams; + WCHAR tszName[MAX_PATH]; +} DIEFFECTINFOW, *LPDIEFFECTINFOW; +typedef const DIEFFECTINFOW *LPCDIEFFECTINFOW; + +DECL_WINELIB_TYPE_AW(DIEFFECTINFO) +DECL_WINELIB_TYPE_AW(LPDIEFFECTINFO) +DECL_WINELIB_TYPE_AW(LPCDIEFFECTINFO) + +typedef BOOL (CALLBACK *LPDIENUMEFFECTSCALLBACKA)(LPCDIEFFECTINFOA, LPVOID); +typedef BOOL (CALLBACK *LPDIENUMEFFECTSCALLBACKW)(LPCDIEFFECTINFOW, LPVOID); + +typedef struct DIEFFESCAPE { + DWORD dwSize; + DWORD dwCommand; + LPVOID lpvInBuffer; + DWORD cbInBuffer; + LPVOID lpvOutBuffer; + DWORD cbOutBuffer; +} DIEFFESCAPE, *LPDIEFFESCAPE; + +typedef struct DIJOYSTATE { + LONG lX; + LONG lY; + LONG lZ; + LONG lRx; + LONG lRy; + LONG lRz; + LONG rglSlider[2]; + DWORD rgdwPOV[4]; + BYTE rgbButtons[32]; +} DIJOYSTATE, *LPDIJOYSTATE; + +typedef struct DIJOYSTATE2 { + LONG lX; + LONG lY; + LONG lZ; + LONG lRx; + LONG lRy; + LONG lRz; + LONG rglSlider[2]; + DWORD rgdwPOV[4]; + BYTE rgbButtons[128]; + LONG lVX; /* 'v' as in velocity */ + LONG lVY; + LONG lVZ; + LONG lVRx; + LONG lVRy; + LONG lVRz; + LONG rglVSlider[2]; + LONG lAX; /* 'a' as in acceleration */ + LONG lAY; + LONG lAZ; + LONG lARx; + LONG lARy; + LONG lARz; + LONG rglASlider[2]; + LONG lFX; /* 'f' as in force */ + LONG lFY; + LONG lFZ; + LONG lFRx; /* 'fr' as in rotational force aka torque */ + LONG lFRy; + LONG lFRz; + LONG rglFSlider[2]; +} DIJOYSTATE2, *LPDIJOYSTATE2; + +#define DIJOFS_X FIELD_OFFSET(DIJOYSTATE, lX) +#define DIJOFS_Y FIELD_OFFSET(DIJOYSTATE, lY) +#define DIJOFS_Z FIELD_OFFSET(DIJOYSTATE, lZ) +#define DIJOFS_RX FIELD_OFFSET(DIJOYSTATE, lRx) +#define DIJOFS_RY FIELD_OFFSET(DIJOYSTATE, lRy) +#define DIJOFS_RZ FIELD_OFFSET(DIJOYSTATE, lRz) +#define DIJOFS_SLIDER(n) (FIELD_OFFSET(DIJOYSTATE, rglSlider) + \ + (n) * sizeof(LONG)) +#define DIJOFS_POV(n) (FIELD_OFFSET(DIJOYSTATE, rgdwPOV) + \ + (n) * sizeof(DWORD)) +#define DIJOFS_BUTTON(n) (FIELD_OFFSET(DIJOYSTATE, rgbButtons) + (n)) +#define DIJOFS_BUTTON0 DIJOFS_BUTTON(0) +#define DIJOFS_BUTTON1 DIJOFS_BUTTON(1) +#define DIJOFS_BUTTON2 DIJOFS_BUTTON(2) +#define DIJOFS_BUTTON3 DIJOFS_BUTTON(3) +#define DIJOFS_BUTTON4 DIJOFS_BUTTON(4) +#define DIJOFS_BUTTON5 DIJOFS_BUTTON(5) +#define DIJOFS_BUTTON6 DIJOFS_BUTTON(6) +#define DIJOFS_BUTTON7 DIJOFS_BUTTON(7) +#define DIJOFS_BUTTON8 DIJOFS_BUTTON(8) +#define DIJOFS_BUTTON9 DIJOFS_BUTTON(9) +#define DIJOFS_BUTTON10 DIJOFS_BUTTON(10) +#define DIJOFS_BUTTON11 DIJOFS_BUTTON(11) +#define DIJOFS_BUTTON12 DIJOFS_BUTTON(12) +#define DIJOFS_BUTTON13 DIJOFS_BUTTON(13) +#define DIJOFS_BUTTON14 DIJOFS_BUTTON(14) +#define DIJOFS_BUTTON15 DIJOFS_BUTTON(15) +#define DIJOFS_BUTTON16 DIJOFS_BUTTON(16) +#define DIJOFS_BUTTON17 DIJOFS_BUTTON(17) +#define DIJOFS_BUTTON18 DIJOFS_BUTTON(18) +#define DIJOFS_BUTTON19 DIJOFS_BUTTON(19) +#define DIJOFS_BUTTON20 DIJOFS_BUTTON(20) +#define DIJOFS_BUTTON21 DIJOFS_BUTTON(21) +#define DIJOFS_BUTTON22 DIJOFS_BUTTON(22) +#define DIJOFS_BUTTON23 DIJOFS_BUTTON(23) +#define DIJOFS_BUTTON24 DIJOFS_BUTTON(24) +#define DIJOFS_BUTTON25 DIJOFS_BUTTON(25) +#define DIJOFS_BUTTON26 DIJOFS_BUTTON(26) +#define DIJOFS_BUTTON27 DIJOFS_BUTTON(27) +#define DIJOFS_BUTTON28 DIJOFS_BUTTON(28) +#define DIJOFS_BUTTON29 DIJOFS_BUTTON(29) +#define DIJOFS_BUTTON30 DIJOFS_BUTTON(30) +#define DIJOFS_BUTTON31 DIJOFS_BUTTON(31) +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +/* DInput 7 structures, types */ +#if(DIRECTINPUT_VERSION >= 0x0700) +typedef struct DIFILEEFFECT { + DWORD dwSize; + GUID GuidEffect; + LPCDIEFFECT lpDiEffect; + CHAR szFriendlyName[MAX_PATH]; +} DIFILEEFFECT, *LPDIFILEEFFECT; + +typedef const DIFILEEFFECT *LPCDIFILEEFFECT; +typedef BOOL (CALLBACK *LPDIENUMEFFECTSINFILECALLBACK)(LPCDIFILEEFFECT , LPVOID); +#endif /* DIRECTINPUT_VERSION >= 0x0700 */ + +/* DInput 8 structures and types */ +#if DIRECTINPUT_VERSION >= 0x0800 +typedef struct _DIACTIONA { + UINT_PTR uAppData; + DWORD dwSemantic; + DWORD dwFlags; + __GNU_EXTENSION union { + LPCSTR lptszActionName; + UINT uResIdString; + } DUMMYUNIONNAME; + GUID guidInstance; + DWORD dwObjID; + DWORD dwHow; +} DIACTIONA, *LPDIACTIONA; +typedef const DIACTIONA *LPCDIACTIONA; + +typedef struct _DIACTIONW { + UINT_PTR uAppData; + DWORD dwSemantic; + DWORD dwFlags; + __GNU_EXTENSION union { + LPCWSTR lptszActionName; + UINT uResIdString; + } DUMMYUNIONNAME; + GUID guidInstance; + DWORD dwObjID; + DWORD dwHow; +} DIACTIONW, *LPDIACTIONW; +typedef const DIACTIONW *LPCDIACTIONW; + +DECL_WINELIB_TYPE_AW(DIACTION) +DECL_WINELIB_TYPE_AW(LPDIACTION) +DECL_WINELIB_TYPE_AW(LPCDIACTION) + +#define DIA_FORCEFEEDBACK 0x00000001 +#define DIA_APPMAPPED 0x00000002 +#define DIA_APPNOMAP 0x00000004 +#define DIA_NORANGE 0x00000008 +#define DIA_APPFIXED 0x00000010 + +#define DIAH_UNMAPPED 0x00000000 +#define DIAH_USERCONFIG 0x00000001 +#define DIAH_APPREQUESTED 0x00000002 +#define DIAH_HWAPP 0x00000004 +#define DIAH_HWDEFAULT 0x00000008 +#define DIAH_DEFAULT 0x00000020 +#define DIAH_ERROR 0x80000000 + +typedef struct _DIACTIONFORMATA { + DWORD dwSize; + DWORD dwActionSize; + DWORD dwDataSize; + DWORD dwNumActions; + LPDIACTIONA rgoAction; + GUID guidActionMap; + DWORD dwGenre; + DWORD dwBufferSize; + LONG lAxisMin; + LONG lAxisMax; + HINSTANCE hInstString; + FILETIME ftTimeStamp; + DWORD dwCRC; + CHAR tszActionMap[MAX_PATH]; +} DIACTIONFORMATA, *LPDIACTIONFORMATA; +typedef const DIACTIONFORMATA *LPCDIACTIONFORMATA; + +typedef struct _DIACTIONFORMATW { + DWORD dwSize; + DWORD dwActionSize; + DWORD dwDataSize; + DWORD dwNumActions; + LPDIACTIONW rgoAction; + GUID guidActionMap; + DWORD dwGenre; + DWORD dwBufferSize; + LONG lAxisMin; + LONG lAxisMax; + HINSTANCE hInstString; + FILETIME ftTimeStamp; + DWORD dwCRC; + WCHAR tszActionMap[MAX_PATH]; +} DIACTIONFORMATW, *LPDIACTIONFORMATW; +typedef const DIACTIONFORMATW *LPCDIACTIONFORMATW; + +DECL_WINELIB_TYPE_AW(DIACTIONFORMAT) +DECL_WINELIB_TYPE_AW(LPDIACTIONFORMAT) +DECL_WINELIB_TYPE_AW(LPCDIACTIONFORMAT) + +#define DIAFTS_NEWDEVICELOW 0xFFFFFFFF +#define DIAFTS_NEWDEVICEHIGH 0xFFFFFFFF +#define DIAFTS_UNUSEDDEVICELOW 0x00000000 +#define DIAFTS_UNUSEDDEVICEHIGH 0x00000000 + +#define DIDBAM_DEFAULT 0x00000000 +#define DIDBAM_PRESERVE 0x00000001 +#define DIDBAM_INITIALIZE 0x00000002 +#define DIDBAM_HWDEFAULTS 0x00000004 + +#define DIDSAM_DEFAULT 0x00000000 +#define DIDSAM_NOUSER 0x00000001 +#define DIDSAM_FORCESAVE 0x00000002 + +#define DICD_DEFAULT 0x00000000 +#define DICD_EDIT 0x00000001 + +#ifndef D3DCOLOR_DEFINED +typedef DWORD D3DCOLOR; +#define D3DCOLOR_DEFINED +#endif + +typedef struct _DICOLORSET { + DWORD dwSize; + D3DCOLOR cTextFore; + D3DCOLOR cTextHighlight; + D3DCOLOR cCalloutLine; + D3DCOLOR cCalloutHighlight; + D3DCOLOR cBorder; + D3DCOLOR cControlFill; + D3DCOLOR cHighlightFill; + D3DCOLOR cAreaFill; +} DICOLORSET, *LPDICOLORSET; +typedef const DICOLORSET *LPCDICOLORSET; + +typedef struct _DICONFIGUREDEVICESPARAMSA { + DWORD dwSize; + DWORD dwcUsers; + LPSTR lptszUserNames; + DWORD dwcFormats; + LPDIACTIONFORMATA lprgFormats; + HWND hwnd; + DICOLORSET dics; + LPUNKNOWN lpUnkDDSTarget; +} DICONFIGUREDEVICESPARAMSA, *LPDICONFIGUREDEVICESPARAMSA; +typedef const DICONFIGUREDEVICESPARAMSA *LPCDICONFIGUREDEVICESPARAMSA; + +typedef struct _DICONFIGUREDEVICESPARAMSW { + DWORD dwSize; + DWORD dwcUsers; + LPWSTR lptszUserNames; + DWORD dwcFormats; + LPDIACTIONFORMATW lprgFormats; + HWND hwnd; + DICOLORSET dics; + LPUNKNOWN lpUnkDDSTarget; +} DICONFIGUREDEVICESPARAMSW, *LPDICONFIGUREDEVICESPARAMSW; +typedef const DICONFIGUREDEVICESPARAMSW *LPCDICONFIGUREDEVICESPARAMSW; + +DECL_WINELIB_TYPE_AW(DICONFIGUREDEVICESPARAMS) +DECL_WINELIB_TYPE_AW(LPDICONFIGUREDEVICESPARAMS) +DECL_WINELIB_TYPE_AW(LPCDICONFIGUREDEVICESPARAMS) + +#define DIDIFT_CONFIGURATION 0x00000001 +#define DIDIFT_OVERLAY 0x00000002 + +#define DIDAL_CENTERED 0x00000000 +#define DIDAL_LEFTALIGNED 0x00000001 +#define DIDAL_RIGHTALIGNED 0x00000002 +#define DIDAL_MIDDLE 0x00000000 +#define DIDAL_TOPALIGNED 0x00000004 +#define DIDAL_BOTTOMALIGNED 0x00000008 + +typedef struct _DIDEVICEIMAGEINFOA { + CHAR tszImagePath[MAX_PATH]; + DWORD dwFlags; + DWORD dwViewID; + RECT rcOverlay; + DWORD dwObjID; + DWORD dwcValidPts; + POINT rgptCalloutLine[5]; + RECT rcCalloutRect; + DWORD dwTextAlign; +} DIDEVICEIMAGEINFOA, *LPDIDEVICEIMAGEINFOA; +typedef const DIDEVICEIMAGEINFOA *LPCDIDEVICEIMAGEINFOA; + +typedef struct _DIDEVICEIMAGEINFOW { + WCHAR tszImagePath[MAX_PATH]; + DWORD dwFlags; + DWORD dwViewID; + RECT rcOverlay; + DWORD dwObjID; + DWORD dwcValidPts; + POINT rgptCalloutLine[5]; + RECT rcCalloutRect; + DWORD dwTextAlign; +} DIDEVICEIMAGEINFOW, *LPDIDEVICEIMAGEINFOW; +typedef const DIDEVICEIMAGEINFOW *LPCDIDEVICEIMAGEINFOW; + +DECL_WINELIB_TYPE_AW(DIDEVICEIMAGEINFO) +DECL_WINELIB_TYPE_AW(LPDIDEVICEIMAGEINFO) +DECL_WINELIB_TYPE_AW(LPCDIDEVICEIMAGEINFO) + +typedef struct _DIDEVICEIMAGEINFOHEADERA { + DWORD dwSize; + DWORD dwSizeImageInfo; + DWORD dwcViews; + DWORD dwcButtons; + DWORD dwcAxes; + DWORD dwcPOVs; + DWORD dwBufferSize; + DWORD dwBufferUsed; + LPDIDEVICEIMAGEINFOA lprgImageInfoArray; +} DIDEVICEIMAGEINFOHEADERA, *LPDIDEVICEIMAGEINFOHEADERA; +typedef const DIDEVICEIMAGEINFOHEADERA *LPCDIDEVICEIMAGEINFOHEADERA; + +typedef struct _DIDEVICEIMAGEINFOHEADERW { + DWORD dwSize; + DWORD dwSizeImageInfo; + DWORD dwcViews; + DWORD dwcButtons; + DWORD dwcAxes; + DWORD dwcPOVs; + DWORD dwBufferSize; + DWORD dwBufferUsed; + LPDIDEVICEIMAGEINFOW lprgImageInfoArray; +} DIDEVICEIMAGEINFOHEADERW, *LPDIDEVICEIMAGEINFOHEADERW; +typedef const DIDEVICEIMAGEINFOHEADERW *LPCDIDEVICEIMAGEINFOHEADERW; + +DECL_WINELIB_TYPE_AW(DIDEVICEIMAGEINFOHEADER) +DECL_WINELIB_TYPE_AW(LPDIDEVICEIMAGEINFOHEADER) +DECL_WINELIB_TYPE_AW(LPCDIDEVICEIMAGEINFOHEADER) + +#endif /* DI8 */ + + +/***************************************************************************** + * IDirectInputEffect interface + */ +#if (DIRECTINPUT_VERSION >= 0x0500) +#undef INTERFACE +#define INTERFACE IDirectInputEffect +DECLARE_INTERFACE_(IDirectInputEffect,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputEffect methods ***/ + STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD, REFGUID) PURE; + STDMETHOD(GetEffectGuid)(THIS_ LPGUID) PURE; + STDMETHOD(GetParameters)(THIS_ LPDIEFFECT, DWORD) PURE; + STDMETHOD(SetParameters)(THIS_ LPCDIEFFECT, DWORD) PURE; + STDMETHOD(Start)(THIS_ DWORD, DWORD) PURE; + STDMETHOD(Stop)(THIS) PURE; + STDMETHOD(GetEffectStatus)(THIS_ LPDWORD) PURE; + STDMETHOD(Download)(THIS) PURE; + STDMETHOD(Unload)(THIS) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInputEffect_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputEffect_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputEffect_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInputEffect methods ***/ +#define IDirectInputEffect_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#define IDirectInputEffect_GetEffectGuid(p,a) (p)->lpVtbl->GetEffectGuid(p,a) +#define IDirectInputEffect_GetParameters(p,a,b) (p)->lpVtbl->GetParameters(p,a,b) +#define IDirectInputEffect_SetParameters(p,a,b) (p)->lpVtbl->SetParameters(p,a,b) +#define IDirectInputEffect_Start(p,a,b) (p)->lpVtbl->Start(p,a,b) +#define IDirectInputEffect_Stop(p) (p)->lpVtbl->Stop(p) +#define IDirectInputEffect_GetEffectStatus(p,a) (p)->lpVtbl->GetEffectStatus(p,a) +#define IDirectInputEffect_Download(p) (p)->lpVtbl->Download(p) +#define IDirectInputEffect_Unload(p) (p)->lpVtbl->Unload(p) +#define IDirectInputEffect_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#else +/*** IUnknown methods ***/ +#define IDirectInputEffect_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputEffect_AddRef(p) (p)->AddRef() +#define IDirectInputEffect_Release(p) (p)->Release() +/*** IDirectInputEffect methods ***/ +#define IDirectInputEffect_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#define IDirectInputEffect_GetEffectGuid(p,a) (p)->GetEffectGuid(a) +#define IDirectInputEffect_GetParameters(p,a,b) (p)->GetParameters(a,b) +#define IDirectInputEffect_SetParameters(p,a,b) (p)->SetParameters(a,b) +#define IDirectInputEffect_Start(p,a,b) (p)->Start(a,b) +#define IDirectInputEffect_Stop(p) (p)->Stop() +#define IDirectInputEffect_GetEffectStatus(p,a) (p)->GetEffectStatus(a) +#define IDirectInputEffect_Download(p) (p)->Download() +#define IDirectInputEffect_Unload(p) (p)->Unload() +#define IDirectInputEffect_Escape(p,a) (p)->Escape(a) +#endif + +#endif /* DI5 */ + + +/***************************************************************************** + * IDirectInputDeviceA interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDeviceA +DECLARE_INTERFACE_(IDirectInputDeviceA,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceA methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; +}; + +/***************************************************************************** + * IDirectInputDeviceW interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDeviceW +DECLARE_INTERFACE_(IDirectInputDeviceW,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceW methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInputDevice_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#else +/*** IUnknown methods ***/ +#define IDirectInputDevice_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice_AddRef(p) (p)->AddRef() +#define IDirectInputDevice_Release(p) (p)->Release() +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice_Acquire(p) (p)->Acquire() +#define IDirectInputDevice_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#endif + + +#if (DIRECTINPUT_VERSION >= 0x0500) +/***************************************************************************** + * IDirectInputDevice2A interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDevice2A +DECLARE_INTERFACE_(IDirectInputDevice2A,IDirectInputDeviceA) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceA methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; + /*** IDirectInputDevice2A methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwEffType) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA pdei, REFGUID rguid) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD pdwOut) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD dwFlags) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE pesc) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) PURE; +}; + +/***************************************************************************** + * IDirectInputDevice2W interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDevice2W +DECLARE_INTERFACE_(IDirectInputDevice2W,IDirectInputDeviceW) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceW methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; + /*** IDirectInputDevice2W methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwEffType) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW pdei, REFGUID rguid) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD pdwOut) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD dwFlags) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE pesc) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInputDevice2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice2_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice2_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice2_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice2_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice2_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice2_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice2_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice2_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice2_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice2_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice2_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice2_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice2_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice2_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice2_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice2_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +/*** IDirectInputDevice2 methods ***/ +#define IDirectInputDevice2_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d) +#define IDirectInputDevice2_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c) +#define IDirectInputDevice2_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b) +#define IDirectInputDevice2_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a) +#define IDirectInputDevice2_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a) +#define IDirectInputDevice2_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c) +#define IDirectInputDevice2_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#define IDirectInputDevice2_Poll(p) (p)->lpVtbl->Poll(p) +#define IDirectInputDevice2_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d) +#else +/*** IUnknown methods ***/ +#define IDirectInputDevice2_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice2_AddRef(p) (p)->AddRef() +#define IDirectInputDevice2_Release(p) (p)->Release() +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice2_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice2_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice2_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice2_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice2_Acquire(p) (p)->Acquire() +#define IDirectInputDevice2_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice2_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice2_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice2_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice2_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice2_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice2_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice2_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice2_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice2_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +/*** IDirectInputDevice2 methods ***/ +#define IDirectInputDevice2_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d) +#define IDirectInputDevice2_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c) +#define IDirectInputDevice2_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b) +#define IDirectInputDevice2_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a) +#define IDirectInputDevice2_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a) +#define IDirectInputDevice2_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c) +#define IDirectInputDevice2_Escape(p,a) (p)->Escape(a) +#define IDirectInputDevice2_Poll(p) (p)->Poll() +#define IDirectInputDevice2_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d) +#endif +#endif /* DI5 */ + +#if DIRECTINPUT_VERSION >= 0x0700 +/***************************************************************************** + * IDirectInputDevice7A interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDevice7A +DECLARE_INTERFACE_(IDirectInputDevice7A,IDirectInputDevice2A) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceA methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; + /*** IDirectInputDevice2A methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwEffType) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA pdei, REFGUID rguid) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD pdwOut) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD dwFlags) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE pesc) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) PURE; + /*** IDirectInputDevice7A methods ***/ + STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR lpszFileName,LPDIENUMEFFECTSINFILECALLBACK pec,LPVOID pvRef,DWORD dwFlags) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR lpszFileName,DWORD dwEntries,LPDIFILEEFFECT rgDiFileEft,DWORD dwFlags) PURE; +}; + +/***************************************************************************** + * IDirectInputDevice7W interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDevice7W +DECLARE_INTERFACE_(IDirectInputDevice7W,IDirectInputDevice2W) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceW methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; + /*** IDirectInputDevice2W methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwEffType) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW pdei, REFGUID rguid) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD pdwOut) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD dwFlags) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE pesc) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) PURE; + /*** IDirectInputDevice7W methods ***/ + STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR lpszFileName,LPDIENUMEFFECTSINFILECALLBACK pec,LPVOID pvRef,DWORD dwFlags) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR lpszFileName,DWORD dwEntries,LPDIFILEEFFECT rgDiFileEft,DWORD dwFlags) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInputDevice7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice7_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice7_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice7_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice7_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice7_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice7_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice7_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice7_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice7_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice7_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice7_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice7_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice7_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice7_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice7_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice7_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice7_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +/*** IDirectInputDevice2 methods ***/ +#define IDirectInputDevice7_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d) +#define IDirectInputDevice7_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c) +#define IDirectInputDevice7_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b) +#define IDirectInputDevice7_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a) +#define IDirectInputDevice7_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a) +#define IDirectInputDevice7_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c) +#define IDirectInputDevice7_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#define IDirectInputDevice7_Poll(p) (p)->lpVtbl->Poll(p) +#define IDirectInputDevice7_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d) +/*** IDirectInputDevice7 methods ***/ +#define IDirectInputDevice7_EnumEffectsInFile(p,a,b,c,d) (p)->lpVtbl->EnumEffectsInFile(p,a,b,c,d) +#define IDirectInputDevice7_WriteEffectToFile(p,a,b,c,d) (p)->lpVtbl->WriteEffectToFile(p,a,b,c,d) +#else +/*** IUnknown methods ***/ +#define IDirectInputDevice7_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice7_AddRef(p) (p)->AddRef() +#define IDirectInputDevice7_Release(p) (p)->Release() +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice7_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice7_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice7_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice7_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice7_Acquire(p) (p)->Acquire() +#define IDirectInputDevice7_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice7_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice7_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice7_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice7_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice7_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice7_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice7_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice7_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice7_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +/*** IDirectInputDevice2 methods ***/ +#define IDirectInputDevice7_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d) +#define IDirectInputDevice7_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c) +#define IDirectInputDevice7_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b) +#define IDirectInputDevice7_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a) +#define IDirectInputDevice7_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a) +#define IDirectInputDevice7_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c) +#define IDirectInputDevice7_Escape(p,a) (p)->Escape(a) +#define IDirectInputDevice7_Poll(p) (p)->Poll() +#define IDirectInputDevice7_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d) +/*** IDirectInputDevice7 methods ***/ +#define IDirectInputDevice7_EnumEffectsInFile(p,a,b,c,d) (p)->EnumEffectsInFile(a,b,c,d) +#define IDirectInputDevice7_WriteEffectToFile(p,a,b,c,d) (p)->WriteEffectToFile(a,b,c,d) +#endif + +#endif /* DI7 */ + +#if DIRECTINPUT_VERSION >= 0x0800 +/***************************************************************************** + * IDirectInputDevice8A interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDevice8A +DECLARE_INTERFACE_(IDirectInputDevice8A,IDirectInputDevice7A) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceA methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; + /*** IDirectInputDevice2A methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwEffType) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA pdei, REFGUID rguid) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD pdwOut) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD dwFlags) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE pesc) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) PURE; + /*** IDirectInputDevice7A methods ***/ + STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR lpszFileName,LPDIENUMEFFECTSINFILECALLBACK pec,LPVOID pvRef,DWORD dwFlags) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR lpszFileName,DWORD dwEntries,LPDIFILEEFFECT rgDiFileEft,DWORD dwFlags) PURE; + /*** IDirectInputDevice8A methods ***/ + STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATA lpdiaf, LPCSTR lpszUserName, DWORD dwFlags) PURE; + STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATA lpdiaf, LPCSTR lpszUserName, DWORD dwFlags) PURE; + STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader) PURE; +}; + +/***************************************************************************** + * IDirectInputDevice8W interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputDevice8W +DECLARE_INTERFACE_(IDirectInputDevice8W,IDirectInputDevice7W) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputDeviceW methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS lpDIDevCaps) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID rguidProp, LPDIPROPHEADER pdiph) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID rguidProp, LPCDIPROPHEADER pdiph) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD cbData, LPVOID lpvData) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT lpdf) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE hEvent) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwFlags) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW pdidi) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) PURE; + /*** IDirectInputDevice2W methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdeff, LPUNKNOWN punkOuter) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwEffType) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW pdei, REFGUID rguid) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD pdwOut) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD dwFlags) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE pesc) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) PURE; + /*** IDirectInputDevice7W methods ***/ + STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR lpszFileName,LPDIENUMEFFECTSINFILECALLBACK pec,LPVOID pvRef,DWORD dwFlags) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR lpszFileName,DWORD dwEntries,LPDIFILEEFFECT rgDiFileEft,DWORD dwFlags) PURE; + /*** IDirectInputDevice8W methods ***/ + STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags) PURE; + STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags) PURE; + STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInputDevice8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice8_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice8_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice8_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice8_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice8_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice8_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice8_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice8_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice8_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice8_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice8_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice8_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice8_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice8_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice8_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice8_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice8_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +/*** IDirectInputDevice2 methods ***/ +#define IDirectInputDevice8_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d) +#define IDirectInputDevice8_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c) +#define IDirectInputDevice8_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b) +#define IDirectInputDevice8_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a) +#define IDirectInputDevice8_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a) +#define IDirectInputDevice8_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c) +#define IDirectInputDevice8_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#define IDirectInputDevice8_Poll(p) (p)->lpVtbl->Poll(p) +#define IDirectInputDevice8_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d) +/*** IDirectInputDevice7 methods ***/ +#define IDirectInputDevice8_EnumEffectsInFile(p,a,b,c,d) (p)->lpVtbl->EnumEffectsInFile(p,a,b,c,d) +#define IDirectInputDevice8_WriteEffectToFile(p,a,b,c,d) (p)->lpVtbl->WriteEffectToFile(p,a,b,c,d) +/*** IDirectInputDevice8 methods ***/ +#define IDirectInputDevice8_BuildActionMap(p,a,b,c) (p)->lpVtbl->BuildActionMap(p,a,b,c) +#define IDirectInputDevice8_SetActionMap(p,a,b,c) (p)->lpVtbl->SetActionMap(p,a,b,c) +#define IDirectInputDevice8_GetImageInfo(p,a) (p)->lpVtbl->GetImageInfo(p,a) +#else +/*** IUnknown methods ***/ +#define IDirectInputDevice8_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice8_AddRef(p) (p)->AddRef() +#define IDirectInputDevice8_Release(p) (p)->Release() +/*** IDirectInputDevice methods ***/ +#define IDirectInputDevice8_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice8_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice8_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice8_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice8_Acquire(p) (p)->Acquire() +#define IDirectInputDevice8_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice8_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice8_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice8_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice8_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice8_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice8_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice8_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice8_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice8_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +/*** IDirectInputDevice2 methods ***/ +#define IDirectInputDevice8_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d) +#define IDirectInputDevice8_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c) +#define IDirectInputDevice8_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b) +#define IDirectInputDevice8_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a) +#define IDirectInputDevice8_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a) +#define IDirectInputDevice8_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c) +#define IDirectInputDevice8_Escape(p,a) (p)->Escape(a) +#define IDirectInputDevice8_Poll(p) (p)->Poll() +#define IDirectInputDevice8_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d) +/*** IDirectInputDevice7 methods ***/ +#define IDirectInputDevice8_EnumEffectsInFile(p,a,b,c,d) (p)->EnumEffectsInFile(a,b,c,d) +#define IDirectInputDevice8_WriteEffectToFile(p,a,b,c,d) (p)->WriteEffectToFile(a,b,c,d) +/*** IDirectInputDevice8 methods ***/ +#define IDirectInputDevice8_BuildActionMap(p,a,b,c) (p)->BuildActionMap(a,b,c) +#define IDirectInputDevice8_SetActionMap(p,a,b,c) (p)->SetActionMap(a,b,c) +#define IDirectInputDevice8_GetImageInfo(p,a) (p)->GetImageInfo(a) +#endif + +#endif /* DI8 */ + +/* "Standard" Mouse report... */ +typedef struct DIMOUSESTATE { + LONG lX; + LONG lY; + LONG lZ; + BYTE rgbButtons[4]; +} DIMOUSESTATE; + +#if DIRECTINPUT_VERSION >= 0x0700 +/* "Standard" Mouse report for DInput 7... */ +typedef struct DIMOUSESTATE2 { + LONG lX; + LONG lY; + LONG lZ; + BYTE rgbButtons[8]; +} DIMOUSESTATE2; +#endif /* DI7 */ + +#define DIMOFS_X FIELD_OFFSET(DIMOUSESTATE, lX) +#define DIMOFS_Y FIELD_OFFSET(DIMOUSESTATE, lY) +#define DIMOFS_Z FIELD_OFFSET(DIMOUSESTATE, lZ) +#define DIMOFS_BUTTON0 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 0) +#define DIMOFS_BUTTON1 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 1) +#define DIMOFS_BUTTON2 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 2) +#define DIMOFS_BUTTON3 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 3) +#if DIRECTINPUT_VERSION >= 0x0700 +#define DIMOFS_BUTTON4 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 4) +#define DIMOFS_BUTTON5 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 5) +#define DIMOFS_BUTTON6 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 6) +#define DIMOFS_BUTTON7 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 7) +#endif /* DI7 */ + +#ifdef __cplusplus +extern "C" { +#endif +extern const DIDATAFORMAT c_dfDIMouse; +#if DIRECTINPUT_VERSION >= 0x0700 +extern const DIDATAFORMAT c_dfDIMouse2; /* DX 7 */ +#endif /* DI7 */ +extern const DIDATAFORMAT c_dfDIKeyboard; +#if DIRECTINPUT_VERSION >= 0x0500 +extern const DIDATAFORMAT c_dfDIJoystick; +extern const DIDATAFORMAT c_dfDIJoystick2; +#endif /* DI5 */ +#ifdef __cplusplus +}; +#endif + +/***************************************************************************** + * IDirectInputA interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputA +DECLARE_INTERFACE_(IDirectInputA,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputA methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICEA *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; +}; + +/***************************************************************************** + * IDirectInputW interface + */ +#undef INTERFACE +#define INTERFACE IDirectInputW +DECLARE_INTERFACE_(IDirectInputW,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputW methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICEW *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInput_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInput methods ***/ +#define IDirectInput_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#else +/*** IUnknown methods ***/ +#define IDirectInput_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput_AddRef(p) (p)->AddRef() +#define IDirectInput_Release(p) (p)->Release() +/*** IDirectInput methods ***/ +#define IDirectInput_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput_Initialize(p,a,b) (p)->Initialize(a,b) +#endif + +/***************************************************************************** + * IDirectInput2A interface + */ +#undef INTERFACE +#define INTERFACE IDirectInput2A +DECLARE_INTERFACE_(IDirectInput2A,IDirectInputA) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputA methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICEA *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; + /*** IDirectInput2A methods ***/ + STDMETHOD(FindDevice)(THIS_ REFGUID rguid, LPCSTR pszName, LPGUID pguidInstance) PURE; +}; + +/***************************************************************************** + * IDirectInput2W interface + */ +#undef INTERFACE +#define INTERFACE IDirectInput2W +DECLARE_INTERFACE_(IDirectInput2W,IDirectInputW) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputW methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICEW *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; + /*** IDirectInput2W methods ***/ + STDMETHOD(FindDevice)(THIS_ REFGUID rguid, LPCWSTR pszName, LPGUID pguidInstance) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInput2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput2_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInput methods ***/ +#define IDirectInput2_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput2_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput2_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput2_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput2_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +/*** IDirectInput2 methods ***/ +#define IDirectInput2_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c) +#else +/*** IUnknown methods ***/ +#define IDirectInput2_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput2_AddRef(p) (p)->AddRef() +#define IDirectInput2_Release(p) (p)->Release() +/*** IDirectInput methods ***/ +#define IDirectInput2_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput2_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput2_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput2_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput2_Initialize(p,a,b) (p)->Initialize(a,b) +/*** IDirectInput2 methods ***/ +#define IDirectInput2_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c) +#endif + +/***************************************************************************** + * IDirectInput7A interface + */ +#undef INTERFACE +#define INTERFACE IDirectInput7A +DECLARE_INTERFACE_(IDirectInput7A,IDirectInput2A) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputA methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICEA *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; + /*** IDirectInput2A methods ***/ + STDMETHOD(FindDevice)(THIS_ REFGUID rguid, LPCSTR pszName, LPGUID pguidInstance) PURE; + /*** IDirectInput7A methods ***/ + STDMETHOD(CreateDeviceEx)(THIS_ REFGUID rguid, REFIID riid, LPVOID *pvOut, LPUNKNOWN lpUnknownOuter) PURE; +}; + +/***************************************************************************** + * IDirectInput7W interface + */ +#undef INTERFACE +#define INTERFACE IDirectInput7W +DECLARE_INTERFACE_(IDirectInput7W,IDirectInput2W) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInputW methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICEW *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; + /*** IDirectInput2W methods ***/ + STDMETHOD(FindDevice)(THIS_ REFGUID rguid, LPCWSTR pszName, LPGUID pguidInstance) PURE; + /*** IDirectInput7W methods ***/ + STDMETHOD(CreateDeviceEx)(THIS_ REFGUID rguid, REFIID riid, LPVOID *pvOut, LPUNKNOWN lpUnknownOuter) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInput7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput7_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput7_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInput methods ***/ +#define IDirectInput7_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput7_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput7_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput7_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput7_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +/*** IDirectInput2 methods ***/ +#define IDirectInput7_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c) +/*** IDirectInput7 methods ***/ +#define IDirectInput7_CreateDeviceEx(p,a,b,c,d) (p)->lpVtbl->CreateDeviceEx(p,a,b,c,d) +#else +/*** IUnknown methods ***/ +#define IDirectInput7_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput7_AddRef(p) (p)->AddRef() +#define IDirectInput7_Release(p) (p)->Release() +/*** IDirectInput methods ***/ +#define IDirectInput7_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput7_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput7_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput7_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput7_Initialize(p,a,b) (p)->Initialize(a,b) +/*** IDirectInput2 methods ***/ +#define IDirectInput7_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c) +/*** IDirectInput7 methods ***/ +#define IDirectInput7_CreateDeviceEx(p,a,b,c,d) (p)->CreateDeviceEx(a,b,c,d) +#endif + + +#if DIRECTINPUT_VERSION >= 0x0800 +/***************************************************************************** + * IDirectInput8A interface + */ +#undef INTERFACE +#define INTERFACE IDirectInput8A +DECLARE_INTERFACE_(IDirectInput8A,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInput8A methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICE8A *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; + STDMETHOD(FindDevice)(THIS_ REFGUID rguid, LPCSTR pszName, LPGUID pguidInstance) PURE; + STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat, LPDIENUMDEVICESBYSEMANTICSCBA lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSA lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) PURE; +}; + +/***************************************************************************** + * IDirectInput8W interface + */ +#undef INTERFACE +#define INTERFACE IDirectInput8W +DECLARE_INTERFACE_(IDirectInput8W,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IDirectInput8W methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID rguid, LPDIRECTINPUTDEVICE8W *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID rguidInstance) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND hwndOwner, DWORD dwFlags) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE; + STDMETHOD(FindDevice)(THIS_ REFGUID rguid, LPCWSTR pszName, LPGUID pguidInstance) PURE; + STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCWSTR ptszUserName, LPDIACTIONFORMATW lpdiActionFormat, LPDIENUMDEVICESBYSEMANTICSCBW lpCallback, LPVOID pvRef, DWORD dwFlags) PURE; + STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) PURE; +}; +#undef INTERFACE + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IDirectInput8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput8_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput8_Release(p) (p)->lpVtbl->Release(p) +/*** IDirectInput8 methods ***/ +#define IDirectInput8_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput8_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput8_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput8_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput8_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectInput8_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c) +#define IDirectInput8_EnumDevicesBySemantics(p,a,b,c,d,e) (p)->lpVtbl->EnumDevicesBySemantics(p,a,b,c,d,e) +#define IDirectInput8_ConfigureDevices(p,a,b,c,d) (p)->lpVtbl->ConfigureDevices(p,a,b,c,d) +#else +/*** IUnknown methods ***/ +#define IDirectInput8_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput8_AddRef(p) (p)->AddRef() +#define IDirectInput8_Release(p) (p)->Release() +/*** IDirectInput8 methods ***/ +#define IDirectInput8_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput8_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput8_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput8_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput8_Initialize(p,a,b) (p)->Initialize(a,b) +#define IDirectInput8_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c) +#define IDirectInput8_EnumDevicesBySemantics(p,a,b,c,d,e) (p)->EnumDevicesBySemantics(a,b,c,d,e) +#define IDirectInput8_ConfigureDevices(p,a,b,c,d) (p)->ConfigureDevices(a,b,c,d) +#endif + +#endif /* DI8 */ + +/* Export functions */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if DIRECTINPUT_VERSION >= 0x0800 +HRESULT WINAPI DirectInput8Create(HINSTANCE,DWORD,REFIID,LPVOID *,LPUNKNOWN); +#else /* DI < 8 */ +HRESULT WINAPI DirectInputCreateA(HINSTANCE,DWORD,LPDIRECTINPUTA *,LPUNKNOWN); +HRESULT WINAPI DirectInputCreateW(HINSTANCE,DWORD,LPDIRECTINPUTW *,LPUNKNOWN); +#define DirectInputCreate WINELIB_NAME_AW(DirectInputCreate) + +HRESULT WINAPI DirectInputCreateEx(HINSTANCE,DWORD,REFIID,LPVOID *,LPUNKNOWN); +#endif /* DI8 */ + +#ifdef __cplusplus +}; +#endif + +#endif /* __DINPUT_INCLUDED__ */ diff --git a/deps/mingw/xinput.h b/deps/mingw/xinput.h new file mode 100644 index 000000000..d3ca726ce --- /dev/null +++ b/deps/mingw/xinput.h @@ -0,0 +1,239 @@ +/* + * The Wine project - Xinput Joystick Library + * Copyright 2008 Andrew Fenn + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_XINPUT_H +#define __WINE_XINPUT_H + +#include + +/* + * Bitmasks for the joysticks buttons, determines what has + * been pressed on the joystick, these need to be mapped + * to whatever device you're using instead of an xbox 360 + * joystick + */ + +#define XINPUT_GAMEPAD_DPAD_UP 0x0001 +#define XINPUT_GAMEPAD_DPAD_DOWN 0x0002 +#define XINPUT_GAMEPAD_DPAD_LEFT 0x0004 +#define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008 +#define XINPUT_GAMEPAD_START 0x0010 +#define XINPUT_GAMEPAD_BACK 0x0020 +#define XINPUT_GAMEPAD_LEFT_THUMB 0x0040 +#define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080 +#define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100 +#define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200 +#define XINPUT_GAMEPAD_A 0x1000 +#define XINPUT_GAMEPAD_B 0x2000 +#define XINPUT_GAMEPAD_X 0x4000 +#define XINPUT_GAMEPAD_Y 0x8000 + +/* + * Defines the flags used to determine if the user is pushing + * down on a button, not holding a button, etc + */ + +#define XINPUT_KEYSTROKE_KEYDOWN 0x0001 +#define XINPUT_KEYSTROKE_KEYUP 0x0002 +#define XINPUT_KEYSTROKE_REPEAT 0x0004 + +/* + * Defines the codes which are returned by XInputGetKeystroke + */ + +#define VK_PAD_A 0x5800 +#define VK_PAD_B 0x5801 +#define VK_PAD_X 0x5802 +#define VK_PAD_Y 0x5803 +#define VK_PAD_RSHOULDER 0x5804 +#define VK_PAD_LSHOULDER 0x5805 +#define VK_PAD_LTRIGGER 0x5806 +#define VK_PAD_RTRIGGER 0x5807 +#define VK_PAD_DPAD_UP 0x5810 +#define VK_PAD_DPAD_DOWN 0x5811 +#define VK_PAD_DPAD_LEFT 0x5812 +#define VK_PAD_DPAD_RIGHT 0x5813 +#define VK_PAD_START 0x5814 +#define VK_PAD_BACK 0x5815 +#define VK_PAD_LTHUMB_PRESS 0x5816 +#define VK_PAD_RTHUMB_PRESS 0x5817 +#define VK_PAD_LTHUMB_UP 0x5820 +#define VK_PAD_LTHUMB_DOWN 0x5821 +#define VK_PAD_LTHUMB_RIGHT 0x5822 +#define VK_PAD_LTHUMB_LEFT 0x5823 +#define VK_PAD_LTHUMB_UPLEFT 0x5824 +#define VK_PAD_LTHUMB_UPRIGHT 0x5825 +#define VK_PAD_LTHUMB_DOWNRIGHT 0x5826 +#define VK_PAD_LTHUMB_DOWNLEFT 0x5827 +#define VK_PAD_RTHUMB_UP 0x5830 +#define VK_PAD_RTHUMB_DOWN 0x5831 +#define VK_PAD_RTHUMB_RIGHT 0x5832 +#define VK_PAD_RTHUMB_LEFT 0x5833 +#define VK_PAD_RTHUMB_UPLEFT 0x5834 +#define VK_PAD_RTHUMB_UPRIGHT 0x5835 +#define VK_PAD_RTHUMB_DOWNRIGHT 0x5836 +#define VK_PAD_RTHUMB_DOWNLEFT 0x5837 + +/* + * Deadzones are for analogue joystick controls on the joypad + * which determine when input should be assumed to be in the + * middle of the pad. This is a threshold to stop a joypad + * controlling the game when the player isn't touching the + * controls. + */ + +#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849 +#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689 +#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30 + + +/* + * Defines what type of abilities the type of joystick has + * DEVTYPE_GAMEPAD is available for all joysticks, however + * there may be more specific identifiers for other joysticks + * which are being used. + */ + +#define XINPUT_DEVTYPE_GAMEPAD 0x01 +#define XINPUT_DEVSUBTYPE_GAMEPAD 0x01 +#define XINPUT_DEVSUBTYPE_WHEEL 0x02 +#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03 +#define XINPUT_DEVSUBTYPE_FLIGHT_SICK 0x04 +#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05 +#define XINPUT_DEVSUBTYPE_GUITAR 0x06 +#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08 + +/* + * These are used with the XInputGetCapabilities function to + * determine the abilities to the joystick which has been + * plugged in. + */ + +#define XINPUT_CAPS_VOICE_SUPPORTED 0x0004 +#define XINPUT_FLAG_GAMEPAD 0x00000001 + +/* + * Defines the status of the battery if one is used in the + * attached joystick. The first two define if the joystick + * supports a battery. Disconnected means that the joystick + * isn't connected. Wired shows that the joystick is a wired + * joystick. + */ + +#define BATTERY_DEVTYPE_GAMEPAD 0x00 +#define BATTERY_DEVTYPE_HEADSET 0x01 +#define BATTERY_TYPE_DISCONNECTED 0x00 +#define BATTERY_TYPE_WIRED 0x01 +#define BATTERY_TYPE_ALKALINE 0x02 +#define BATTERY_TYPE_NIMH 0x03 +#define BATTERY_TYPE_UNKNOWN 0xFF +#define BATTERY_LEVEL_EMPTY 0x00 +#define BATTERY_LEVEL_LOW 0x01 +#define BATTERY_LEVEL_MEDIUM 0x02 +#define BATTERY_LEVEL_FULL 0x03 + +/* + * How many joysticks can be used with this library. Games that + * use the xinput library will not go over this number. + */ + +#define XUSER_MAX_COUNT 4 +#define XUSER_INDEX_ANY 0x000000FF + +/* + * Defines the structure of an xbox 360 joystick. + */ + +typedef struct _XINPUT_GAMEPAD { + WORD wButtons; + BYTE bLeftTrigger; + BYTE bRightTrigger; + SHORT sThumbLX; + SHORT sThumbLY; + SHORT sThumbRX; + SHORT sThumbRY; +} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD; + +typedef struct _XINPUT_STATE { + DWORD dwPacketNumber; + XINPUT_GAMEPAD Gamepad; +} XINPUT_STATE, *PXINPUT_STATE; + +/* + * Defines the structure of how much vibration is set on both the + * right and left motors in a joystick. If you're not using a 360 + * joystick you will have to map these to your device. + */ + +typedef struct _XINPUT_VIBRATION { + WORD wLeftMotorSpeed; + WORD wRightMotorSpeed; +} XINPUT_VIBRATION, *PXINPUT_VIBRATION; + +/* + * Defines the structure for what kind of abilities the joystick has + * such abilities are things such as if the joystick has the ability + * to send and receive audio, if the joystick is in fact a driving + * wheel or perhaps if the joystick is some kind of dance pad or + * guitar. + */ + +typedef struct _XINPUT_CAPABILITIES { + BYTE Type; + BYTE SubType; + WORD Flags; + XINPUT_GAMEPAD Gamepad; + XINPUT_VIBRATION Vibration; +} XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES; + +/* + * Defines the structure for a joystick input event which is + * retrieved using the function XInputGetKeystroke + */ +typedef struct _XINPUT_KEYSTROKE { + WORD VirtualKey; + WCHAR Unicode; + WORD Flags; + BYTE UserIndex; + BYTE HidCode; +} XINPUT_KEYSTROKE, *PXINPUT_KEYSTROKE; + +typedef struct _XINPUT_BATTERY_INFORMATION +{ + BYTE BatteryType; + BYTE BatteryLevel; +} XINPUT_BATTERY_INFORMATION, *PXINPUT_BATTERY_INFORMATION; + +#ifdef __cplusplus +extern "C" { +#endif + +void WINAPI XInputEnable(WINBOOL); +DWORD WINAPI XInputSetState(DWORD, XINPUT_VIBRATION*); +DWORD WINAPI XInputGetState(DWORD, XINPUT_STATE*); +DWORD WINAPI XInputGetKeystroke(DWORD, DWORD, PXINPUT_KEYSTROKE); +DWORD WINAPI XInputGetCapabilities(DWORD, DWORD, XINPUT_CAPABILITIES*); +DWORD WINAPI XInputGetDSoundAudioDeviceGuids(DWORD, GUID*, GUID*); +DWORD WINAPI XInputGetBatteryInformation(DWORD, BYTE, XINPUT_BATTERY_INFORMATION*); + +#ifdef __cplusplus +} +#endif + +#endif /* __WINE_XINPUT_H */ diff --git a/deps/tinycthread.c b/deps/tinycthread.c index 5d4018de7..ddb86d99b 100644 --- a/deps/tinycthread.c +++ b/deps/tinycthread.c @@ -21,7 +21,7 @@ freely, subject to the following restrictions: distribution. */ -/* 2013-01-06 Camilla Berglund +/* 2013-01-06 Camilla Berglund * * Added casts from time_t to DWORD to avoid warnings on VC++. * Fixed time retrieval on POSIX systems. diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 063aa48a4..c030ac735 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -14,7 +14,6 @@ set(glfw_DOCS_SOURCES "${GLFW_SOURCE_DIR}/docs/window.dox" "${GLFW_SOURCE_DIR}/docs/input.dox" "${GLFW_SOURCE_DIR}/docs/vulkan.dox" - "${GLFW_SOURCE_DIR}/docs/rift.dox" "${GLFW_SOURCE_DIR}/docs/compat.dox") if (GLFW_DOCUMENT_INTERNALS) diff --git a/docs/build.dox b/docs/build.dox index fde65add1..c489acf25 100644 --- a/docs/build.dox +++ b/docs/build.dox @@ -103,7 +103,8 @@ 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 @@ -153,7 +154,7 @@ uses OpenGL and `glu32` if it uses GLU. This section is about using CMake to compile and link GLFW along with your application. If you want to use an installed binary instead, see @ref -build_link_cmake_module. +build_link_cmake_package. With just a few changes to your `CMakeLists.txt` you can have the GLFW source tree built along with your application. @@ -184,59 +185,78 @@ the include directory for the GLFW header and, when applicable, the 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. -@subsection build_link_cmake_module With CMake and installed GLFW binaries + +@subsection build_link_cmake_package With CMake and installed GLFW binaries This section is about using CMake to link GLFW after it has been built and installed. If you want to build it along with your application instead, see @ref build_link_cmake_source. -With just a few changes to your `CMakeLists.txt`, you can locate the module and +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. - -@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. + @subsection build_link_pkgconfig With makefiles and pkg-config on Unix @@ -268,15 +288,19 @@ 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 OS X, 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 module. +`glu` pkg-config package. @code{.sh} 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. + If you are using the static version of the GLFW library, make sure you don't link statically against GLU. diff --git a/docs/compat.dox b/docs/compat.dox index ee10770f5..175036b91 100644 --- a/docs/compat.dox +++ b/docs/compat.dox @@ -185,7 +185,7 @@ 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. +GLFW uses the standard system-wide 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. diff --git a/docs/compile.dox b/docs/compile.dox index adadf7793..c77a26c0e 100644 --- a/docs/compile.dox +++ b/docs/compile.dox @@ -197,6 +197,9 @@ built along with the library. `GLFW_BUILD_DOCS` determines whether the GLFW documentation is built along with the library. +`GLFW_VULKAN_STATIC` determines whether to use the Vulkan loader linked +statically into the application. + @subsubsection compile_options_osx OS X specific CMake options @@ -214,9 +217,7 @@ Retina displays. `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 `AmdPowerXpressRequestHighPerformance` symbols, which force the use of the @@ -251,6 +252,10 @@ ramps and clipboard. The options are: 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. +If you are linking the Vulkan loader statically into your application then you +must also define `_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 diff --git a/docs/context.dox b/docs/context.dox index 7cc1f120c..ad3b1848a 100644 --- a/docs/context.dox +++ b/docs/context.dox @@ -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 diff --git a/docs/input.dox b/docs/input.dox index 7ac3f2292..1a06e62a5 100644 --- a/docs/input.dox +++ b/docs/input.dox @@ -5,12 +5,13 @@ @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 diff --git a/docs/internal.dox b/docs/internal.dox index 593ad67d3..3eb0aee56 100644 --- a/docs/internal.dox +++ b/docs/internal.dox @@ -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_GLXGETPROCADDRESS` +Examples: `_GLFW_HAS_XF86VM` */ diff --git a/docs/intro.dox b/docs/intro.dox index 6f0a22919..f78408004 100644 --- a/docs/intro.dox +++ b/docs/intro.dox @@ -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. @@ -34,8 +34,8 @@ successfully initialized, and only from the main thread. - @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 +50,15 @@ 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 intro_init_terminate Terminating GLFW @@ -70,7 +72,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 @@ -249,11 +251,12 @@ functions may be called from any thread: - @ref glfwGetTimerFrequency - @ref glfwGetTimerValue -The regular timer may be queried from any thread, but this is not synchronized -by GLFW with calls to @ref glfwSetTime. The following timer related functions -may be called from any thread: +The regular timer may be used from any thread, but the reading and writing of +the timer offset is not synchronized by GLFW. The following timer related +functions may be called from any thread: - @ref glfwGetTime + - @ref glfwSetTime Library version information may be queried from any thread. The following version related functions may be called from any thread: @@ -281,9 +284,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 diff --git a/docs/main.dox b/docs/main.dox index 9f9ef7977..fc95cc4eb 100644 --- a/docs/main.dox +++ b/docs/main.dox @@ -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 release 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 @@ -34,8 +34,6 @@ use the new API. There is a section on @ref guarantees_limitations for pointer lifetimes, reentrancy, thread safety, event order and backward and forward compatibility. -@ref rift_guide fills in the gaps for how to use LibOVR with GLFW. - The [FAQ](http://www.glfw.org/faq.html) answers many common questions about the design, implementation and use of GLFW. diff --git a/docs/monitor.dox b/docs/monitor.dox index 53e88aac4..0aa0b0505 100644 --- a/docs/monitor.dox +++ b/docs/monitor.dox @@ -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 @@ -84,6 +85,9 @@ void monitor_callback(GLFWmonitor* monitor, int event) } @endcode +If a monitor is disconnected, any windows that are full screen on it get forced +into windowed mode. + @section monitor_properties Monitor properties diff --git a/docs/news.dox b/docs/news.dox index e0fb5f80c..619331ea9 100644 --- a/docs/news.dox +++ b/docs/news.dox @@ -2,21 +2,12 @@ @page news New features +@section news_33 New features in 3.3 + + @section news_32 New features in 3.2 -@subsection news_32_sizelimits Window size limit support - -GLFW now supports setting both absolute and relative window size limits with -@ref glfwSetWindowSizeLimits and @ref glfwSetWindowAspectRatio. - - -@subsection news_32_keyname Localized key names - -GLFW now supports querying the localized name of printable keys with @ref -glfwGetKeyName, either by key token or by scancode. - - @subsection news_32_vulkan Support for Vulkan GLFW now supports basic integration with Vulkan with @ref glfwVulkanSupported, @@ -39,20 +30,21 @@ GLFW now supports window maximization with @ref glfwMaximizeWindow and the [GLFW_MAXIMIZED](@ref window_attribs_wnd) window hint and attribute. -@subsection news_32_icon Window icon support - -GLFW now supports setting the icon of windows with @ref glfwSetWindowIcon. - - @subsection news_32_focus Window input focus control GLFW now supports giving windows input focus with @ref glfwFocusWindow. -@subsection news_32_timer Raw timer access +@subsection news_32_sizelimits Window size limit support -GLFW now supports raw timer values with @ref glfwGetTimerValue and @ref -glfwGetTimerFrequency. +GLFW now supports setting both absolute and relative window size limits with +@ref glfwSetWindowSizeLimits and @ref glfwSetWindowAspectRatio. + + +@subsection news_32_keyname Localized key names + +GLFW now supports querying the localized name of printable keys with @ref +glfwGetKeyName, either by key token or by scancode. @subsection news_32_waittimeout Wait for events with timeout @@ -61,10 +53,47 @@ GLFW now supports waiting for events for a set amount of time with @ref glfwWaitEventsTimeout. +@subsection news_32_icon Window icon support + +GLFW now supports setting the icon of windows with @ref glfwSetWindowIcon. + + +@subsection news_32_timer Raw timer access + +GLFW now supports raw timer values with @ref glfwGetTimerValue and @ref +glfwGetTimerFrequency. + + +@subsection news_32_joystick Joystick connection callback + +GLFW now supports notifying when a joystick has been connected or disconnected +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). + + @subsection news_32_contextapi Run-time context creation API selection -GLFW now supports selecting the context creation API at run-time with -[GLFW_CONTEXT_CREATION_API](@ref window_hints_ctx). +GLFW now supports selecting the context creation API at run-time with the +[GLFW_CONTEXT_CREATION_API](@ref window_hints_ctx) window hint value. + + +@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. + + +@subsection news_32_cmake CMake config-file package support + +GLFW now supports being used as a +[config-file package](@ref build_link_cmake_package) from other projects for +easy linking with the library and its dependencies. @section news_31 New features in 3.1 @@ -134,13 +163,6 @@ GLFW now queries the window input focus, visibility and iconification attributes and the cursor position directly instead of returning cached data. -@subsection news_31_libovr Better interoperability with Oculus Rift - -GLFW now provides native access functions for the OS level handles corresponding -to monitor objects, as well as the @ref rift_guide. It is also regularly -tested for compatibility with the latest version of LibOVR (0.4.4 on release). - - @subsection news_31_charmods Character with modifiers callback GLFW now provides a callback for character events with modifier key bits. The @@ -326,7 +348,7 @@ 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 +Windowed mode windows can now be created without decorations, e.g. things like a frame, a title bar, with the `GLFW_DECORATED` window hint. This allows for the creation of things like splash screens. diff --git a/docs/rift.dox b/docs/rift.dox deleted file mode 100644 index 2de395fc8..000000000 --- a/docs/rift.dox +++ /dev/null @@ -1,199 +0,0 @@ -/*! - -@page rift_guide Using GLFW with LibOVR - -@tableofcontents - -This guide is intended to fill in the gaps between the -[Oculus PC SDK documentation](https://developer.oculus.com/documentation/) and -the rest of the GLFW documentation and is not a replacement for either. It -requires you to use [native access](@ref native) and assumes a certain level of -proficiency with LibOVR, platform specific APIs and your chosen development -environment. - -While GLFW has no explicit support for LibOVR, it is tested with and tries to -interoperate well with it. - -@note Because of the speed of development of the Oculus SDK, this guide may -become outdated before the next release. If this is a local copy of the -documentation, you may want to check the GLFW website for updates. This -revision of the guide is written against version 0.4.4 of the SDK. - - -@section rift_include Including the LibOVR and GLFW header files - -Both the OpenGL LibOVR header and the GLFW native header need macros telling -them what OS you are building for. Because LibOVR only supports three major -desktop platforms, this can be solved with canonical predefined macros. - -@code -#if defined(_WIN32) - #define GLFW_EXPOSE_NATIVE_WIN32 - #define GLFW_EXPOSE_NATIVE_WGL - #define OVR_OS_WIN32 -#elif defined(__APPLE__) - #define GLFW_EXPOSE_NATIVE_COCOA - #define GLFW_EXPOSE_NATIVE_NSGL - #define OVR_OS_MAC -#elif defined(__linux__) - #define GLFW_EXPOSE_NATIVE_X11 - #define GLFW_EXPOSE_NATIVE_GLX - #define OVR_OS_LINUX -#endif - -#include -#include - -#include -@endcode - -Both the GLFW and LibOVR headers by default attempt to include the standard -OpenGL `GL/gl.h` header (`OpenGL/gl.h` on OS X). If you wish to use a different -standard header or an [extension loading library](@ref context_glext_auto), -include that header before these. - - -@section rift_init Initializing LibOVR and GLFW - -LibOVR needs to be initialized before GLFW. This means calling at least -`ovr_Initialize`, `ovrHmd_Create` and `ovrHmd_ConfigureTracking` before @ref -glfwInit. Similarly, LibOVR must be shut down after GLFW. This means calling -`ovrHmd_Destroy` and `ovr_Shutdown` after @ref glfwTerminate. - - -@section rift_direct Direct HMD mode - -Direct HMD mode is the recommended display mode for new applications, but the -Oculus Rift runtime currently (January 2015) only supports this mode on Windows. -In direct mode the HMD is not detectable as a GLFW monitor. - - -@subsection rift_direct_create Creating a window and context - -If the HMD is in direct mode you can use either a full screen or a windowed mode -window, but full screen is only recommended if there is a monitor that supports -the resolution of the HMD. Due to limitations in LibOVR, the size of the client -area of the window must equal the resolution of the HMD. - -If the resolution of the HMD is much larger than the regular monitor, the window -may be resized by the window manager on creation. One way to avoid this is to -make it undecorated with the [GLFW_DECORATED](@ref window_hints_wnd) window -hint. - - -@subsection rift_direct_attach Attaching the window to the HMD - -Once you have created the window and context, you need to attach the native -handle of the GLFW window to the HMD. - -@code -ovrHmd_AttachToWindow(hmd, glfwGetWin32Window(window), NULL, NULL); -@endcode - - -@section rift_extend Extend Desktop mode - -Extend desktop mode is a legacy display mode, but is still (January 2015) the -only available mode on OS X and Linux, as well as on Windows machines that for -technical reasons do not yet support direct HMD mode. - - -@subsection rift_extend_detect Detecting a HMD with GLFW - -If the HMD is in extend desktop mode you can deduce which GLFW monitor it -corresponds to and create a full screen window on that monitor. - -On Windows, the native display device name of a GLFW monitor corresponds to the -display device name of the detected HMD as stored, in the `DisplayDeviceName` -member of `ovrHmdDesc`. - -On OS X, the native display ID of a GLFW monitor corresponds to the display ID -of the detected HMD, as stored in the `DisplayId` member of `ovrHmdDesc`. - -At the time of writing (January 2015), the Oculus SDK does not support detecting -which monitor corresponds to the HMD in any sane fashion, but as long as the HMD -is set up and rotated properly it can be found via the screen position and -resolution provided by LibOVR. This method may instead find another monitor -that is mirroring the HMD, but this only matters if you intend to change its -video mode. - -@code -int i, count; -GLFWmonitor** monitors = glfwGetMonitors(&count); - -for (i = 0; i < count; i++) -{ -#if defined(_WIN32) - if (strcmp(glfwGetWin32Monitor(monitors[i]), hmd->DisplayDeviceName) == 0) - return monitors[i]; -#elif defined(__APPLE__) - if (glfwGetCocoaMonitor(monitors[i]) == hmd->DisplayId) - return monitors[i]; -#elif defined(__linux__) - int xpos, ypos; - const GLFWvidmode* mode = glfwGetVideoMode(monitors[i]); - glfwGetMonitorPos(monitors[i], &xpos, &ypos); - - if (hmd->WindowsPos.x == xpos && - hmd->WindowsPos.y == ypos && - hmd->Resolution.w == mode->width && - hmd->Resolution.h == mode->height) - { - return monitors[i]; - } -#endif -} -@endcode - - -@subsection rift_extend_create Creating a window and context - -The window is created as a regular full screen window on the found monitor. It -is usually a good idea to create a -[windowed full screen](@ref window_windowed_full_screen) window, as the HMD will -very likely already be set to the correct video mode. However, in extend -desktop mode it behaves like a regular monitor and any supported video mode can -be requested. - -If other monitors are mirroring the HMD and you request a different video mode, -all monitors in the mirroring set will get the new video mode. - - -@section rift_render Rendering to the HMD - -@subsection rift_render_sdk SDK distortion rendering - -If you wish to use SDK distortion rendering you will need some information from -GLFW to configure the renderer. Below are the parts of the `ovrGLConfig` union -that need to be filled with from GLFW. Note that there are other fields that -also need to be filled for `ovrHmd_ConfigureRendering` to succeed. - -Before configuring SDK distortion rendering you should make your context -current. - -@code - int width, height; - union ovrGLConfig config; - - glfwGetFramebufferSize(window, &width, &height); - - config.OGL.Header.BackBufferSize.w = width; - config.OGL.Header.BackBufferSize.h = height; -#if defined(_WIN32) - config.OGL.Window = glfwGetWin32Window(window); -#elif defined(__APPLE__) -#elif defined(__linux__) - config.OGL.Disp = glfwGetX11Display(); -#endif -@endcode - -When using SDK distortion rendering you should not swap the buffers yourself, as -the HMD is updated by `ovrHmd_EndFrame`. - - -@subsection rift_render_custom Client distortion rendering - -With client distortion rendering you are in full control of the contents of the -HMD and should render and swap the buffers normally. - -*/ diff --git a/docs/vulkan.dox b/docs/vulkan.dox index 988c2b84b..e704222ac 100644 --- a/docs/vulkan.dox +++ b/docs/vulkan.dox @@ -18,9 +18,8 @@ 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. +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 @@ -39,8 +38,8 @@ before including the GLFW header. #include @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 diff --git a/docs/window.dox b/docs/window.dox index b66874bb9..25e2a5eac 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -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 @@ -79,7 +80,8 @@ 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 @@ -268,15 +270,19 @@ 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. +@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. + `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. @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 may still get +__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. @par @@ -285,12 +291,12 @@ 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:__ `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. `GLFW_OPENGL_FORWARD_COMPAT` specifies whether the OpenGL context should be forward-compatible, i.e. one where all functionality deprecated in the requested @@ -645,7 +651,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. diff --git a/examples/particles.c b/examples/particles.c index 023a33e3c..4a65ab124 100644 --- a/examples/particles.c +++ b/examples/particles.c @@ -1,7 +1,7 @@ //======================================================================== // A simple particle engine with threaded physics // Copyright (c) Marcus Geelnard -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -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); } diff --git a/examples/simple.c b/examples/simple.c index c789d1af9..43d11fa92 100644 --- a/examples/simple.c +++ b/examples/simple.c @@ -1,6 +1,6 @@ //======================================================================== // Simple GLFW example -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index ed7f11a6d..36c8552c7 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -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-2010 Camilla Berglund + * Copyright (c) 2006-2016 Camilla Berglund * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -115,11 +115,14 @@ extern "C" { #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most Windows GLU headers need wchar_t. - * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. +/* Include because most Windows GLU headers need wchar_t and + * the OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. * Include it unconditionally to avoid surprising side-effects. */ #include + +/* Include because it is needed by Vulkan and related functions. + */ #include /* Include the chosen client API headers. @@ -219,7 +222,7 @@ extern "C" { * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 2 +#define GLFW_VERSION_MINOR 3 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -1183,6 +1186,7 @@ typedef struct GLFWgammaramp /*! @brief Image data. * * @sa @ref cursor_custom + * @sa @ref window_icon * * @since Added in version 2.1. * @glfw3 Removed format and bytes-per-pixel members. @@ -1740,6 +1744,10 @@ GLFWAPI void glfwWindowHint(int hint, int value); * screen windows, including the creation of so called _windowed full screen_ * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * + * Once you have created the window, you can switch it between windowed and + * full screen mode with @ref glfwSetWindowMonitor. If the window has an + * OpenGL or OpenGL ES context, it will be unaffected. + * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it * initially invisible using the [GLFW_VISIBLE](@ref window_hints_wnd) window @@ -1776,9 +1784,10 @@ GLFWAPI void glfwWindowHint(int hint, int value); * @remark @win32 Window creation will fail if the Microsoft GDI software * OpenGL implementation is the only one available. * - * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` - * it will be set as the icon for the window. If no such icon is present, the - * `IDI_WINLOGO` icon will be used instead. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` it + * will be set as the initial icon for the window. If no such icon is present, + * the `IDI_WINLOGO` icon will be used instead. To set a different icon, see + * @ref glfwSetWindowIcon. * * @remark @win32 The context to share resources with must not be current on * any other thread. @@ -1804,8 +1813,6 @@ GLFWAPI void glfwWindowHint(int hint, int value); * a custom `Info.plist` template for this, which can be found as * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remark @x11 There is no mechanism for setting the window icon yet. - * * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * @@ -1947,8 +1954,8 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); * returns. * * @remark @osx The GLFW window has no icon, as it is not a document - * window, but the dock icon will be the same as the application bundle's icon. - * For more information on bundles, see the + * window, so this function does nothing. The dock icon will be the same as + * the application bundle's icon. For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * @@ -2298,6 +2305,9 @@ GLFWAPI void glfwRestoreWindow(GLFWwindow* window); * * @param[in] window The window to maximize. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @par Thread Safety * This function may only be called from the main thread. * @@ -2389,8 +2399,8 @@ GLFWAPI void glfwFocusWindow(GLFWwindow* window); * in full screen on. * * @param[in] window The window to query. - * @return The monitor, or `NULL` if the window is in windowed mode or an error - * occurred. + * @return The monitor, or `NULL` if the window is in windowed mode or an + * [error](@ref error_handling) occurred. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @@ -2435,7 +2445,8 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); * or video mode. * @param[in] height The desired height, in screen coordinates, of the client * area or video mode. - * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode, + * or `GLFW_DONT_CARE`. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * GLFW_PLATFORM_ERROR. @@ -2844,7 +2855,7 @@ GLFWAPI void glfwWaitEventsTimeout(double timeout); /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event - * queue, causing @ref glfwWaitEvents to return. + * queue, causing @ref glfwWaitEvents or @ref glfwWaitEventsTimeout to return. * * If no windows exist, this function returns immediately. For synchronization * of threads in applications that do not create windows, use your threading @@ -2857,6 +2868,7 @@ GLFWAPI void glfwWaitEventsTimeout(double timeout); * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * * @since Added in version 3.1. * @@ -3125,10 +3137,6 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos); * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * GLFW_PLATFORM_ERROR. * - * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for - * the window focus event to arrive. This means you may not be able to set the - * cursor position directly after window creation. - * * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos @@ -3356,7 +3364,7 @@ GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun cbfun); * @param[in] cbfun The new callback, or `NULL` to remove the currently set * callback. * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * [error](@ref error_handling) occurred. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @@ -3535,8 +3543,10 @@ GLFWAPI int glfwJoystickPresent(int joy); * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned - * array. This is set to zero if an error occurred. - * @return An array of axis values, or `NULL` if the joystick is not present. + * array. This is set to zero if the joystick is not present or an error + * occurred. + * @return An array of axis values, or `NULL` if the joystick is not present or + * an [error](@ref error_handling) occurred. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. @@ -3567,8 +3577,10 @@ GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count); * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned - * array. This is set to zero if an error occurred. - * @return An array of button states, or `NULL` if the joystick is not present. + * array. This is set to zero if the joystick is not present or an error + * occurred. + * @return An array of button states, or `NULL` if the joystick is not present + * or an [error](@ref error_handling) occurred. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. @@ -3601,7 +3613,7 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count); * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick - * is not present. + * is not present or an [error](@ref error_handling) occurred. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. @@ -3714,8 +3726,9 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window); * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @thread_safety This function may be called from any thread. Reading of the - * internal timer offset is not atomic. + * @thread_safety This function may be called from any thread. Reading and + * writing of the internal timer offset is not atomic, so it needs to be + * externally synchronized with calls to @ref glfwSetTime. * * @sa @ref time * @@ -3740,8 +3753,9 @@ GLFWAPI double glfwGetTime(void); * floor((264 - 1) / 109) and is due to implementations * storing nanoseconds in 64 bits. The limit may be increased in the future. * - * @thread_safety This function may be called from any thread. Writing of the - * internal timer offset is not atomic. + * @thread_safety This function may be called from any thread. Reading and + * writing of the internal timer offset is not atomic, so it needs to be + * externally synchronized with calls to @ref glfwGetTime. * * @sa @ref time * diff --git a/include/GLFW/glfw3native.h b/include/GLFW/glfw3native.h index 9fa955e94..056bc8292 100644 --- a/include/GLFW/glfw3native.h +++ b/include/GLFW/glfw3native.h @@ -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-2010 Camilla Berglund + * Copyright (c) 2006-2016 Camilla Berglund * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/cocoa_init.m b/src/cocoa_init.m index 9b6434d5b..7c56071c2 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -1,7 +1,7 @@ //======================================================================== -// GLFW 3.2 OS X - www.glfw.org +// GLFW 3.3 OS X - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2009-2010 Camilla Berglund +// Copyright (c) 2009-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -200,6 +200,97 @@ static void createKeyTables(void) } } +// Retrieve Unicode data for the current keyboard layout +// +static GLFWbool updateUnicodeDataNS(void) +{ + if (_glfw.ns.inputSource) + { + CFRelease(_glfw.ns.inputSource); + _glfw.ns.inputSource = NULL; + _glfw.ns.unicodeData = nil; + } + + _glfw.ns.inputSource = TISCopyCurrentKeyboardLayoutInputSource(); + if (!_glfw.ns.inputSource) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Cocoa: Failed to retrieve keyboard layout input source"); + return GLFW_FALSE; + } + + _glfw.ns.unicodeData = TISGetInputSourceProperty(_glfw.ns.inputSource, + kTISPropertyUnicodeKeyLayoutData); + if (!_glfw.ns.unicodeData) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Cocoa: Failed to retrieve keyboard layout Unicode data"); + return GLFW_FALSE; + } + + return GLFW_TRUE; +} + +// Load HIToolbox.framework and the TIS symbols we need from it +// +static GLFWbool initializeTIS(void) +{ + // This works only because Cocoa has already loaded it properly + _glfw.ns.tis.bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox")); + if (!_glfw.ns.tis.bundle) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Cocoa: Failed to load HIToolbox.framework"); + return GLFW_FALSE; + } + + 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")); + _glfw.ns.tis.GetInputSourceProperty = + CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle, + CFSTR("TISGetInputSourceProperty")); + _glfw.ns.tis.GetKbdType = + CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle, + CFSTR("LMGetKbdType")); + + if (!kPropertyUnicodeKeyLayoutData || + !kNotifySelectedKeyboardInputSourceChanged || + !TISCopyCurrentKeyboardLayoutInputSource || + !TISGetInputSourceProperty || + !LMGetKbdType) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Cocoa: Failed to load TIS API symbols"); + return GLFW_FALSE; + } + + _glfw.ns.tis.kPropertyUnicodeKeyLayoutData = + *kPropertyUnicodeKeyLayoutData; + _glfw.ns.tis.kNotifySelectedKeyboardInputSourceChanged = + *kNotifySelectedKeyboardInputSourceChanged; + + return updateUnicodeDataNS(); +} + +@interface GLFWLayoutListener : NSObject +@end + +@implementation GLFWLayoutListener + +- (void)selectedKeyboardInputSourceChanged:(NSObject* )object +{ + updateUnicodeDataNS(); +} + +@end + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// @@ -209,6 +300,13 @@ int _glfwPlatformInit(void) { _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init]; + _glfw.ns.listener = [[GLFWLayoutListener alloc] init]; + [[NSDistributedNotificationCenter defaultCenter] + addObserver:_glfw.ns.listener + selector:@selector(selectedKeyboardInputSourceChanged:) + name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged + object:nil]; + #if defined(_GLFW_USE_CHDIR) changeToResourcesDirectory(); #endif @@ -221,23 +319,12 @@ int _glfwPlatformInit(void) CGEventSourceSetLocalEventsSuppressionInterval(_glfw.ns.eventSource, 0.0); - // TODO: Catch kTISNotifySelectedKeyboardInputSourceChanged and update - - _glfw.ns.inputSource = TISCopyCurrentKeyboardLayoutInputSource(); - if (!_glfw.ns.inputSource) - return GLFW_FALSE; - - _glfw.ns.unicodeData = TISGetInputSourceProperty(_glfw.ns.inputSource, - kTISPropertyUnicodeKeyLayoutData); - if (!_glfw.ns.unicodeData) + if (!initializeTIS()) return GLFW_FALSE; if (!_glfwInitThreadLocalStoragePOSIX()) return GLFW_FALSE; - if (!_glfwInitNSGL()) - return GLFW_FALSE; - _glfwInitTimerNS(); _glfwInitJoysticksNS(); @@ -250,6 +337,7 @@ void _glfwPlatformTerminate(void) { CFRelease(_glfw.ns.inputSource); _glfw.ns.inputSource = NULL; + _glfw.ns.unicodeData = nil; } if (_glfw.ns.eventSource) @@ -265,6 +353,18 @@ void _glfwPlatformTerminate(void) _glfw.ns.delegate = nil; } + if (_glfw.ns.listener) + { + [[NSDistributedNotificationCenter defaultCenter] + removeObserver:_glfw.ns.listener + name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged + object:nil]; + [[NSDistributedNotificationCenter defaultCenter] + removeObserver:_glfw.ns.listener]; + [_glfw.ns.listener release]; + _glfw.ns.listener = nil; + } + [_glfw.ns.cursor release]; _glfw.ns.cursor = nil; diff --git a/src/cocoa_joystick.h b/src/cocoa_joystick.h index 48d82b85b..9a5910153 100644 --- a/src/cocoa_joystick.h +++ b/src/cocoa_joystick.h @@ -1,7 +1,7 @@ //======================================================================== -// GLFW 3.2 Cocoa - www.glfw.org +// GLFW 3.3 Cocoa - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2006-2014 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -32,12 +32,13 @@ #include #include -#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWjoystickNS ns_js +#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \ + _GLFWjoystickNS ns_js[GLFW_JOYSTICK_LAST + 1] // Cocoa-specific per-joystick data // -typedef struct _GLFWjoydeviceNS +typedef struct _GLFWjoystickNS { GLFWbool present; char name[256]; @@ -50,17 +51,9 @@ typedef struct _GLFWjoydeviceNS float* axes; unsigned char* buttons; -} _GLFWjoydeviceNS; - -// Cocoa-specific joystick API data -// -typedef struct _GLFWjoystickNS -{ - _GLFWjoydeviceNS js[GLFW_JOYSTICK_LAST + 1]; - - IOHIDManagerRef managerRef; } _GLFWjoystickNS; + void _glfwInitJoysticksNS(void); void _glfwTerminateJoysticksNS(void); diff --git a/src/cocoa_joystick.m b/src/cocoa_joystick.m index 674004235..439918fd7 100644 --- a/src/cocoa_joystick.m +++ b/src/cocoa_joystick.m @@ -1,7 +1,7 @@ //======================================================================== -// GLFW 3.2 Cocoa - www.glfw.org +// GLFW 3.3 Cocoa - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2009-2010 Camilla Berglund +// Copyright (c) 2009-2016 Camilla Berglund // Copyright (c) 2012 Torsten Walluhn // // This software is provided 'as-is', without any express or implied @@ -57,7 +57,7 @@ static void getElementsCFArrayHandler(const void* value, void* parameter); // Adds an element to the specified joystick // -static void addJoystickElement(_GLFWjoydeviceNS* js, +static void addJoystickElement(_GLFWjoystickNS* js, IOHIDElementRef elementRef) { IOHIDElementType elementType; @@ -126,14 +126,14 @@ static void getElementsCFArrayHandler(const void* value, void* parameter) { if (CFGetTypeID(value) == IOHIDElementGetTypeID()) { - addJoystickElement((_GLFWjoydeviceNS*) parameter, + addJoystickElement((_GLFWjoystickNS*) parameter, (IOHIDElementRef) value); } } // Returns the value of the specified element of the specified joystick // -static long getElementValue(_GLFWjoydeviceNS* js, _GLFWjoyelementNS* element) +static long getElementValue(_GLFWjoystickNS* js, _GLFWjoyelementNS* element) { IOReturn result = kIOReturnSuccess; IOHIDValueRef valueRef; @@ -163,7 +163,7 @@ static long getElementValue(_GLFWjoydeviceNS* js, _GLFWjoyelementNS* element) // Removes the specified joystick // -static void removeJoystick(_GLFWjoydeviceNS* js) +static void removeJoystick(_GLFWjoystickNS* js) { int i; @@ -188,14 +188,14 @@ static void removeJoystick(_GLFWjoydeviceNS* js) free(js->axes); free(js->buttons); - memset(js, 0, sizeof(_GLFWjoydeviceNS)); + memset(js, 0, sizeof(_GLFWjoystickNS)); - _glfwInputJoystickChange(js - _glfw.ns_js.js, GLFW_DISCONNECTED); + _glfwInputJoystickChange(js - _glfw.ns_js, GLFW_DISCONNECTED); } // Polls for joystick axis events and updates GLFW state // -static GLFWbool pollJoystickAxisEvents(_GLFWjoydeviceNS* js) +static GLFWbool pollJoystickAxisEvents(_GLFWjoystickNS* js) { CFIndex i; @@ -221,7 +221,7 @@ static GLFWbool pollJoystickAxisEvents(_GLFWjoydeviceNS* js) // Polls for joystick button events and updates GLFW state // -static GLFWbool pollJoystickButtonEvents(_GLFWjoydeviceNS* js) +static GLFWbool pollJoystickButtonEvents(_GLFWjoystickNS* js) { CFIndex i; int buttonIndex = 0; @@ -271,25 +271,25 @@ static void matchCallback(void* context, void* sender, IOHIDDeviceRef deviceRef) { - _GLFWjoydeviceNS* js; + _GLFWjoystickNS* 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) + if (_glfw.ns_js[joy].present && _glfw.ns_js[joy].deviceRef == deviceRef) return; } for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++) { - if (!_glfw.ns_js.js[joy].present) + if (!_glfw.ns_js[joy].present) break; } if (joy > GLFW_JOYSTICK_LAST) return; - js = _glfw.ns_js.js + joy; + js = _glfw.ns_js + joy; js->present = GLFW_TRUE; js->deviceRef = deviceRef; @@ -338,9 +338,9 @@ static void removeCallback(void* context, for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++) { - if (_glfw.ns_js.js[joy].deviceRef == deviceRef) + if (_glfw.ns_js[joy].deviceRef == deviceRef) { - removeJoystick(_glfw.ns_js.js + joy); + removeJoystick(_glfw.ns_js + joy); break; } } @@ -397,8 +397,8 @@ void _glfwInitJoysticksNS(void) { CFMutableArrayRef matchingCFArrayRef; - _glfw.ns_js.managerRef = IOHIDManagerCreate(kCFAllocatorDefault, - kIOHIDOptionsTypeNone); + _glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault, + kIOHIDOptionsTypeNone); matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, @@ -431,21 +431,21 @@ void _glfwInitJoysticksNS(void) CFRelease(matchingCFDictRef); } - IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns_js.managerRef, + IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager, matchingCFArrayRef); CFRelease(matchingCFArrayRef); } - IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns_js.managerRef, + IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns.hidManager, &matchCallback, NULL); - IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns_js.managerRef, + IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns.hidManager, &removeCallback, NULL); - IOHIDManagerScheduleWithRunLoop(_glfw.ns_js.managerRef, + 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 @@ -460,12 +460,12 @@ void _glfwTerminateJoysticksNS(void) for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++) { - _GLFWjoydeviceNS* js = _glfw.ns_js.js + joy; + _GLFWjoystickNS* js = _glfw.ns_js + joy; removeJoystick(js); } - CFRelease(_glfw.ns_js.managerRef); - _glfw.ns_js.managerRef = NULL; + CFRelease(_glfw.ns.hidManager); + _glfw.ns.hidManager = NULL; } @@ -475,13 +475,13 @@ void _glfwTerminateJoysticksNS(void) int _glfwPlatformJoystickPresent(int joy) { - _GLFWjoydeviceNS* js = _glfw.ns_js.js + joy; + _GLFWjoystickNS* js = _glfw.ns_js + joy; return js->present; } const float* _glfwPlatformGetJoystickAxes(int joy, int* count) { - _GLFWjoydeviceNS* js = _glfw.ns_js.js + joy; + _GLFWjoystickNS* js = _glfw.ns_js + joy; if (!pollJoystickAxisEvents(js)) return NULL; @@ -491,7 +491,7 @@ const float* _glfwPlatformGetJoystickAxes(int joy, int* count) const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count) { - _GLFWjoydeviceNS* js = _glfw.ns_js.js + joy; + _GLFWjoystickNS* js = _glfw.ns_js + joy; if (!pollJoystickButtonEvents(js)) return NULL; @@ -502,7 +502,7 @@ const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count) const char* _glfwPlatformGetJoystickName(int joy) { - _GLFWjoydeviceNS* js = _glfw.ns_js.js + joy; + _GLFWjoystickNS* js = _glfw.ns_js + joy; if (!js->present) return NULL; diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 859f37785..9a384b699 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -1,8 +1,8 @@ //======================================================================== -// GLFW 3.2 OS X - www.glfw.org +// GLFW 3.3 OS X - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard -// Copyright (c) 2006-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -27,11 +27,9 @@ #include "internal.h" -#include #include #include -#include #include #include #include @@ -66,7 +64,7 @@ static char* getDisplayName(CGDirectDisplayID displayID) size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value), kCFStringEncodingUTF8); - name = calloc(size + 1, sizeof(char)); + name = calloc(size + 1, 1); CFStringGetCString(value, name, size, kCFStringEncodingUTF8); CFRelease(info); diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 95eae62bc..891b53395 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -1,7 +1,7 @@ //======================================================================== -// GLFW 3.2 OS X - www.glfw.org +// GLFW 3.3 OS X - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2009-2010 Camilla Berglund +// Copyright (c) 2009-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -56,6 +56,16 @@ typedef void* id; #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); +#define TISGetInputSourceProperty _glfw.ns.tis.GetInputSourceProperty +typedef UInt8 (*PFN_LMGetKbdType)(void); +#define LMGetKbdType _glfw.ns.tis.GetKbdType + // Cocoa-specific per-window data // @@ -68,11 +78,10 @@ typedef struct _GLFWwindowNS // The total sum of the distances the cursor has been warped // since the last cursor motion event was processed // This is kept to counteract Cocoa doing the same internally - double warpDeltaX, warpDeltaY; + double cursorWarpDeltaX, cursorWarpDeltaY; } _GLFWwindowNS; - // Cocoa-specific global data // typedef struct _GLFWlibraryNS @@ -82,16 +91,30 @@ 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]; char* clipboardString; + // Where to place the cursor when re-enabled + double restoreCursorPosX, restoreCursorPosY; + // The window whose disabled cursor mode is active + _GLFWwindow* disabledCursorWindow; + + struct { + CFBundleRef bundle; + PFN_TISCopyCurrentKeyboardLayoutInputSource CopyCurrentKeyboardLayoutInputSource; + PFN_TISGetInputSourceProperty GetInputSourceProperty; + PFN_LMGetKbdType GetKbdType; + CFStringRef kPropertyUnicodeKeyLayoutData; + CFStringRef kNotifySelectedKeyboardInputSourceChanged; + } tis; } _GLFWlibraryNS; - // Cocoa-specific per-monitor data // typedef struct _GLFWmonitorNS @@ -102,7 +125,6 @@ typedef struct _GLFWmonitorNS } _GLFWmonitorNS; - // Cocoa-specific per-cursor data // typedef struct _GLFWcursorNS @@ -111,7 +133,6 @@ typedef struct _GLFWcursorNS } _GLFWcursorNS; - // Cocoa-specific global timer data // typedef struct _GLFWtimeNS diff --git a/src/cocoa_time.c b/src/cocoa_time.c index f8db04e97..9a0bf6a2b 100644 --- a/src/cocoa_time.c +++ b/src/cocoa_time.c @@ -1,7 +1,7 @@ //======================================================================== -// GLFW 3.2 OS X - www.glfw.org +// GLFW 3.3 OS X - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2009-2010 Camilla Berglund +// Copyright (c) 2009-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 95ef9aebf..3d7e19495 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1,7 +1,7 @@ //======================================================================== -// GLFW 3.2 OS X - www.glfw.org +// GLFW 3.3 OS X - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2009-2010 Camilla Berglund +// Copyright (c) 2009-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -85,6 +85,29 @@ static void centerCursor(_GLFWwindow *window) _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0); } +// Returns whether the cursor is in the client area of the specified window +// +static GLFWbool cursorInClientArea(_GLFWwindow* window) +{ + const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream]; + return [window->ns.view mouse:pos inRect:[window->ns.view frame]]; +} + +// Updates the cursor image according to its cursor mode +// +static void updateCursorImage(_GLFWwindow* window) +{ + if (window->cursorMode == GLFW_CURSOR_NORMAL) + { + if (window->cursor) + [(NSCursor*) window->cursor->ns.object set]; + else + [[NSCursor arrowCursor] set]; + } + else + [(NSCursor*) _glfw.ns.cursor set]; +} + // Transforms the specified y-coordinate between the CG display and NS screen // coordinate systems // @@ -212,11 +235,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; if (window->context.client != GLFW_NO_API) [window->context.nsgl.object update]; - if (_glfw.cursorWindow == window && - window->cursorMode == GLFW_CURSOR_DISABLED) - { + if (_glfw.ns.disabledCursorWindow == window) centerCursor(window); - } const NSRect contentRect = [window->ns.view frame]; const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect]; @@ -230,11 +250,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; if (window->context.client != GLFW_NO_API) [window->context.nsgl.object update]; - if (_glfw.cursorWindow == window && - window->cursorMode == GLFW_CURSOR_DISABLED) - { + if (_glfw.ns.disabledCursorWindow == window) centerCursor(window); - } int x, y; _glfwPlatformGetWindowPos(window, &x, &y); @@ -259,11 +276,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)windowDidBecomeKey:(NSNotification *)notification { - if (_glfw.cursorWindow == window && - window->cursorMode == GLFW_CURSOR_DISABLED) - { + if (_glfw.ns.disabledCursorWindow == window) centerCursor(window); - } _glfwInputWindowFocus(window, GLFW_TRUE); _glfwPlatformSetCursorMode(window, window->cursorMode); @@ -398,7 +412,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)cursorUpdate:(NSEvent *)event { - _glfwPlatformSetCursorMode(window, window->cursorMode); + updateCursorImage(window); } - (void)mouseDown:(NSEvent *)event @@ -426,20 +440,23 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; { if (window->cursorMode == GLFW_CURSOR_DISABLED) { - _glfwInputCursorMotion(window, - [event deltaX] - window->ns.warpDeltaX, - [event deltaY] - window->ns.warpDeltaY); + const double dx = [event deltaX] - window->ns.cursorWarpDeltaX; + const double dy = [event deltaY] - window->ns.cursorWarpDeltaY; + + _glfwInputCursorPos(window, + window->virtualCursorPosX + dx, + window->virtualCursorPosY + dy); } else { const NSRect contentRect = [window->ns.view frame]; const NSPoint pos = [event locationInWindow]; - _glfwInputCursorMotion(window, pos.x, contentRect.size.height - pos.y); + _glfwInputCursorPos(window, pos.x, contentRect.size.height - pos.y); } - window->ns.warpDeltaX = 0; - window->ns.warpDeltaY = 0; + window->ns.cursorWarpDeltaX = 0; + window->ns.cursorWarpDeltaY = 0; } - (void)rightMouseDown:(NSEvent *)event @@ -611,9 +628,9 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; NSArray* files = [pasteboard propertyListForType:NSFilenamesPboardType]; const NSRect contentRect = [window->ns.view frame]; - _glfwInputCursorMotion(window, - [sender draggingLocation].x, - contentRect.size.height - [sender draggingLocation].y); + _glfwInputCursorPos(window, + [sender draggingLocation].x, + contentRect.size.height - [sender draggingLocation].y); const int count = [files count]; if (count) @@ -767,6 +784,12 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; [super sendEvent:event]; } + +// No-op thread entry point +// +- (void)doNothing:(id)object +{ +} @end #if defined(_GLFW_USE_MENUBAR) @@ -892,6 +915,11 @@ static GLFWbool initializeAppKit(void) // Implicitly create shared NSApplication instance [GLFWApplication sharedApplication]; + // Make Cocoa enter multi-threaded mode + [NSThread detachNewThreadSelector:@selector(doNothing:) + toTarget:NSApp + withObject:nil]; + // In case we are unbundled, make us a proper UI application [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; @@ -920,8 +948,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) @@ -1003,13 +1031,15 @@ 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; } @@ -1026,6 +1056,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, _glfwPlatformFocusWindow(window); if (!acquireMonitor(window)) return GLFW_FALSE; + + centerCursor(window); } return GLFW_TRUE; @@ -1033,13 +1065,16 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, void _glfwPlatformDestroyWindow(_GLFWwindow* window) { + if (_glfw.ns.disabledCursorWindow == window) + _glfw.ns.disabledCursorWindow = NULL; + [window->ns.object orderOut:nil]; if (window->monitor) releaseMonitor(window); - if (window->context.client != GLFW_NO_API) - window->context.destroyContext(window); + if (window->context.destroy) + window->context.destroy(window); [window->ns.object setDelegate:nil]; [window->ns.delegate release]; @@ -1409,13 +1444,13 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) { - _glfwPlatformSetCursorMode(window, window->cursorMode); + updateCursorImage(window); const NSRect contentRect = [window->ns.view frame]; const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream]; - window->ns.warpDeltaX += x - pos.x; - window->ns.warpDeltaY += y - contentRect.size.height + pos.y; + window->ns.cursorWarpDeltaX += x - pos.x; + window->ns.cursorWarpDeltaY += y - contentRect.size.height + pos.y; if (window->monitor) { @@ -1435,20 +1470,26 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) { - if (mode == GLFW_CURSOR_NORMAL) - { - if (window->cursor) - [(NSCursor*) window->cursor->ns.object set]; - else - [[NSCursor arrowCursor] set]; - } - else - [(NSCursor*) _glfw.ns.cursor set]; - if (mode == GLFW_CURSOR_DISABLED) + { + _glfw.ns.disabledCursorWindow = window; + _glfwPlatformGetCursorPos(window, + &_glfw.ns.restoreCursorPosX, + &_glfw.ns.restoreCursorPosY); + centerCursor(window); CGAssociateMouseAndMouseCursorPosition(false); - else + } + else if (_glfw.ns.disabledCursorWindow == window) + { + _glfw.ns.disabledCursorWindow = NULL; CGAssociateMouseAndMouseCursorPosition(true); + _glfwPlatformSetCursorPos(window, + _glfw.ns.restoreCursorPosX, + _glfw.ns.restoreCursorPosY); + } + + if (cursorInClientArea(window)) + updateCursorImage(window); } const char* _glfwPlatformGetKeyName(int key, int scancode) @@ -1522,7 +1563,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)]; @@ -1561,16 +1602,8 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) { - const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream]; - - if (window->cursorMode == GLFW_CURSOR_NORMAL && - [window->ns.view mouse:pos inRect:[window->ns.view frame]]) - { - if (cursor) - [(NSCursor*) cursor->ns.object set]; - else - [[NSCursor arrowCursor] set]; - } + if (cursorInClientArea(window)) + updateCursorImage(window); } void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) diff --git a/src/context.c b/src/context.c index e3733fef0..1961d89bb 100644 --- a/src/context.c +++ b/src/context.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -34,56 +34,6 @@ #include -// 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 ////// ////////////////////////////////////////////////////////////////////////// @@ -375,27 +325,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 = _glfwPlatformGetCurrentContext(); + + 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 && @@ -408,10 +410,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; } @@ -422,7 +435,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, @@ -527,7 +540,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); } @@ -582,11 +596,11 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) if (previous) { if (!window || window->context.source != previous->context.source) - previous->context.makeContextCurrent(NULL); + previous->context.makeCurrent(NULL); } if (window) - window->context.makeContextCurrent(window); + window->context.makeCurrent(window); } GLFWAPI GLFWwindow* glfwGetCurrentContext(void) diff --git a/src/egl_context.c b/src/egl_context.c index 062030276..8915a6e15 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -28,13 +28,14 @@ #include "internal.h" #include +#include #include #include // 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,7 +194,7 @@ static void makeContextCurrent(_GLFWwindow* window) { _glfwInputError(GLFW_PLATFORM_ERROR, "EGL: Failed to clear current context: %s", - getErrorString(eglGetError())); + getEGLErrorString(eglGetError())); return; } } @@ -201,7 +202,7 @@ static void makeContextCurrent(_GLFWwindow* window) _glfwPlatformSetCurrentContext(window); } -static void swapBuffers(_GLFWwindow* window) +static void swapBuffersEGL(_GLFWwindow* window) { if (window != _glfwPlatformGetCurrentContext()) { @@ -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,7 +231,7 @@ static int extensionSupported(const char* extension) return GLFW_FALSE; } -static GLFWglproc getProcAddress(const char* procname) +static GLFWglproc getProcAddressEGL(const char* procname) { _GLFWwindow* window = _glfwPlatformGetCurrentContext(); @@ -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, @@ -296,6 +297,9 @@ GLFWbool _glfwInitEGL(void) NULL }; + if (_glfw.egl.handle) + return GLFW_TRUE; + for (i = 0; sonames[i]; i++) { _glfw.egl.handle = _glfw_dlopen(sonames[i]); @@ -304,7 +308,12 @@ GLFWbool _glfwInitEGL(void) } if (!_glfw.egl.handle) + { + _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found"); return GLFW_FALSE; + } + + _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0); _glfw.egl.GetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC) _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib"); @@ -339,12 +348,36 @@ GLFWbool _glfwInitEGL(void) _glfw.egl.GetProcAddress = (PFNEGLGETPROCADDRESSPROC) _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 +387,18 @@ 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"); return GLFW_TRUE; } @@ -413,7 +446,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 +459,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to bind OpenGL ES: %s", - getErrorString(eglGetError())); + getEGLErrorString(eglGetError())); return GLFW_FALSE; } } @@ -436,7 +469,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to bind OpenGL: %s", - getErrorString(eglGetError())); + getEGLErrorString(eglGetError())); return GLFW_FALSE; } } @@ -515,7 +548,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, { _glfwInputError(GLFW_VERSION_UNAVAILABLE, "EGL: Failed to create context: %s", - getErrorString(eglGetError())); + getEGLErrorString(eglGetError())); return GLFW_FALSE; } @@ -543,7 +576,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, { _glfwInputError(GLFW_PLATFORM_ERROR, "EGL: Failed to create window surface: %s", - getErrorString(eglGetError())); + getEGLErrorString(eglGetError())); return GLFW_FALSE; } @@ -600,6 +633,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,12 +651,12 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, } } - window->context.makeContextCurrent = makeContextCurrent; - window->context.swapBuffers = swapBuffers; - window->context.swapInterval = swapInterval; - window->context.extensionSupported = extensionSupported; - window->context.getProcAddress = getProcAddress; - window->context.destroyContext = destroyContext; + 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; } @@ -638,7 +676,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"); diff --git a/src/egl_context.h b/src/egl_context.h index aed8a255d..39bd575ff 100644 --- a/src/egl_context.h +++ b/src/egl_context.h @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -165,13 +165,13 @@ 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; diff --git a/src/glfw_config.h.in b/src/glfw_config.h.in index aed7f7a91..f709726f0 100644 --- a/src/glfw_config.h.in +++ b/src/glfw_config.h.in @@ -1,7 +1,7 @@ //======================================================================== -// GLFW 3.2 - www.glfw.org +// GLFW 3.3 - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2010 Camilla Berglund +// Copyright (c) 2010-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -47,6 +47,8 @@ // 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 diff --git a/src/glx_context.c b/src/glx_context.c index 1760582b8..6f2f27612 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -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; @@ -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) { @@ -168,12 +168,12 @@ static void makeContextCurrent(_GLFWwindow* window) _glfwPlatformSetCurrentContext(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(); @@ -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,61 @@ 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_context_flush_control")) _glfw.glx.ARB_context_flush_control = GLFW_TRUE; return GLFW_TRUE; @@ -413,7 +437,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"); @@ -549,12 +573,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,12 +599,12 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, return GLFW_FALSE; } - window->context.makeContextCurrent = makeContextCurrent; - window->context.swapBuffers = swapBuffers; - window->context.swapInterval = swapInterval; - window->context.extensionSupported = extensionSupported; - window->context.getProcAddress = getProcAddress; - window->context.destroyContext = destroyContext; + 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; } @@ -593,7 +620,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"); diff --git a/src/glx_context.h b/src/glx_context.h index c60186a64..15e4f9b25 100644 --- a/src/glx_context.h +++ b/src/glx_context.h @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -84,7 +84,7 @@ 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 __GLXextproc (* PFNGLXGETPROCADDRESSPROC)(const GLubyte *procName); typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int); typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int); typedef void (*PFNGLXSWAPINTERVALEXTPROC)(Display*,GLXDrawable,int); @@ -121,7 +121,6 @@ typedef struct _GLFWcontextGLX } _GLFWcontextGLX; - // GLX-specific global data // typedef struct _GLFWlibraryGLX diff --git a/src/init.c b/src/init.c index 3674dcf01..e0ebfadee 100644 --- a/src/init.c +++ b/src/init.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -65,9 +65,9 @@ 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"; case GLFW_FORMAT_UNAVAILABLE: @@ -130,8 +130,6 @@ GLFWAPI int glfwInit(void) return GLFW_FALSE; } - _glfwInitVulkan(); - _glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount); _glfwInitialized = GLFW_TRUE; diff --git a/src/input.c b/src/input.c index 287dab3cc..37c98c6f0 100644 --- a/src/input.c +++ b/src/input.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -28,103 +28,13 @@ #include "internal.h" #include +#include #include // Internal key state used for sticky keys #define _GLFW_STICK 3 -// Sets the cursor mode for the specified window -// -static void setCursorMode(_GLFWwindow* window, int newMode) -{ - const int oldMode = window->cursorMode; - - if (newMode != GLFW_CURSOR_NORMAL && - newMode != GLFW_CURSOR_HIDDEN && - newMode != GLFW_CURSOR_DISABLED) - { - _glfwInputError(GLFW_INVALID_ENUM, "Invalid cursor mode %i", newMode); - return; - } - - if (oldMode == newMode) - return; - - window->cursorMode = newMode; - - if (_glfw.cursorWindow == window) - { - if (oldMode == GLFW_CURSOR_DISABLED) - { - _glfwPlatformSetCursorPos(window, - _glfw.cursorPosX, - _glfw.cursorPosY); - } - else if (newMode == GLFW_CURSOR_DISABLED) - { - int width, height; - - _glfwPlatformGetCursorPos(window, - &_glfw.cursorPosX, - &_glfw.cursorPosY); - - window->cursorPosX = _glfw.cursorPosX; - window->cursorPosY = _glfw.cursorPosY; - - _glfwPlatformGetWindowSize(window, &width, &height); - _glfwPlatformSetCursorPos(window, width / 2, height / 2); - } - - _glfwPlatformSetCursorMode(window, window->cursorMode); - } -} - -// Set sticky keys mode for the specified window -// -static void setStickyKeys(_GLFWwindow* window, int enabled) -{ - if (window->stickyKeys == enabled) - return; - - if (!enabled) - { - int i; - - // Release all sticky keys - for (i = 0; i <= GLFW_KEY_LAST; i++) - { - if (window->keys[i] == _GLFW_STICK) - window->keys[i] = GLFW_RELEASE; - } - } - - window->stickyKeys = enabled; -} - -// Set sticky mouse buttons mode for the specified window -// -static void setStickyMouseButtons(_GLFWwindow* window, int enabled) -{ - if (window->stickyMouseButtons == enabled) - return; - - if (!enabled) - { - int i; - - // Release all sticky mouse buttons - for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) - { - if (window->mouseButtons[i] == _GLFW_STICK) - window->mouseButtons[i] = GLFW_RELEASE; - } - } - - window->stickyMouseButtons = enabled; -} - - ////////////////////////////////////////////////////////////////////////// ////// GLFW event API ////// ////////////////////////////////////////////////////////////////////////// @@ -190,22 +100,16 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods); } -void _glfwInputCursorMotion(_GLFWwindow* window, double x, double y) +void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos) { - if (window->cursorMode == GLFW_CURSOR_DISABLED) - { - if (x == 0.0 && y == 0.0) - return; + if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos) + return; - window->cursorPosX += x; - window->cursorPosY += y; - - x = window->cursorPosX; - y = window->cursorPosY; - } + window->virtualCursorPosX = xpos; + window->virtualCursorPosY = ypos; if (window->callbacks.cursorPos) - window->callbacks.cursorPos((GLFWwindow*) window, x, y); + window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos); } void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered) @@ -274,18 +178,76 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) switch (mode) { case GLFW_CURSOR: - setCursorMode(window, value); - break; + { + if (value != GLFW_CURSOR_NORMAL && + value != GLFW_CURSOR_HIDDEN && + value != GLFW_CURSOR_DISABLED) + { + _glfwInputError(GLFW_INVALID_ENUM, + "Invalid cursor mode %i", + value); + return; + } + + if (window->cursorMode == value) + return; + + window->cursorMode = value; + + _glfwPlatformGetCursorPos(window, + &window->virtualCursorPosX, + &window->virtualCursorPosY); + + if (_glfwPlatformWindowFocused(window)) + _glfwPlatformSetCursorMode(window, value); + + return; + } + case GLFW_STICKY_KEYS: - setStickyKeys(window, value ? GLFW_TRUE : GLFW_FALSE); - break; + { + if (window->stickyKeys == value) + return; + + if (!value) + { + int i; + + // Release all sticky keys + for (i = 0; i <= GLFW_KEY_LAST; i++) + { + if (window->keys[i] == _GLFW_STICK) + window->keys[i] = GLFW_RELEASE; + } + } + + window->stickyKeys = value ? GLFW_TRUE : GLFW_FALSE; + return; + } + case GLFW_STICKY_MOUSE_BUTTONS: - setStickyMouseButtons(window, value ? GLFW_TRUE : GLFW_FALSE); - break; - default: - _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode); - break; + { + if (window->stickyMouseButtons == value) + return; + + if (!value) + { + int i; + + // Release all sticky mouse buttons + for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) + { + if (window->mouseButtons[i] == _GLFW_STICK) + window->mouseButtons[i] = GLFW_RELEASE; + } + } + + window->stickyMouseButtons = value ? GLFW_TRUE : GLFW_FALSE; + return; + } } + + _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode); } GLFWAPI const char* glfwGetKeyName(int key, int scancode) @@ -301,7 +263,7 @@ GLFWAPI int glfwGetKey(GLFWwindow* handle, int key) _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); - if (key < 0 || key > GLFW_KEY_LAST) + if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST) { _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key); return GLFW_RELEASE; @@ -324,7 +286,7 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button) _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); - if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) + if (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST) { _glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button); return GLFW_RELEASE; @@ -355,9 +317,9 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos) if (window->cursorMode == GLFW_CURSOR_DISABLED) { if (xpos) - *xpos = window->cursorPosX; + *xpos = window->virtualCursorPosX; if (ypos) - *ypos = window->cursorPosY; + *ypos = window->virtualCursorPosY; } else _glfwPlatformGetCursorPos(window, xpos, ypos); @@ -370,14 +332,23 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos) _GLFW_REQUIRE_INIT(); - if (_glfw.cursorWindow != window) + if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX || + ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX) + { + _glfwInputError(GLFW_INVALID_VALUE, + "Invalid cursor position %f %f", + xpos, ypos); + return; + } + + if (!_glfwPlatformWindowFocused(window)) return; if (window->cursorMode == GLFW_CURSOR_DISABLED) { // Only update the accumulated position if the cursor is disabled - window->cursorPosX = xpos; - window->cursorPosY = ypos; + window->virtualCursorPosX = xpos; + window->virtualCursorPosY = ypos; } else { @@ -480,9 +451,9 @@ GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle) _GLFW_REQUIRE_INIT(); - _glfwPlatformSetCursor(window, cursor); - window->cursor = cursor; + + _glfwPlatformSetCursor(window, cursor); } GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun) @@ -638,7 +609,6 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string) { _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - assert(string != NULL); _GLFW_REQUIRE_INIT(); diff --git a/src/internal.h b/src/internal.h index f5d4f06f8..aaf0198c9 100644 --- a/src/internal.h +++ b/src/internal.h @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -40,6 +40,7 @@ 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 @@ -149,11 +150,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" @@ -256,7 +262,6 @@ struct _GLFWwndconfig GLFWbool maximized; }; - /*! @brief Context configuration. * * Parameters relating to the creation of the context but not directly related @@ -278,7 +283,6 @@ struct _GLFWctxconfig _GLFWwindow* share; }; - /*! @brief Framebuffer configuration. * * This describes buffers and their sizes. It also contains @@ -307,7 +311,6 @@ struct _GLFWfbconfig uintptr_t handle; }; - /*! @brief Context structure. */ struct _GLFWcontext @@ -324,12 +327,12 @@ struct _GLFWcontext PFNGLGETINTEGERVPROC GetIntegerv; PFNGLGETSTRINGPROC GetString; - _GLFWmakecontextcurrentfun makeContextCurrent; + _GLFWmakecontextcurrentfun makeCurrent; _GLFWswapbuffersfun swapBuffers; _GLFWswapintervalfun swapInterval; _GLFWextensionsupportedfun extensionSupported; _GLFWgetprocaddressfun getProcAddress; - _GLFWdestroycontextfun destroyContext; + _GLFWdestroycontextfun destroy; // This is defined in the context API's context.h _GLFW_PLATFORM_CONTEXT_STATE; @@ -337,7 +340,6 @@ struct _GLFWcontext _GLFW_EGL_CONTEXT_STATE; }; - /*! @brief Window and context structure. */ struct _GLFWwindow @@ -360,13 +362,13 @@ struct _GLFWwindow int maxwidth, maxheight; int numer, denom; - // Window input state GLFWbool stickyKeys; GLFWbool stickyMouseButtons; - double cursorPosX, cursorPosY; int cursorMode; char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1]; char keys[GLFW_KEY_LAST + 1]; + // Virtual cursor position when cursor is disabled + double virtualCursorPosX, virtualCursorPosY; _GLFWcontext context; @@ -392,7 +394,6 @@ struct _GLFWwindow _GLFW_PLATFORM_WINDOW_STATE; }; - /*! @brief Monitor structure. */ struct _GLFWmonitor @@ -416,7 +417,6 @@ struct _GLFWmonitor _GLFW_PLATFORM_MONITOR_STATE; }; - /*! @brief Cursor structure */ struct _GLFWcursor @@ -438,12 +438,9 @@ struct _GLFWlibrary int refreshRate; } hints; - double cursorPosX, cursorPosY; - _GLFWcursor* cursorListHead; _GLFWwindow* windowListHead; - _GLFWwindow* cursorWindow; _GLFWmonitor** monitors; int monitorCount; @@ -455,8 +452,10 @@ struct _GLFWlibrary void* handle; char** extensions; uint32_t extensionCount; +#if !defined(_GLFW_VULKAN_STATIC) PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties; PFN_vkGetInstanceProcAddr GetInstanceProcAddr; +#endif GLFWbool KHR_surface; GLFWbool KHR_win32_surface; GLFWbool KHR_xlib_surface; @@ -884,11 +883,11 @@ void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWb /*! @brief Notifies shared code of a scroll event. * @param[in] window The window that received the event. - * @param[in] x The scroll offset along the x-axis. - * @param[in] y The scroll offset along the y-axis. + * @param[in] xoffset The scroll offset along the x-axis. + * @param[in] yoffset The scroll offset along the y-axis. * @ingroup event */ -void _glfwInputScroll(_GLFWwindow* window, double x, double y); +void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset); /*! @brief Notifies shared code of a mouse button click event. * @param[in] window The window that received the event. @@ -900,13 +899,13 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) /*! @brief Notifies shared code of a cursor motion event. * @param[in] window The window that received the event. - * @param[in] x The new x-coordinate of the cursor, relative to the left edge - * of the client area of the window. - * @param[in] y The new y-coordinate of the cursor, relative to the top edge + * @param[in] xpos The new x-coordinate of the cursor, relative to the left + * edge of the client area of the window. + * @param[in] ypos The new y-coordinate of the cursor, relative to the top edge * of the client area of the window. * @ingroup event */ -void _glfwInputCursorMotion(_GLFWwindow* window, double x, double y); +void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos); /*! @brief Notifies shared code of a cursor enter/leave event. * @param[in] window The window that received the event. @@ -1044,7 +1043,7 @@ GLFWbool _glfwIsPrintable(int key); /*! @ingroup utility */ -void _glfwInitVulkan(void); +GLFWbool _glfwInitVulkan(void); /*! @ingroup utility */ diff --git a/src/linux_joystick.c b/src/linux_joystick.c index e3e03cf17..ad249955b 100644 --- a/src/linux_joystick.c +++ b/src/linux_joystick.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -49,7 +49,7 @@ static GLFWbool openJoystickDevice(const char* path) { char axisCount, buttonCount; - char name[256]; + char name[256] = ""; int joy, fd, version; _GLFWjoystickLinux* js; @@ -153,7 +153,7 @@ static GLFWbool pollJoystickEvents(_GLFWjoystickLinux* js) return js->present; } -// 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) diff --git a/src/linux_joystick.h b/src/linux_joystick.h index c949e81d6..4187b1370 100644 --- a/src/linux_joystick.h +++ b/src/linux_joystick.h @@ -1,5 +1,5 @@ //======================================================================== -// GLFW 3.2 Linux - www.glfw.org +// GLFW 3.3 Linux - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014 Jonas Ådahl // @@ -46,7 +46,6 @@ typedef struct _GLFWjoystickLinux char* path; } _GLFWjoystickLinux; - // Linux-specific joystick API data // typedef struct _GLFWjoylistLinux diff --git a/src/mir_init.c b/src/mir_init.c index 3f649670d..7385bb74d 100644 --- a/src/mir_init.c +++ b/src/mir_init.c @@ -1,5 +1,5 @@ //======================================================================== -// GLFW 3.2 Mir - www.glfw.org +// GLFW 3.3 Mir - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014-2015 Brandon Schaefer // @@ -183,9 +183,6 @@ int _glfwPlatformInit(void) if (!_glfwInitThreadLocalStoragePOSIX()) return GLFW_FALSE; - if (!_glfwInitEGL()) - return GLFW_FALSE; - if (!_glfwInitJoysticksLinux()) return GLFW_FALSE; diff --git a/src/mir_monitor.c b/src/mir_monitor.c index 90aa6c93e..94c131379 100644 --- a/src/mir_monitor.c +++ b/src/mir_monitor.c @@ -1,5 +1,5 @@ //======================================================================== -// GLFW 3.2 Mir - www.glfw.org +// GLFW 3.3 Mir - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014-2015 Brandon Schaefer // diff --git a/src/mir_platform.h b/src/mir_platform.h index 66c6776db..2bd9b6213 100644 --- a/src/mir_platform.h +++ b/src/mir_platform.h @@ -1,5 +1,5 @@ //======================================================================== -// GLFW 3.2 Mir - www.glfw.org +// GLFW 3.3 Mir - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014-2015 Brandon Schaefer // @@ -87,7 +87,6 @@ typedef struct _GLFWwindowMir } _GLFWwindowMir; - // Mir-specific per-monitor data // typedef struct _GLFWmonitorMir @@ -99,7 +98,6 @@ typedef struct _GLFWmonitorMir } _GLFWmonitorMir; - // Mir-specific global data // typedef struct _GLFWlibraryMir @@ -116,7 +114,6 @@ typedef struct _GLFWlibraryMir } _GLFWlibraryMir; - // Mir-specific per-cursor data // TODO: Only system cursors are implemented in Mir atm. Need to wait for support. // diff --git a/src/mir_window.c b/src/mir_window.c index ddc70fa63..7d7f6322f 100644 --- a/src/mir_window.c +++ b/src/mir_window.c @@ -1,5 +1,5 @@ //======================================================================== -// GLFW 3.2 Mir - www.glfw.org +// GLFW 3.3 Mir - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014-2015 Brandon Schaefer // @@ -201,15 +201,14 @@ static void handlePointerButton(_GLFWwindow* window, static void handlePointerMotion(_GLFWwindow* window, const MirPointerEvent* pointer_event) { - int current_x = window->cursorPosX; - int current_y = window->cursorPosY; + 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); - if (current_x != x || current_y != y) - _glfwInputCursorMotion(window, x, y); + _glfwInputCursorPos(window, x, y); if (dx != 0 || dy != 0) _glfwInputScroll(window, dx, dy); } @@ -380,6 +379,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (ctxconfig->client != GLFW_NO_API) { + if (!_glfwInitEGL()) + return GLFW_FALSE; if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) return GLFW_FALSE; } @@ -395,8 +396,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) window->mir.surface = NULL; } - if (window->context.client != GLFW_NO_API) - window->context.destroyContext(window); + if (window->context.destroy) + window->context.destroy(window); } void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) diff --git a/src/monitor.c b/src/monitor.c index f63aff9be..df32a3c48 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -375,8 +375,8 @@ GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle; assert(monitor != NULL); - assert(count != NULL); + *count = 0; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); @@ -454,8 +454,18 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle; assert(monitor != NULL); - assert(ramp != NULL); + assert(ramp->red != NULL); + assert(ramp->green != NULL); + assert(ramp->blue != NULL); + + if (ramp->size <= 0) + { + _glfwInputError(GLFW_INVALID_VALUE, + "Invalid gamma ramp size %i", + ramp->size); + return; + } _GLFW_REQUIRE_INIT(); diff --git a/src/nsgl_context.h b/src/nsgl_context.h index ab4cf3dfe..aa42d2375 100644 --- a/src/nsgl_context.h +++ b/src/nsgl_context.h @@ -1,7 +1,7 @@ //======================================================================== -// GLFW 3.2 OS X - www.glfw.org +// GLFW 3.3 OS X - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2009-2010 Camilla Berglund +// Copyright (c) 2009-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -40,7 +40,6 @@ typedef struct _GLFWcontextNSGL } _GLFWcontextNSGL; - // NSGL-specific global data // typedef struct _GLFWlibraryNSGL diff --git a/src/nsgl_context.m b/src/nsgl_context.m index 122ef0bf8..c727cc4e5 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -1,7 +1,7 @@ //======================================================================== -// GLFW 3.2 OS X - www.glfw.org +// GLFW 3.3 OS X - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2009-2010 Camilla Berglund +// Copyright (c) 2009-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -27,7 +27,7 @@ #include "internal.h" -static void makeContextCurrent(_GLFWwindow* window) +static void makeContextCurrentNSGL(_GLFWwindow* window) { if (window) [window->context.nsgl.object makeCurrentContext]; @@ -37,13 +37,13 @@ static void makeContextCurrent(_GLFWwindow* window) _glfwPlatformSetCurrentContext(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(); @@ -52,13 +52,13 @@ static void swapInterval(int interval) 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) @@ -280,12 +283,12 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, [window->context.nsgl.object setView:window->ns.view]; - window->context.makeContextCurrent = makeContextCurrent; - window->context.swapBuffers = swapBuffers; - window->context.swapInterval = swapInterval; - window->context.extensionSupported = extensionSupported; - window->context.getProcAddress = getProcAddress; - window->context.destroyContext = destroyContext; + 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; } diff --git a/src/posix_time.c b/src/posix_time.c index 7b2d1ab29..368cbdf31 100644 --- a/src/posix_time.c +++ b/src/posix_time.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/src/posix_time.h b/src/posix_time.h index 237db3a99..4a23bfa3e 100644 --- a/src/posix_time.h +++ b/src/posix_time.h @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/src/posix_tls.c b/src/posix_tls.c index a0efa1f35..3edade55e 100644 --- a/src/posix_tls.c +++ b/src/posix_tls.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/src/posix_tls.h b/src/posix_tls.h index 507fc81c6..f79ba987f 100644 --- a/src/posix_tls.h +++ b/src/posix_tls.h @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/src/vulkan.c b/src/vulkan.c index fb62a18fd..a2d10b6a1 100644 --- a/src/vulkan.c +++ b/src/vulkan.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -36,20 +36,25 @@ ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwInitVulkan(void) +GLFWbool _glfwInitVulkan(void) { VkResult err; VkExtensionProperties* ep; uint32_t i, count; + +#if !defined(_GLFW_VULKAN_STATIC) #if defined(_GLFW_WIN32) const char* name = "vulkan-1.dll"; #else const char* name = "libvulkan.so.1"; #endif + if (_glfw.vk.available) + return GLFW_TRUE; + _glfw.vk.handle = _glfw_dlopen(name); if (!_glfw.vk.handle) - return; + return GLFW_FALSE; _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) _glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr"); @@ -57,7 +62,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,8 +73,11 @@ 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) @@ -75,7 +85,9 @@ void _glfwInitVulkan(void) _glfwInputError(GLFW_PLATFORM_ERROR, "Vulkan: Failed to query instance extension count: %s", _glfwGetVulkanResultString(err)); - return; + + _glfwTerminateVulkan(); + return GLFW_FALSE; } ep = calloc(count, sizeof(VkExtensionProperties)); @@ -88,7 +100,8 @@ void _glfwInitVulkan(void) _glfwGetVulkanResultString(err)); free(ep); - return; + _glfwTerminateVulkan(); + return GLFW_FALSE; } for (i = 0; i < count; i++) @@ -111,11 +124,13 @@ void _glfwInitVulkan(void) _glfw.vk.available = GLFW_TRUE; - if (!_glfw.vk.KHR_surface) - return; + if (_glfw.vk.KHR_surface) + { + _glfw.vk.extensions = + _glfwPlatformGetRequiredInstanceExtensions(&_glfw.vk.extensionCount); + } - _glfw.vk.extensions = - _glfwPlatformGetRequiredInstanceExtensions(&_glfw.vk.extensionCount); + return GLFW_TRUE; } void _glfwTerminateVulkan(void) @@ -193,7 +208,7 @@ const char* _glfwGetVulkanResultString(VkResult result) GLFWAPI int glfwVulkanSupported(void) { _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); - return _glfw.vk.available; + return _glfwInitVulkan(); } GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count) @@ -202,9 +217,9 @@ GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count) _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - if (!_glfw.vk.available) + if (!_glfwInitVulkan()) { - _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found"); + _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available"); return NULL; } @@ -219,9 +234,9 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - if (!_glfw.vk.available) + if (!_glfwInitVulkan()) { - _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found"); + _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available"); return NULL; } @@ -238,9 +253,9 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, { _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); - if (!_glfw.vk.available) + if (!_glfwInitVulkan()) { - _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found"); + _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available"); return GLFW_FALSE; } @@ -263,15 +278,15 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, { _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - assert(surface != NULL); + *surface = VK_NULL_HANDLE; _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED); - if (!_glfw.vk.available) + if (!_glfwInitVulkan()) { - _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found"); + _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available"); return VK_ERROR_INITIALIZATION_FAILED; } diff --git a/src/wgl_context.c b/src/wgl_context.c index 55399cb1c..677860de7 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -55,19 +55,17 @@ 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 _GLFWfbconfig* desired) { _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 { @@ -197,7 +195,7 @@ 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); @@ -207,13 +205,13 @@ static GLFWbool choosePixelFormat(_GLFWwindow* window, "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,7 +229,7 @@ static GLFWbool isCompositionEnabled(void) return enabled; } -static void makeContextCurrent(_GLFWwindow* window) +static void makeContextCurrentWGL(_GLFWwindow* window) { if (window) { @@ -256,7 +254,7 @@ static void makeContextCurrent(_GLFWwindow* window) } } -static void swapBuffers(_GLFWwindow* window) +static void swapBuffersWGL(_GLFWwindow* window) { // HACK: Use DwmFlush when desktop composition is enabled if (isCompositionEnabled() && !window->monitor) @@ -269,7 +267,7 @@ static void swapBuffers(_GLFWwindow* window) SwapBuffers(window->context.wgl.dc); } -static void swapInterval(int interval) +static void swapIntervalWGL(int interval) { _GLFWwindow* window = _glfwPlatformGetCurrentContext(); @@ -284,12 +282,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 +298,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 +309,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 +320,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 +331,88 @@ 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)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "WGL: Failed to set pixel format for dummy context"); + return; + } + + rc = wglCreateContext(dc); + if (!rc) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "WGL: Failed to create dummy context"); + return; + } + + if (!wglMakeCurrent(dc, rc)) + { + wglDeleteContext(rc); + + _glfwInputError(GLFW_PLATFORM_ERROR, + "WGL: Failed to make dummy context current"); + 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.EXT_swap_control = - extensionSupported("WGL_EXT_swap_control"); + extensionSupportedWGL("WGL_EXT_swap_control"); _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,6 +424,9 @@ static void loadExtensions(void) // GLFWbool _glfwInitWGL(void) { + if (_glfw.wgl.instance) + return GLFW_TRUE; + _glfw.wgl.instance = LoadLibraryA("opengl32.dll"); if (!_glfw.wgl.instance) { @@ -404,6 +440,8 @@ GLFWbool _glfwInitWGL(void) GetProcAddress(_glfw.wgl.instance, "wglDeleteContext"); _glfw.wgl.GetProcAddress = (WGLGETPROCADDRESS_T) GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress"); + _glfw.wgl.GetCurrentDC = (WGLGETCURRENTDC_T) + GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC"); _glfw.wgl.MakeCurrent = (WGLMAKECURRENT_T) GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent"); _glfw.wgl.ShareLists = (WGLSHARELISTS_T) @@ -434,12 +472,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,7 +490,8 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, return GLFW_FALSE; } - if (!choosePixelFormat(window, fbconfig, &pixelFormat)) + pixelFormat = choosePixelFormat(window, fbconfig); + if (!pixelFormat) return GLFW_FALSE; if (!DescribePixelFormat(window->context.wgl.dc, @@ -470,6 +509,40 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, 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; @@ -550,8 +623,44 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, 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 (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; } } @@ -576,114 +685,18 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, } } - window->context.makeContextCurrent = makeContextCurrent; - window->context.swapBuffers = swapBuffers; - window->context.swapInterval = swapInterval; - window->context.extensionSupported = extensionSupported; - window->context.getProcAddress = getProcAddress; - window->context.destroyContext = destroyContext; + 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; -} - ////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// diff --git a/src/wgl_context.h b/src/wgl_context.h index f1e653c8d..6d989232b 100644 --- a/src/wgl_context.h +++ b/src/wgl_context.h @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -73,6 +73,9 @@ #define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0 #define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 +#define ERROR_INVALID_VERSION_ARB 0x2095 +#define ERROR_INVALID_PROFILE_ARB 0x2096 + typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int); typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*); typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void); @@ -82,6 +85,7 @@ 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 HDC (WINAPI * WGLGETCURRENTDC_T)(void); typedef BOOL (WINAPI * WGLMAKECURRENT_T)(HDC,HGLRC); typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC,HGLRC); @@ -89,6 +93,7 @@ typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC,HGLRC); #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,7 +115,6 @@ typedef struct _GLFWcontextWGL } _GLFWcontextWGL; - // WGL-specific global data // typedef struct _GLFWlibraryWGL @@ -119,6 +123,7 @@ typedef struct _GLFWlibraryWGL WGLCREATECONTEXT_T CreateContext; WGLDELETECONTEXT_T DeleteContext; WGLGETPROCADDRESS_T GetProcAddress; + WGLGETCURRENTDC_T GetCurrentDC; WGLMAKECURRENT_T MakeCurrent; WGLSHARELISTS_T ShareLists; @@ -148,8 +153,5 @@ 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_ diff --git a/src/win32_init.c b/src/win32_init.c index 0bfe34c7c..12e98a090 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -319,6 +319,10 @@ static HWND createHelperWindow(void) 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; @@ -373,7 +377,7 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source) if (!length) return NULL; - target = calloc(length, sizeof(char)); + target = calloc(length, 1); if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length, NULL, NULL)) { @@ -415,16 +419,12 @@ int _glfwPlatformInit(void) if (!_glfwRegisterWindowClassWin32()) return GLFW_FALSE; - _glfw.win32.helperWindow = createHelperWindow(); - if (!_glfw.win32.helperWindow) + _glfw.win32.helperWindowHandle = createHelperWindow(); + if (!_glfw.win32.helperWindowHandle) return GLFW_FALSE; _glfwPlatformPollEvents(); - if (!_glfwInitWGL()) - return GLFW_FALSE; - - _glfwInitEGL(); _glfwInitTimerWin32(); _glfwInitJoysticksWin32(); @@ -433,8 +433,8 @@ int _glfwPlatformInit(void) void _glfwPlatformTerminate(void) { - if (_glfw.win32.helperWindow) - DestroyWindow(_glfw.win32.helperWindow); + if (_glfw.win32.helperWindowHandle) + DestroyWindow(_glfw.win32.helperWindowHandle); _glfwUnregisterWindowClassWin32(); diff --git a/src/win32_joystick.c b/src/win32_joystick.c index 0268e0514..49f3b871d 100644 --- a/src/win32_joystick.c +++ b/src/win32_joystick.c @@ -2,7 +2,7 @@ // GLFW 3.1 Win32 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard -// Copyright (c) 2006-2015 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -176,7 +176,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 +185,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 +211,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)); diff --git a/src/win32_joystick.h b/src/win32_joystick.h index c6faeda0d..44ce9531b 100644 --- a/src/win32_joystick.h +++ b/src/win32_joystick.h @@ -1,7 +1,7 @@ //======================================================================== -// GLFW 3.2 Win32 - www.glfw.org +// GLFW 3.3 Win32 - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2006-2014 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -30,7 +30,7 @@ #define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \ _GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1] -// Spoo +// Joystick element (axis, button or slider) // typedef struct _GLFWjoyobjectWin32 { diff --git a/src/win32_monitor.c b/src/win32_monitor.c index a6eeeb1ed..dc29f7c7c 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/src/win32_platform.h b/src/win32_platform.h index f3570bcc2..d742f3beb 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -237,21 +237,24 @@ typedef struct _GLFWwindowWin32 GLFWbool iconified; // The last received cursor position, regardless of source - int cursorPosX, cursorPosY; + int lastCursorPosX, lastCursorPosY; } _GLFWwindowWin32; - // Win32-specific global data // typedef struct _GLFWlibraryWin32 { - HWND helperWindow; + HWND helperWindowHandle; DWORD foregroundLockTimeout; char* clipboardString; char keyName[64]; short int publicKeys[512]; short int nativeKeys[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; struct { HINSTANCE instance; @@ -289,7 +292,6 @@ typedef struct _GLFWlibraryWin32 } _GLFWlibraryWin32; - // Win32-specific per-monitor data // typedef struct _GLFWmonitorWin32 @@ -304,7 +306,6 @@ typedef struct _GLFWmonitorWin32 } _GLFWmonitorWin32; - // Win32-specific per-cursor data // typedef struct _GLFWcursorWin32 @@ -313,7 +314,6 @@ typedef struct _GLFWcursorWin32 } _GLFWcursorWin32; - // Win32-specific global timer data // typedef struct _GLFWtimeWin32 @@ -323,7 +323,6 @@ typedef struct _GLFWtimeWin32 } _GLFWtimeWin32; - // Win32-specific global TLS data // typedef struct _GLFWtlsWin32 diff --git a/src/win32_time.c b/src/win32_time.c index 43e673512..add55c5f9 100644 --- a/src/win32_time.c +++ b/src/win32_time.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/src/win32_tls.c b/src/win32_tls.c index ca6ab3eed..0607ca6cf 100644 --- a/src/win32_tls.c +++ b/src/win32_tls.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/src/win32_window.c b/src/win32_window.c index b5c03ea3f..64c3d71a9 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -218,15 +218,64 @@ static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area) } } +// Centers the cursor over the window client area +// +static void centerCursor(_GLFWwindow* window) +{ + int width, height; + _glfwPlatformGetWindowSize(window, &width, &height); + _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0); +} + +// Returns whether the cursor is in the client area of the specified window +// +static GLFWbool cursorInClientArea(_GLFWwindow* window) +{ + RECT area; + POINT pos; + + if (!GetCursorPos(&pos)) + return GLFW_FALSE; + + if (WindowFromPoint(pos) != window->win32.handle) + return GLFW_FALSE; + + GetClientRect(window->win32.handle, &area); + ClientToScreen(window->win32.handle, (POINT*) &area.left); + ClientToScreen(window->win32.handle, (POINT*) &area.right); + + return PtInRect(&area, pos); +} + +// Updates the cursor image according to its cursor mode +// +static void updateCursorImage(_GLFWwindow* window) +{ + if (window->cursorMode == GLFW_CURSOR_NORMAL) + { + if (window->cursor) + SetCursor(window->cursor->win32.handle); + else + SetCursor(LoadCursorW(NULL, IDC_ARROW)); + } + else + SetCursor(NULL); +} + // Updates the cursor clip rect // static void updateClipRect(_GLFWwindow* window) { - RECT clipRect; - GetClientRect(window->win32.handle, &clipRect); - ClientToScreen(window->win32.handle, (POINT*) &clipRect.left); - ClientToScreen(window->win32.handle, (POINT*) &clipRect.right); - ClipCursor(&clipRect); + if (window) + { + RECT clipRect; + GetClientRect(window->win32.handle, &clipRect); + ClientToScreen(window->win32.handle, (POINT*) &clipRect.left); + ClientToScreen(window->win32.handle, (POINT*) &clipRect.right); + ClipCursor(&clipRect); + } + else + ClipCursor(NULL); } // Translates a GLFW standard cursor to a resource ID @@ -329,6 +378,13 @@ static int translateKey(WPARAM wParam, LPARAM lParam) return GLFW_KEY_LEFT_CONTROL; } + if (wParam == VK_PROCESSKEY) + { + // IME notifies that keys have been filtered by setting the virtual + // key-code to VK_PROCESSKEY + return _GLFW_KEY_INVALID; + } + return _glfw.win32.publicKeys[HIWORD(lParam) & 0x1FF]; } @@ -369,7 +425,7 @@ static void releaseMonitor(_GLFWwindow* window) static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - _GLFWwindow* window = (_GLFWwindow*) GetPropW(hWnd, L"GLFW"); + _GLFWwindow* window = GetPropW(hWnd, L"GLFW"); if (!window) { // This is the message handling for the hidden helper window @@ -413,10 +469,11 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, { case WM_SETFOCUS: { + _glfwInputWindowFocus(window, GLFW_TRUE); + if (window->cursorMode == GLFW_CURSOR_DISABLED) _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); - _glfwInputWindowFocus(window, GLFW_TRUE); return 0; } @@ -561,18 +618,21 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, if (window->cursorMode == GLFW_CURSOR_DISABLED) { - if (_glfw.cursorWindow != window) + const int dx = x - window->win32.lastCursorPosX; + const int dy = y - window->win32.lastCursorPosY; + + if (_glfw.win32.disabledCursorWindow != window) break; - _glfwInputCursorMotion(window, - x - window->win32.cursorPosX, - y - window->win32.cursorPosY); + _glfwInputCursorPos(window, + window->virtualCursorPosX + dx, + window->virtualCursorPosY + dy); } else - _glfwInputCursorMotion(window, x, y); + _glfwInputCursorPos(window, x, y); - window->win32.cursorPosX = x; - window->win32.cursorPosY = y; + window->win32.lastCursorPosX = x; + window->win32.lastCursorPosY = y; if (!window->win32.cursorTracked) { @@ -611,6 +671,24 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, return 0; } + case WM_ENTERSIZEMOVE: + case WM_ENTERMENULOOP: + { + if (window->cursorMode == GLFW_CURSOR_DISABLED) + _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL); + + break; + } + + case WM_EXITSIZEMOVE: + case WM_EXITMENULOOP: + { + if (window->cursorMode == GLFW_CURSOR_DISABLED) + _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); + + break; + } + case WM_SIZE: { const GLFWbool iconified = @@ -619,11 +697,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, window->win32.iconified && (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED); - if (_glfw.cursorWindow == window) - { - if (window->cursorMode == GLFW_CURSOR_DISABLED) - updateClipRect(window); - } + if (_glfw.win32.disabledCursorWindow == window) + updateClipRect(window); if (iconified) _glfwInputWindowIconify(window, GLFW_TRUE); @@ -651,11 +726,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_MOVE: { - if (_glfw.cursorWindow == window) - { - if (window->cursorMode == GLFW_CURSOR_DISABLED) - updateClipRect(window); - } + if (_glfw.win32.disabledCursorWindow == window) + updateClipRect(window); // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as // those macros do not handle negative window positions correctly @@ -718,19 +790,10 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_SETCURSOR: { - if (_glfw.cursorWindow == window && LOWORD(lParam) == HTCLIENT) + if (LOWORD(lParam) == HTCLIENT) { - if (window->cursorMode == GLFW_CURSOR_HIDDEN || - window->cursorMode == GLFW_CURSOR_DISABLED) - { - SetCursor(NULL); - return TRUE; - } - else if (window->cursor) - { - SetCursor(window->cursor->win32.handle); - return TRUE; - } + updateCursorImage(window); + return TRUE; } break; @@ -760,7 +823,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, // Move the mouse to the position of the drop DragQueryPoint(drop, &pt); - _glfwInputCursorMotion(window, pt.x, pt.y); + _glfwInputCursorPos(window, pt.x, pt.y); for (i = 0; i < count; i++) { @@ -787,9 +850,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,18 +929,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 (window->win32.handle) - { - RemovePropW(window->win32.handle, L"GLFW"); - DestroyWindow(window->win32.handle); - window->win32.handle = NULL; - } -} - ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// @@ -935,60 +987,22 @@ 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.makeContextCurrent(NULL); - - // Next destroy the Win32 window and WGL context (without resetting - // or destroying the GLFW window object) - window->context.destroyContext(window); - destroyWindow(window); - - // ...and then create them again, this time with better APIs - if (!createWindow(window, wndconfig)) - return GLFW_FALSE; - if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig)) - return GLFW_FALSE; - } } else { + if (!_glfwInitEGL()) + return GLFW_FALSE; if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) return GLFW_FALSE; } @@ -1000,6 +1014,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, _glfwPlatformFocusWindow(window); if (!acquireMonitor(window)) return GLFW_FALSE; + + centerCursor(window); } return GLFW_TRUE; @@ -1010,10 +1026,18 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) if (window->monitor) releaseMonitor(window); - if (window->context.client != GLFW_NO_API) - window->context.destroyContext(window); + 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); @@ -1326,6 +1350,8 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window) void _glfwPlatformPollEvents(void) { MSG msg; + HWND handle; + _GLFWwindow* window; while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { @@ -1335,7 +1361,7 @@ void _glfwPlatformPollEvents(void) // While GLFW does not itself post WM_QUIT, other processes may post // it to this one, for example Task Manager - _GLFWwindow* window = _glfw.windowListHead; + window = _glfw.windowListHead; while (window) { _glfwInputWindowCloseRequest(window); @@ -1349,13 +1375,14 @@ void _glfwPlatformPollEvents(void) } } - if (_glfw.cursorWindow) + handle = GetActiveWindow(); + if (handle) { - _GLFWwindow* window = _glfw.cursorWindow; - // 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 + window = GetPropW(handle, L"GLFW"); + if (window) { const int mods = getAsyncKeyMods(); @@ -1371,19 +1398,20 @@ void _glfwPlatformPollEvents(void) if (!rshiftDown && window->keys[GLFW_KEY_RIGHT_SHIFT] == 1) _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, 0, GLFW_RELEASE, mods); } + } - if (window->cursorMode == GLFW_CURSOR_DISABLED) + window = _glfw.win32.disabledCursorWindow; + if (window) + { + int width, height; + _glfwPlatformGetWindowSize(window, &width, &height); + + // NOTE: Re-center the cursor only if it has moved since the last call, + // to avoid breaking glfwWaitEvents with WM_MOUSEMOVE + if (window->win32.lastCursorPosX != width / 2 || + window->win32.lastCursorPosY != height / 2) { - int width, height; - _glfwPlatformGetWindowSize(window, &width, &height); - - // NOTE: Re-center the cursor only if it has moved since the last - // call, to avoid breaking glfwWaitEvents with WM_MOUSEMOVE - if (window->win32.cursorPosX != width / 2 || - window->win32.cursorPosY != height / 2) - { - _glfwPlatformSetCursorPos(window, width / 2, height / 2); - } + _glfwPlatformSetCursorPos(window, width / 2, height / 2); } } } @@ -1428,8 +1456,8 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos) POINT pos = { (int) xpos, (int) ypos }; // Store the new position so it can be recognized later - window->win32.cursorPosX = pos.x; - window->win32.cursorPosY = pos.y; + window->win32.lastCursorPosX = pos.x; + window->win32.lastCursorPosY = pos.y; ClientToScreen(window->win32.handle, &pos); SetCursorPos(pos.x, pos.y); @@ -1437,28 +1465,26 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos) void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) { - POINT pos; - if (mode == GLFW_CURSOR_DISABLED) - updateClipRect(window); - else - ClipCursor(NULL); - - if (!GetCursorPos(&pos)) - return; - - if (WindowFromPoint(pos) != window->win32.handle) - return; - - if (mode == GLFW_CURSOR_NORMAL) { - if (window->cursor) - SetCursor(window->cursor->win32.handle); - else - SetCursor(LoadCursorW(NULL, IDC_ARROW)); + _glfw.win32.disabledCursorWindow = window; + _glfwPlatformGetCursorPos(window, + &_glfw.win32.restoreCursorPosX, + &_glfw.win32.restoreCursorPosY); + centerCursor(window); + updateClipRect(window); } - else - SetCursor(NULL); + else if (_glfw.win32.disabledCursorWindow == window) + { + _glfw.win32.disabledCursorWindow = NULL; + updateClipRect(NULL); + _glfwPlatformSetCursorPos(window, + _glfw.win32.restoreCursorPosX, + _glfw.win32.restoreCursorPosY); + } + + if (cursorInClientArea(window)) + updateCursorImage(window); } const char* _glfwPlatformGetKeyName(int key, int scancode) @@ -1518,91 +1544,70 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) { - RECT area; - POINT pos; - - if (_glfw.cursorWindow != window) - return; - - if (window->cursorMode != GLFW_CURSOR_NORMAL) - return; - - if (!GetCursorPos(&pos)) - return; - - if (WindowFromPoint(pos) != window->win32.handle) - return; - - GetClientRect(window->win32.handle, &area); - ClientToScreen(window->win32.handle, (POINT*) &area.left); - ClientToScreen(window->win32.handle, (POINT*) &area.right); - - if (!PtInRect(&area, pos)) - return; - - if (cursor) - SetCursor(cursor->win32.handle); - else - SetCursor(LoadCursorW(NULL, IDC_ARROW)); + if (cursorInClientArea(window)) + updateCursorImage(window); } 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) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to convert string to UTF-16"); + "Win32: Failed to convert clipboard string to UTF-16"); return; } - wideSize = (wcslen(wideString) + 1) * sizeof(WCHAR); - - stringHandle = GlobalAlloc(GMEM_MOVEABLE, wideSize); - if (!stringHandle) + object = GlobalAlloc(GMEM_MOVEABLE, characterCount * sizeof(WCHAR)); + if (!object) { - free(wideString); - _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to allocate global handle for clipboard"); return; } - memcpy(GlobalLock(stringHandle), wideString, wideSize); - GlobalUnlock(stringHandle); - - if (!OpenClipboard(_glfw.win32.helperWindow)) + buffer = GlobalLock(object); + if (!buffer) { - GlobalFree(stringHandle); - free(wideString); + GlobalFree(object); + + _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to lock global handle"); + return; + } + + MultiByteToWideChar(CP_UTF8, 0, string, -1, buffer, characterCount); + GlobalUnlock(object); + + if (!OpenClipboard(_glfw.win32.helperWindowHandle)) + { + GlobalFree(object); _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard"); 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.helperWindow)) + if (!OpenClipboard(_glfw.win32.helperWindowHandle)) { _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard"); return NULL; } - stringHandle = GetClipboardData(CF_UNICODETEXT); - if (!stringHandle) + object = GetClipboardData(CF_UNICODETEXT); + if (!object) { CloseClipboard(); @@ -1611,11 +1616,20 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) return NULL; } + buffer = GlobalLock(object); + if (!buffer) + { + CloseClipboard(); + + _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to lock global handle"); + return NULL; + } + free(_glfw.win32.clipboardString); _glfw.win32.clipboardString = - _glfwCreateUTF8FromWideStringWin32(GlobalLock(stringHandle)); + _glfwCreateUTF8FromWideStringWin32(buffer); - GlobalUnlock(stringHandle); + GlobalUnlock(object); CloseClipboard(); if (!_glfw.win32.clipboardString) diff --git a/src/window.c b/src/window.c index 397cf5774..53216fcba 100644 --- a/src/window.c +++ b/src/window.c @@ -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-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // Copyright (c) 2012 Torsten Walluhn // // This software is provided 'as-is', without any express or implied @@ -42,8 +42,6 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) { if (focused) { - _glfw.cursorWindow = window; - if (window->callbacks.focus) window->callbacks.focus((GLFWwindow*) window, focused); } @@ -51,8 +49,6 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) { int i; - _glfw.cursorWindow = NULL; - if (window->callbacks.focus) window->callbacks.focus((GLFWwindow*) window, focused); @@ -155,7 +151,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; @@ -206,7 +203,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, if (ctxconfig.client != GLFW_NO_API) { - window->context.makeContextCurrent(window); + window->context.makeCurrent(window); // Retrieve the actual (as opposed to requested) context attributes if (!_glfwRefreshContextAttribs(&ctxconfig)) @@ -220,17 +217,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, glfwMakeContextCurrent((GLFWwindow*) previous); } - if (window->monitor) - { - int width, height; - _glfwPlatformGetWindowSize(window, &width, &height); - - window->cursorPosX = width / 2; - window->cursorPosY = height / 2; - - _glfwPlatformSetCursorPos(window, window->cursorPosX, window->cursorPosY); - } - else + if (!window->monitor) { if (wndconfig.visible) { @@ -409,10 +396,6 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) if (window == _glfwPlatformGetCurrentContext()) glfwMakeContextCurrent(NULL); - // Clear the focused window pointer if this is the focused window - if (_glfw.cursorWindow == window) - _glfw.cursorWindow = NULL; - _glfwPlatformDestroyWindow(window); // Unlink window from global linked list @@ -532,11 +515,27 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle, _GLFW_REQUIRE_INIT(); - if (minwidth < 0 || minheight < 0 || - maxwidth < minwidth || maxheight < minheight) + if (minwidth != GLFW_DONT_CARE && minheight != GLFW_DONT_CARE) { - _glfwInputError(GLFW_INVALID_VALUE, "Invalid window size limits"); - return; + if (minwidth < 0 || minheight < 0) + { + _glfwInputError(GLFW_INVALID_VALUE, + "Invalid window minimum size %ix%i", + minwidth, minheight); + return; + } + } + + if (maxwidth != GLFW_DONT_CARE && maxheight != GLFW_DONT_CARE) + { + if (maxwidth < 0 || maxheight < 0 || + maxwidth < minwidth || maxheight < minheight) + { + _glfwInputError(GLFW_INVALID_VALUE, + "Invalid window maximum size %ix%i", + maxwidth, maxheight); + return; + } } window->minwidth = minwidth; @@ -559,10 +558,15 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom) _GLFW_REQUIRE_INIT(); - if (numer <= 0 || denom <= 0) + if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE) { - _glfwInputError(GLFW_INVALID_VALUE, "Invalid window aspect ratio"); - return; + if (numer <= 0 || denom <= 0) + { + _glfwInputError(GLFW_INVALID_VALUE, + "Invalid window aspect ratio %i:%i", + numer, denom); + return; + } } window->numer = numer; @@ -577,7 +581,7 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom) GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height) { _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window); + assert(window != NULL); if (width) *width = 0; @@ -629,7 +633,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); } @@ -738,10 +748,26 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh, { _GLFWwindow* window = (_GLFWwindow*) wh; _GLFWmonitor* monitor = (_GLFWmonitor*) mh; - assert(window); + assert(window != NULL); _GLFW_REQUIRE_INIT(); + if (width <= 0 || height <= 0) + { + _glfwInputError(GLFW_INVALID_VALUE, + "Invalid window size %ix%i", + width, height); + return; + } + + if (refreshRate < 0 && refreshRate != GLFW_DONT_CARE) + { + _glfwInputError(GLFW_INVALID_VALUE, + "Invalid refresh rate %i", + refreshRate); + return; + } + window->videoMode.width = width; window->videoMode.height = height; window->videoMode.refreshRate = refreshRate; diff --git a/src/wl_init.c b/src/wl_init.c index 29509ae91..1b590091f 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -1,5 +1,5 @@ //======================================================================== -// GLFW 3.2 Wayland - www.glfw.org +// GLFW 3.3 Wayland - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014 Jonas Ådahl // @@ -91,9 +91,9 @@ static void pointerHandleMotion(void* data, window->wl.cursorPosY = wl_fixed_to_double(sy); } - _glfwInputCursorMotion(window, - wl_fixed_to_double(sx), - wl_fixed_to_double(sy)); + _glfwInputCursorPos(window, + wl_fixed_to_double(sx), + wl_fixed_to_double(sy)); } static void pointerHandleButton(void* data, @@ -600,9 +600,6 @@ int _glfwPlatformInit(void) if (!_glfwInitThreadLocalStoragePOSIX()) return GLFW_FALSE; - if (!_glfwInitEGL()) - return GLFW_FALSE; - if (!_glfwInitJoysticksLinux()) return GLFW_FALSE; diff --git a/src/wl_monitor.c b/src/wl_monitor.c index 3b2b95fed..d6a5a3f46 100644 --- a/src/wl_monitor.c +++ b/src/wl_monitor.c @@ -1,5 +1,5 @@ //======================================================================== -// GLFW 3.2 Wayland - www.glfw.org +// GLFW 3.3 Wayland - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014 Jonas Ådahl // @@ -120,7 +120,7 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version) struct wl_output *output; char name_str[80]; - memset(name_str, 0, 80 * sizeof(char)); + memset(name_str, 0, sizeof(name_str)); snprintf(name_str, 79, "wl_output@%u", name); if (version < 2) diff --git a/src/wl_platform.h b/src/wl_platform.h index 221108ed0..e2d3d43bc 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -1,5 +1,5 @@ //======================================================================== -// GLFW 3.2 Wayland - www.glfw.org +// GLFW 3.3 Wayland - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014 Jonas Ådahl // @@ -74,7 +74,6 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR // typedef struct _GLFWvidmodeWayland _GLFWvidmodeWayland; - // Wayland-specific per-window data // typedef struct _GLFWwindowWayland @@ -105,7 +104,6 @@ typedef struct _GLFWwindowWayland } pointerLock; } _GLFWwindowWayland; - // Wayland-specific global data // typedef struct _GLFWlibraryWayland @@ -149,7 +147,6 @@ typedef struct _GLFWlibraryWayland } _GLFWlibraryWayland; - // Wayland-specific per-monitor data // typedef struct _GLFWmonitorWayland @@ -166,7 +163,6 @@ typedef struct _GLFWmonitorWayland int scale; } _GLFWmonitorWayland; - // Wayland-specific per-cursor data // typedef struct _GLFWcursorWayland diff --git a/src/wl_window.c b/src/wl_window.c index 58a721fd9..d633c6618 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1,5 +1,5 @@ //======================================================================== -// GLFW 3.2 Wayland - www.glfw.org +// GLFW 3.3 Wayland - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014 Jonas Ådahl // @@ -393,6 +393,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (ctxconfig->client != GLFW_NO_API) { + if (!_glfwInitEGL()) + return GLFW_FALSE; if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) return GLFW_FALSE; } @@ -435,8 +437,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) _glfwInputWindowFocus(window, GLFW_FALSE); } - if (window->context.client != GLFW_NO_API) - window->context.destroyContext(window); + if (window->context.destroy) + window->context.destroy(window); if (window->wl.native) wl_egl_window_destroy(window->wl.native); @@ -784,9 +786,9 @@ static void handleRelativeMotion(void* data, if (window->cursorMode != GLFW_CURSOR_DISABLED) return; - _glfwInputCursorMotion(window, - wl_fixed_to_double(dxUnaccel), - wl_fixed_to_double(dyUnaccel)); + _glfwInputCursorPos(window, + window->virtualCursorPosX + wl_fixed_to_double(dxUnaccel), + window->virtualCursorPosY + wl_fixed_to_double(dyUnaccel)); } static const struct zwp_relative_pointer_v1_listener relativePointerListener = { diff --git a/src/x11_init.c b/src/x11_init.c index 112e4547d..87bd877eb 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -1,8 +1,8 @@ //======================================================================== -// GLFW 3.2 X11 - www.glfw.org +// GLFW 3.3 X11 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard -// Copyright (c) 2006-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -72,9 +72,8 @@ static int translateKeyCode(int scancode) default: break; } - // Now try primary keysym for function keys (non-printable keys). These - // should not be layout dependent (i.e. US layout and international - // layouts should give the same result). + // Now try primary keysym for function keys (non-printable keys) + // These should not depend on the current keyboard layout keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 0); } else @@ -766,13 +765,9 @@ int _glfwPlatformInit(void) if (!_glfwInitThreadLocalStoragePOSIX()) return GLFW_FALSE; - if (!_glfwInitGLX()) - return GLFW_FALSE; - if (!_glfwInitJoysticksLinux()) return GLFW_FALSE; - _glfwInitEGL(); _glfwInitTimerPOSIX(); return GLFW_TRUE; diff --git a/src/x11_monitor.c b/src/x11_monitor.c index 63f106f25..111ef1aa2 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -1,8 +1,8 @@ //======================================================================== -// GLFW 3.2 X11 - www.glfw.org +// GLFW 3.3 X11 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard -// Copyright (c) 2006-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/src/x11_platform.h b/src/x11_platform.h index 9c76d1898..074ab70d6 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -1,8 +1,8 @@ //======================================================================== -// GLFW 3.2 X11 - www.glfw.org +// GLFW 3.3 X11 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard -// Copyright (c) 2006-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -118,19 +118,16 @@ typedef struct _GLFWwindowX11 int xpos, ypos; // The last received cursor position, regardless of source - double cursorPosX, cursorPosY; + int lastCursorPosX, lastCursorPosY; // The last position the cursor was warped to by GLFW - int warpPosX, warpPosY; + int warpCursorPosX, warpCursorPosY; // The information from the last KeyPress event - struct { - unsigned int keycode; - Time time; - } last; + unsigned int lastKeyCode; + Time lastKeyTime; } _GLFWwindowX11; - // X11-specific global data // typedef struct _GLFWlibraryX11 @@ -155,6 +152,10 @@ typedef struct _GLFWlibraryX11 short int publicKeys[256]; // GLFW key to X11 keycode LUT short int nativeKeys[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; // Window manager atoms Atom WM_PROTOCOLS; @@ -255,7 +256,6 @@ typedef struct _GLFWlibraryX11 } _GLFWlibraryX11; - // X11-specific per-monitor data // typedef struct _GLFWmonitorX11 @@ -270,7 +270,6 @@ typedef struct _GLFWmonitorX11 } _GLFWmonitorX11; - // X11-specific per-cursor data // typedef struct _GLFWcursorX11 diff --git a/src/x11_window.c b/src/x11_window.c index 19b9d2469..7542321d5 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1,8 +1,8 @@ //======================================================================== -// GLFW 3.2 X11 - www.glfw.org +// GLFW 3.3 X11 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard -// Copyright (c) 2006-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -49,15 +49,15 @@ #define Button7 7 -// Wait for data to arrive +// Wait for data to arrive using select +// This avoids blocking other threads via the per-display Xlib lock that also +// covers GLX functions // -void selectDisplayConnection(struct timeval* timeout) +static GLFWbool waitForEvent(double* timeout) { fd_set fds; - int result, count; const int fd = ConnectionNumber(_glfw.x11.display); - - count = fd + 1; + int count = fd + 1; FD_ZERO(&fds); FD_SET(fd, &fds); @@ -67,18 +67,49 @@ void selectDisplayConnection(struct timeval* timeout) if (fd < _glfw.linux_js.inotify) count = _glfw.linux_js.inotify + 1; #endif - - // NOTE: We use select instead of an X function like XNextEvent, as the - // wait inside those are guarded by the mutex protecting the display - // struct, locking out other threads from using X (including GLX) - // NOTE: Only retry on EINTR if there is no timeout, as select is not - // required to update it for the time elapsed - // TODO: Update timeout value manually - do + for (;;) { - result = select(count, &fds, NULL, NULL, timeout); + if (timeout) + { + const long seconds = (long) *timeout; + const long microseconds = (long) ((*timeout - seconds) * 1e6); + struct timeval tv = { seconds, microseconds }; + const uint64_t base = _glfwPlatformGetTimerValue(); + + const int result = select(count, &fds, NULL, NULL, &tv); + const int error = errno; + + *timeout -= (_glfwPlatformGetTimerValue() - base) / + (double) _glfwPlatformGetTimerFrequency(); + + if (result > 0) + return GLFW_TRUE; + if ((result == -1 && error == EINTR) || *timeout <= 0.0) + return GLFW_FALSE; + } + else if (select(count, &fds, NULL, NULL, NULL) != -1 || errno != EINTR) + return GLFW_TRUE; } - while (result == -1 && errno == EINTR && timeout == NULL); +} + +// Waits until a VisibilityNotify event arrives for the specified window or the +// timeout period elapses (ICCCM section 4.2.2) +// +static GLFWbool waitForVisibilityNotify(_GLFWwindow* window) +{ + XEvent dummy; + double timeout = 0.1; + + while (!XCheckTypedWindowEvent(_glfw.x11.display, + window->x11.handle, + VisibilityNotify, + &dummy)) + { + if (!waitForEvent(&timeout)) + return GLFW_FALSE; + } + + return GLFW_TRUE; } // Returns whether the window is iconified @@ -105,6 +136,15 @@ static int getWindowState(_GLFWwindow* window) // Returns whether the event is a selection event // +static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer) +{ + return event->type == SelectionRequest || + event->type == SelectionNotify || + event->type == SelectionClear; +} + +// Returns whether it is a _NET_FRAME_EXTENTS event for the specified window +// static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointer) { _GLFWwindow* window = (_GLFWwindow*) pointer; @@ -218,14 +258,18 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height) if (window->resizable) { if (window->minwidth != GLFW_DONT_CARE && - window->minheight != GLFW_DONT_CARE && - window->maxwidth != GLFW_DONT_CARE && + window->minheight != GLFW_DONT_CARE) + { + hints->flags |= PMinSize; + hints->min_width = window->minwidth; + hints->min_height = window->minheight; + } + + if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE) { - hints->flags |= (PMinSize | PMaxSize); - hints->min_width = window->minwidth; - hints->min_height = window->minheight; - hints->max_width = window->maxwidth; + hints->flags |= PMaxSize; + hints->max_width = window->maxwidth; hints->max_height = window->maxheight; } @@ -245,6 +289,9 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height) } } + hints->flags |= PWinGravity; + hints->win_gravity = StaticGravity; + XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints); XFree(hints); } @@ -387,16 +434,40 @@ static char** parseUriList(char* text, int* count) return paths; } +// Centers the cursor over the window client area +// +static void centerCursor(_GLFWwindow* window) +{ + int width, height; + _glfwPlatformGetWindowSize(window, &width, &height); + _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0); +} + +// Updates the cursor image according to its cursor mode +// +static void updateCursorImage(_GLFWwindow* window) +{ + if (window->cursorMode == GLFW_CURSOR_NORMAL) + { + if (window->cursor) + { + XDefineCursor(_glfw.x11.display, window->x11.handle, + window->cursor->x11.handle); + } + else + XUndefineCursor(_glfw.x11.display, window->x11.handle); + } + else + XDefineCursor(_glfw.x11.display, window->x11.handle, _glfw.x11.cursor); +} + // Create the X11 window (and its colormap) // -static GLFWbool createWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - Visual* visual, int depth) +static GLFWbool createNativeWindow(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + Visual* visual, int depth) { - // Every window needs a colormap - // Create one based on the visual used by the current context - // TODO: Decouple this from context creation - + // Create a colormap based on the visual used by the current context window->x11.colormap = XCreateColormap(_glfw.x11.display, _glfw.x11.root, visual, @@ -584,15 +655,6 @@ static GLFWbool createWindow(_GLFWwindow* window, return GLFW_TRUE; } -// Returns whether the event is a selection event -// -static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer) -{ - return event->type == SelectionRequest || - event->type == SelectionNotify || - event->type == SelectionClear; -} - // Set the specified property to the selection converted to the requested target // static Atom writeTargetToProperty(const XSelectionRequestEvent* request) @@ -791,7 +853,7 @@ static void pushSelectionToManager(_GLFWwindow* window) } } - selectDisplayConnection(NULL); + waitForEvent(NULL); } } @@ -933,15 +995,15 @@ static void processEvent(XEvent *event) // HACK: Ignore duplicate key press events generated by ibus // Corresponding release events are filtered out by the // GLFW key repeat logic - if (window->x11.last.keycode != keycode || - window->x11.last.time != event->xkey.time) + if (window->x11.lastKeyCode != keycode || + window->x11.lastKeyTime != event->xkey.time) { if (keycode) _glfwInputKey(window, key, keycode, GLFW_PRESS, mods); } - window->x11.last.keycode = keycode; - window->x11.last.time = event->xkey.time; + window->x11.lastKeyCode = keycode; + window->x11.lastKeyTime = event->xkey.time; if (!filtered) { @@ -1152,25 +1214,28 @@ static void processEvent(XEvent *event) const int x = event->xmotion.x; const int y = event->xmotion.y; - if (x != window->x11.warpPosX || y != window->x11.warpPosY) + if (x != window->x11.warpCursorPosX || y != window->x11.warpCursorPosY) { // The cursor was moved by something other than GLFW if (window->cursorMode == GLFW_CURSOR_DISABLED) { - if (_glfw.cursorWindow != window) + if (_glfw.x11.disabledCursorWindow != window) return; - _glfwInputCursorMotion(window, - x - window->x11.cursorPosX, - y - window->x11.cursorPosY); + const int dx = x - window->x11.lastCursorPosX; + const int dy = y - window->x11.lastCursorPosY; + + _glfwInputCursorPos(window, + window->virtualCursorPosX + dx, + window->virtualCursorPosY + dy); } else - _glfwInputCursorMotion(window, x, y); + _glfwInputCursorPos(window, x, y); } - window->x11.cursorPosX = x; - window->x11.cursorPosY = y; + window->x11.lastCursorPosX = x; + window->x11.lastCursorPosY = y; return; } @@ -1268,7 +1333,7 @@ static void processEvent(XEvent *event) int x, y; _glfwPlatformGetWindowPos(window, &x, &y); - _glfwInputCursorMotion(window, absX - x, absY - y); + _glfwInputCursorPos(window, absX - x, absY - y); // Reply that we are ready to copy the dragged data XEvent reply; @@ -1340,6 +1405,9 @@ static void processEvent(XEvent *event) case FocusIn: { + if (window->cursorMode == GLFW_CURSOR_DISABLED) + _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); + if (event->xfocus.mode == NotifyGrab || event->xfocus.mode == NotifyUngrab) { @@ -1351,15 +1419,15 @@ static void processEvent(XEvent *event) if (window->x11.ic) XSetICFocus(window->x11.ic); - if (window->cursorMode == GLFW_CURSOR_DISABLED) - _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); - _glfwInputWindowFocus(window, GLFW_TRUE); return; } case FocusOut: { + if (window->cursorMode == GLFW_CURSOR_DISABLED) + _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL); + if (event->xfocus.mode == NotifyGrab || event->xfocus.mode == NotifyUngrab) { @@ -1371,9 +1439,6 @@ static void processEvent(XEvent *event) if (window->x11.ic) XUnsetICFocus(window->x11.ic); - if (window->cursorMode == GLFW_CURSOR_DISABLED) - _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL); - if (window->monitor && window->autoIconify) _glfwPlatformIconifyWindow(window); @@ -1487,17 +1552,21 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, { if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API) { + if (!_glfwInitGLX()) + return GLFW_FALSE; if (!_glfwChooseVisualGLX(ctxconfig, fbconfig, &visual, &depth)) return GLFW_FALSE; } else { + if (!_glfwInitEGL()) + return GLFW_FALSE; if (!_glfwChooseVisualEGL(ctxconfig, fbconfig, &visual, &depth)) return GLFW_FALSE; } } - if (!createWindow(window, wndconfig, visual, depth)) + if (!createNativeWindow(window, wndconfig, visual, depth)) return GLFW_FALSE; if (ctxconfig->client != GLFW_NO_API) @@ -1520,13 +1589,19 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, updateWindowMode(window); if (!acquireMonitor(window)) return GLFW_FALSE; + + centerCursor(window); } + XFlush(_glfw.x11.display); return GLFW_TRUE; } void _glfwPlatformDestroyWindow(_GLFWwindow* window) { + if (_glfw.x11.disabledCursorWindow == window) + _glfw.x11.disabledCursorWindow = NULL; + if (window->monitor) releaseMonitor(window); @@ -1536,8 +1611,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) window->x11.ic = NULL; } - if (window->context.client != GLFW_NO_API) - window->context.destroyContext(window); + if (window->context.destroy) + window->context.destroy(window); if (window->x11.handle) { @@ -1640,21 +1715,11 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window, void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) { - Window child; + Window dummy; int x, y; XTranslateCoordinates(_glfw.x11.display, window->x11.handle, _glfw.x11.root, - 0, 0, &x, &y, &child); - - if (child) - { - int left, top; - XTranslateCoordinates(_glfw.x11.display, window->x11.handle, child, - 0, 0, &left, &top, &child); - - x -= left; - y -= top; - } + 0, 0, &x, &y, &dummy); if (xpos) *xpos = x; @@ -1753,19 +1818,16 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, if (!_glfwPlatformWindowVisible(window) && _glfw.x11.NET_REQUEST_FRAME_EXTENTS) { - uint64_t base; XEvent event; + double timeout = 0.5; // Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to // function before the window is mapped sendEventToWM(window, _glfw.x11.NET_REQUEST_FRAME_EXTENTS, 0, 0, 0, 0, 0); - base = _glfwPlatformGetTimerValue(); - - // HACK: Poll with timeout for the required reply instead of blocking - // This is done because some window managers (at least Unity, - // Fluxbox and Xfwm) failed to send the required reply + // HACK: Use a timeout because earlier versions of some window managers + // (at least Unity, Fluxbox and Xfwm) failed to send the reply // They have been fixed but broken versions are still in the wild // If you are affected by this and your window manager is NOT // listed above, PLEASE report it to their and our issue trackers @@ -1774,21 +1836,12 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, isFrameExtentsEvent, (XPointer) window)) { - double remaining; - struct timeval timeout; - - remaining = 0.5 - (_glfwPlatformGetTimerValue() - base) / - (double) _glfwPlatformGetTimerFrequency(); - if (remaining <= 0.0) + if (!waitForEvent(&timeout)) { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue"); return; } - - timeout.tv_sec = 0; - timeout.tv_usec = (long) (remaining * 1e6); - selectDisplayConnection(&timeout); } } @@ -1838,8 +1891,11 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) } if (_glfwPlatformWindowIconified(window)) + { XMapWindow(_glfw.x11.display, window->x11.handle); - else + waitForVisibilityNotify(window); + } + else if (_glfwPlatformWindowVisible(window)) { if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT && @@ -1875,8 +1931,11 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window) void _glfwPlatformShowWindow(_GLFWwindow* window) { + if (_glfwPlatformWindowVisible(window)) + return; + XMapWindow(_glfw.x11.display, window->x11.handle); - XFlush(_glfw.x11.display); + waitForVisibilityNotify(window); } void _glfwPlatformHideWindow(_GLFWwindow* window) @@ -1931,7 +1990,8 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, if (window->monitor) { XMapRaised(_glfw.x11.display, window->x11.handle); - acquireMonitor(window); + if (waitForVisibilityNotify(window)) + acquireMonitor(window); } else { @@ -2000,40 +2060,26 @@ void _glfwPlatformPollEvents(void) processEvent(&event); } - _GLFWwindow* window = _glfw.cursorWindow; - if (window && window->cursorMode == GLFW_CURSOR_DISABLED) - { - int width, height; - _glfwPlatformGetWindowSize(window, &width, &height); - _glfwPlatformSetCursorPos(window, width / 2, height / 2); - } + if (_glfw.x11.disabledCursorWindow) + centerCursor(_glfw.x11.disabledCursorWindow); + + XFlush(_glfw.x11.display); } void _glfwPlatformWaitEvents(void) { while (!XPending(_glfw.x11.display)) - selectDisplayConnection(NULL); + waitForEvent(NULL); _glfwPlatformPollEvents(); } void _glfwPlatformWaitEventsTimeout(double timeout) { - const double deadline = timeout + _glfwPlatformGetTimerValue() / - (double) _glfwPlatformGetTimerFrequency(); - while (!XPending(_glfw.x11.display)) { - const double remaining = deadline - _glfwPlatformGetTimerValue() / - (double) _glfwPlatformGetTimerFrequency(); - if (remaining <= 0.0) - return; - - const long seconds = (long) remaining; - const long microseconds = (long) ((remaining - seconds) * 1e6); - struct timeval tv = { seconds, microseconds }; - - selectDisplayConnection(&tv); + if (!waitForEvent(&timeout)) + break; } _glfwPlatformPollEvents(); @@ -2074,42 +2120,39 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) { // Store the new position so it can be recognized later - window->x11.warpPosX = (int) x; - window->x11.warpPosY = (int) y; + window->x11.warpCursorPosX = (int) x; + window->x11.warpCursorPosY = (int) y; XWarpPointer(_glfw.x11.display, None, window->x11.handle, 0,0,0,0, (int) x, (int) y); + XFlush(_glfw.x11.display); } void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) { if (mode == GLFW_CURSOR_DISABLED) { + _glfw.x11.disabledCursorWindow = window; + _glfwPlatformGetCursorPos(window, + &_glfw.x11.restoreCursorPosX, + &_glfw.x11.restoreCursorPosY); + centerCursor(window); XGrabPointer(_glfw.x11.display, window->x11.handle, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, window->x11.handle, _glfw.x11.cursor, CurrentTime); } - else + else if (_glfw.x11.disabledCursorWindow == window) { + _glfw.x11.disabledCursorWindow = NULL; XUngrabPointer(_glfw.x11.display, CurrentTime); - - if (mode == GLFW_CURSOR_NORMAL) - { - if (window->cursor) - { - XDefineCursor(_glfw.x11.display, window->x11.handle, - window->cursor->x11.handle); - } - else - XUndefineCursor(_glfw.x11.display, window->x11.handle); - } - else - { - XDefineCursor(_glfw.x11.display, window->x11.handle, - _glfw.x11.cursor); - } + _glfwPlatformSetCursorPos(window, + _glfw.x11.restoreCursorPosX, + _glfw.x11.restoreCursorPosY); } + + updateCursorImage(window); + XFlush(_glfw.x11.display); } const char* _glfwPlatformGetKeyName(int key, int scancode) @@ -2175,11 +2218,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) { if (window->cursorMode == GLFW_CURSOR_NORMAL) { - if (cursor) - XDefineCursor(_glfw.x11.display, window->x11.handle, cursor->x11.handle); - else - XUndefineCursor(_glfw.x11.display, window->x11.handle); - + updateCursorImage(window); XFlush(_glfw.x11.display); } } @@ -2231,10 +2270,8 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) _glfw.x11.GLFW_SELECTION, window->x11.handle, CurrentTime); - // XCheckTypedEvent is used instead of XIfEvent in order not to lock - // other threads out from the display during the entire wait period while (!XCheckTypedEvent(_glfw.x11.display, SelectionNotify, &event)) - selectDisplayConnection(NULL); + waitForEvent(NULL); if (event.xselection.property == None) continue; diff --git a/src/xkb_unicode.c b/src/xkb_unicode.c index a092c4b1e..e16a070ca 100644 --- a/src/xkb_unicode.c +++ b/src/xkb_unicode.c @@ -1,8 +1,8 @@ //======================================================================== -// GLFW 3.2 X11 - www.glfw.org +// GLFW 3.3 X11 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard -// Copyright (c) 2006-2010 Camilla Berglund +// Copyright (c) 2006-2016 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/src/xkb_unicode.h b/src/xkb_unicode.h index 688374d84..164a6fa8a 100644 --- a/src/xkb_unicode.h +++ b/src/xkb_unicode.h @@ -1,5 +1,5 @@ //======================================================================== -// GLFW 3.2 Linux - www.glfw.org +// GLFW 3.3 Linux - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014 Jonas Ådahl // diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9339ee594..205ec377e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -48,7 +48,9 @@ set(CONSOLE_BINARIES clipboard events msaa gamma glfwinfo if (VULKAN_FOUND) add_executable(vulkan WIN32 vulkan.c ${ICON}) target_include_directories(vulkan PRIVATE "${VULKAN_INCLUDE_DIR}") - target_link_libraries(vulkan "${VULKAN_LIBRARY}") + if (NOT GLFW_VULKAN_STATIC) + target_link_libraries(vulkan "${VULKAN_LIBRARY}") + endif() list(APPEND WINDOWS_BINARIES vulkan) endif() diff --git a/tests/clipboard.c b/tests/clipboard.c index a340fa1e9..d6c961ccb 100644 --- a/tests/clipboard.c +++ b/tests/clipboard.c @@ -1,6 +1,6 @@ //======================================================================== // Clipboard test program -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/tests/cursor.c b/tests/cursor.c index f1bcc42f5..71799dc04 100644 --- a/tests/cursor.c +++ b/tests/cursor.c @@ -1,6 +1,6 @@ //======================================================================== // Cursor & input mode tests -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -47,7 +47,7 @@ static double cursor_x; static double cursor_y; static int swap_interval = 1; -static int wait_events = GLFW_FALSE; +static int wait_events = GLFW_TRUE; static int animate_cursor = GLFW_FALSE; static int track_cursor = GLFW_FALSE; static GLFWcursor* standard_cursors[6]; diff --git a/tests/empty.c b/tests/empty.c index a376a4a4e..f4a51b70b 100644 --- a/tests/empty.c +++ b/tests/empty.c @@ -1,6 +1,6 @@ //======================================================================== // Empty event test -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/tests/events.c b/tests/events.c index 5e697f973..674b584e7 100644 --- a/tests/events.c +++ b/tests/events.c @@ -1,6 +1,6 @@ //======================================================================== // Event linter (event spewer) -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/tests/gamma.c b/tests/gamma.c index 28b6c8cdb..a80392f74 100644 --- a/tests/gamma.c +++ b/tests/gamma.c @@ -1,6 +1,6 @@ //======================================================================== // Gamma correction test program -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -43,6 +43,9 @@ static GLfloat gamma_value = 1.0f; static void usage(void) { printf("Usage: gamma [-h] [-f]\n"); + printf("Options:\n"); + printf(" -f create full screen window\n"); + printf(" -h show this help\n"); } static void set_gamma(GLFWwindow* window, float value) @@ -75,6 +78,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, } case GLFW_KEY_KP_ADD: + case GLFW_KEY_UP: case GLFW_KEY_Q: { set_gamma(window, gamma_value + STEP_SIZE); @@ -82,6 +86,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, } case GLFW_KEY_KP_SUBTRACT: + case GLFW_KEY_DOWN: case GLFW_KEY_W: { if (gamma_value - STEP_SIZE > 0.f) diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c index e85b38585..a3e286ff1 100644 --- a/tests/glfwinfo.c +++ b/tests/glfwinfo.c @@ -1,6 +1,6 @@ //======================================================================== // Context creation and information tool -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -357,7 +357,7 @@ static void print_version(void) int main(int argc, char** argv) { - int ch, client, context, major, minor, revision, profile; + int ch, client, major, minor, revision, profile; GLint redbits, greenbits, bluebits, alphabits, depthbits, stencilbits; int list_extensions = GLFW_FALSE, list_layers = GLFW_FALSE; GLenum error; @@ -412,7 +412,7 @@ int main(int argc, char** argv) if (!glfwInit()) exit(EXIT_FAILURE); - while ((ch = getopt_long(argc, argv, "a:b:dfhlm:n:p:s:v", options, NULL)) != -1) + while ((ch = getopt_long(argc, argv, "a:b:c:dfhlm:n:p:s:v", options, NULL)) != -1) { switch (ch) { @@ -636,7 +636,6 @@ int main(int argc, char** argv) // Report client API version client = glfwGetWindowAttrib(window, GLFW_CLIENT_API); - context = glfwGetWindowAttrib(window, GLFW_CONTEXT_CREATION_API); major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR); minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR); revision = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION); diff --git a/tests/icon.c b/tests/icon.c index 781b2cf65..d866ff1a2 100644 --- a/tests/icon.c +++ b/tests/icon.c @@ -1,6 +1,6 @@ //======================================================================== // Window icon test program -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/tests/iconify.c b/tests/iconify.c index 870345987..b7c742367 100644 --- a/tests/iconify.c +++ b/tests/iconify.c @@ -1,6 +1,6 @@ //======================================================================== // Iconify/restore test program -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/tests/joysticks.c b/tests/joysticks.c index 04b578e90..fa9800e9c 100644 --- a/tests/joysticks.c +++ b/tests/joysticks.c @@ -1,6 +1,6 @@ //======================================================================== // Joystick input test -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/tests/monitors.c b/tests/monitors.c index bb051ad0f..d1d581069 100644 --- a/tests/monitors.c +++ b/tests/monitors.c @@ -1,6 +1,6 @@ //======================================================================== // Monitor information tool -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/tests/msaa.c b/tests/msaa.c index 2777937ca..d6e7df328 100644 --- a/tests/msaa.c +++ b/tests/msaa.c @@ -1,6 +1,6 @@ //======================================================================== // Multisample anti-aliasing test -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/tests/reopen.c b/tests/reopen.c index 40f7b6f70..caaf3626e 100644 --- a/tests/reopen.c +++ b/tests/reopen.c @@ -1,6 +1,6 @@ //======================================================================== // Window re-opener (open/close stress test) -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/tests/sharing.c b/tests/sharing.c index dbaf21c1b..a7f1a3193 100644 --- a/tests/sharing.c +++ b/tests/sharing.c @@ -1,6 +1,6 @@ //======================================================================== // Context sharing test program -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/tests/tearing.c b/tests/tearing.c index d2d621b8c..5cd48b3d4 100644 --- a/tests/tearing.c +++ b/tests/tearing.c @@ -1,6 +1,6 @@ //======================================================================== // Vsync enabling test -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -43,7 +43,7 @@ static double frame_rate; static void usage(void) { - printf("Usage: iconify [-h] [-f]\n"); + printf("Usage: tearing [-h] [-f]\n"); printf("Options:\n"); printf(" -f create full screen window\n"); printf(" -h show this help\n"); diff --git a/tests/threads.c b/tests/threads.c index b961a1d1e..699a0ad13 100644 --- a/tests/threads.c +++ b/tests/threads.c @@ -1,6 +1,6 @@ //======================================================================== // Multi-threading test -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/tests/timeout.c b/tests/timeout.c index 83f18998e..4bf05514b 100644 --- a/tests/timeout.c +++ b/tests/timeout.c @@ -1,97 +1,97 @@ -//======================================================================== -// Event wait timeout test -// Copyright (c) Camilla Berglund -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== -// -// This test is intended to verify that waiting for events with timeout works -// -//======================================================================== - -#include -#include - -#include -#include -#include -#include - -static void error_callback(int error, const char* description) -{ - fprintf(stderr, "Error: %s\n", description); -} - -static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) -{ - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) - glfwSetWindowShouldClose(window, GLFW_TRUE); -} - -static float nrand(void) -{ - return (float) rand() / (float) RAND_MAX; -} - -int main(void) -{ - GLFWwindow* window; - - srand((unsigned int) time(NULL)); - - glfwSetErrorCallback(error_callback); - - if (!glfwInit()) - exit(EXIT_FAILURE); - - window = glfwCreateWindow(640, 480, "Event Wait Timeout Test", NULL, NULL); - if (!window) - { - glfwTerminate(); - exit(EXIT_FAILURE); - } - - glfwMakeContextCurrent(window); - gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); - glfwSetKeyCallback(window, key_callback); - - while (!glfwWindowShouldClose(window)) - { - int width, height; - float r = nrand(), g = nrand(), b = nrand(); - float l = (float) sqrt(r * r + g * g + b * b); - - glfwGetFramebufferSize(window, &width, &height); - - glViewport(0, 0, width, height); - glClearColor(r / l, g / l, b / l, 1.f); - glClear(GL_COLOR_BUFFER_BIT); - glfwSwapBuffers(window); - - glfwWaitEventsTimeout(1.0); - } - - glfwDestroyWindow(window); - - glfwTerminate(); - exit(EXIT_SUCCESS); -} - +//======================================================================== +// Event wait timeout test +// Copyright (c) Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +// +// This test is intended to verify that waiting for events with timeout works +// +//======================================================================== + +#include +#include + +#include +#include +#include +#include + +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + +static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) + glfwSetWindowShouldClose(window, GLFW_TRUE); +} + +static float nrand(void) +{ + return (float) rand() / (float) RAND_MAX; +} + +int main(void) +{ + GLFWwindow* window; + + srand((unsigned int) time(NULL)); + + glfwSetErrorCallback(error_callback); + + if (!glfwInit()) + exit(EXIT_FAILURE); + + window = glfwCreateWindow(640, 480, "Event Wait Timeout Test", NULL, NULL); + if (!window) + { + glfwTerminate(); + exit(EXIT_FAILURE); + } + + glfwMakeContextCurrent(window); + gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); + glfwSetKeyCallback(window, key_callback); + + while (!glfwWindowShouldClose(window)) + { + int width, height; + float r = nrand(), g = nrand(), b = nrand(); + float l = (float) sqrt(r * r + g * g + b * b); + + glfwGetFramebufferSize(window, &width, &height); + + glViewport(0, 0, width, height); + glClearColor(r / l, g / l, b / l, 1.f); + glClear(GL_COLOR_BUFFER_BIT); + glfwSwapBuffers(window); + + glfwWaitEventsTimeout(1.0); + } + + glfwDestroyWindow(window); + + glfwTerminate(); + exit(EXIT_SUCCESS); +} + diff --git a/tests/title.c b/tests/title.c index eeb8eef63..9fe67f4e7 100644 --- a/tests/title.c +++ b/tests/title.c @@ -1,6 +1,6 @@ //======================================================================== // UTF-8 window title test -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/tests/windows.c b/tests/windows.c index 21db08d5c..025cce294 100644 --- a/tests/windows.c +++ b/tests/windows.c @@ -1,6 +1,6 @@ //======================================================================== // Simple multi-window test -// Copyright (c) Camilla Berglund +// Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages