diff --git a/CMakeLists.txt b/CMakeLists.txt index 5042ab9c..f5e538bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,6 @@ option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" ${GLFW_STANDALONE}) option(GLFW_BUILD_TESTS "Build the GLFW test programs" ${GLFW_STANDALONE}) option(GLFW_BUILD_DOCS "Build the GLFW documentation" ON) option(GLFW_INSTALL "Generate installation target" ON) -option(GLFW_VULKAN_STATIC "Assume the Vulkan loader is linked with the application" OFF) include(GNUInstallDirs) include(CMakeDependentOption) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 00000000..1bfc5bc5 --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,234 @@ +# Acknowledgements + +GLFW exists because people around the world donated their time and lent their +skills. This list only includes contributions to the main repository and +excludes other invaluable contributions like language bindings and text and +video tutorials. + + - Bobyshev Alexander + - Laurent Aphecetche + - Matt Arsenault + - ashishgamedev + - David Avedissian + - Keith Bauer + - John Bartholomew + - Coşku Baş + - Niklas Behrens + - Andrew Belt + - Nevyn Bengtsson + - Niklas Bergström + - Denis Bernard + - Doug Binks + - blanco + - Waris Boonyasiriwat + - Kyle Brenneman + - Rok Breulj + - Kai Burjack + - Martin Capitanio + - Nicolas Caramelli + - David Carlier + - Arturo Castro + - Chi-kwan Chan + - Joseph Chua + - Ian Clarkson + - Michał Cichoń + - Lambert Clara + - Anna Clarke + - Josh Codd + - Yaron Cohen-Tal + - Omar Cornut + - Andrew Corrigan + - Bailey Cosier + - Noel Cower + - CuriouserThing + - Jason Daly + - Jarrod Davis + - Olivier Delannoy + - Paul R. Deppe + - Michael Dickens + - Роман Донченко + - Mario Dorn + - Wolfgang Draxinger + - Jonathan Dummer + - Ralph Eastwood + - Fredrik Ehnbom + - Robin Eklind + - Jan Ekström + - Siavash Eliasi + - Ahmad Fatoum + - Felipe Ferreira + - Michael Fogleman + - Jason Francis + - Gerald Franz + - Mário Freitas + - GeO4d + - Marcus Geelnard + - ghuser404 + - Charles Giessen + - Ryan C. Gordon + - Stephen Gowen + - Kovid Goyal + - Eloi Marín Gratacós + - Stefan Gustavson + - Andrew Gutekanst + - Stephen Gutekanst + - Jonathan Hale + - hdf89shfdfs + - Sylvain Hellegouarch + - Matthew Henry + - heromyth + - Lucas Hinderberger + - Paul Holden + - Warren Hu + - Charles Huber + - InKryption + - IntellectualKitty + - Aaron Jacobs + - Erik S. V. Jansson + - Toni Jovanoski + - Arseny Kapoulkine + - Cem Karan + - Osman Keskin + - Koray Kilinc + - Josh Kilmer + - Byunghoon Kim + - Cameron King + - Peter Knut + - Christoph Kubisch + - Yuri Kunde Schlesner + - Rokas Kupstys + - Konstantin Käfer + - Eric Larson + - Francis Lecavalier + - Jong Won Lee + - Robin Leffmann + - Glenn Lewis + - Shane Liesegang + - Anders Lindqvist + - Leon Linhart + - Marco Lizza + - Eyal Lotem + - Aaron Loucks + - Luflosi + - lukect + - Tristam MacDonald + - Hans Mackowiak + - Дмитри Малышев + - Zbigniew Mandziejewicz + - Adam Marcus + - Célestin Marot + - Kyle McDonald + - David V. McKay + - David Medlock + - Bryce Mehring + - Jonathan Mercier + - Marcel Metz + - Liam Middlebrook + - Ave Milia + - Jonathan Miller + - Kenneth Miller + - Bruce Mitchener + - Jack Moffitt + - Jeff Molofee + - Alexander Monakov + - Pierre Morel + - Jon Morton + - Pierre Moulon + - Martins Mozeiko + - Pascal Muetschard + - Julian Møller + - ndogxj + - n3rdopolis + - Kristian Nielsen + - Kamil Nowakowski + - onox + - Denis Ovod + - Ozzy + - Andri Pálsson + - luz paz + - Peoro + - Braden Pellett + - Christopher Pelloux + - Arturo J. Pérez + - Vladimir Perminov + - Anthony Pesch + - Orson Peters + - Emmanuel Gil Peyrot + - Cyril Pichard + - Keith Pitt + - Stanislav Podgorskiy + - Konstantin Podsvirov + - Nathan Poirier + - Alexandre Pretyman + - Pablo Prietz + - przemekmirek + - pthom + - Guillaume Racicot + - Philip Rideout + - Eddie Ringle + - Max Risuhin + - Jorge Rodriguez + - Jari Ronkainen + - Luca Rood + - Ed Ropple + - Aleksey Rybalkin + - Mikko Rytkönen + - Riku Salminen + - Brandon Schaefer + - Sebastian Schuberth + - Christian Sdunek + - Matt Sealey + - Steve Sexton + - Arkady Shapkin + - Ali Sherief + - Yoshiki Shibukawa + - Dmitri Shuralyov + - Daniel Skorupski + - Anthony Smith + - Bradley Smith + - Cliff Smolinsky + - Patrick Snape + - Erlend Sogge Heggen + - Julian Squires + - Johannes Stein + - Pontus Stenetorp + - Michael Stocker + - Justin Stoecker + - Elviss Strazdins + - Paul Sultana + - Nathan Sweet + - TTK-Bandit + - Jared Tiala + - Sergey Tikhomirov + - Arthur Tombs + - Ioannis Tsakpinis + - Samuli Tuomola + - Matthew Turner + - urraka + - Elias Vanderstuyft + - Stef Velzel + - Jari Vetoniemi + - Ricardo Vieira + - Nicholas Vitovitch + - Simon Voordouw + - Corentin Wallez + - Torsten Walluhn + - Patrick Walton + - Xo Wang + - Jay Weisskopf + - Frank Wille + - Andy Williams + - Joel Winarske + - Richard A. Wilkes + - Tatsuya Yatagawa + - Ryogo Yoshimura + - Lukas Zanner + - Andrey Zholos + - Aihui Zhu + - Santi Zupancic + - Jonas Ådahl + - Lasse Öörni + - Leonard König + - All the unmentioned and anonymous contributors in the GLFW community, for bug + reports, patches, feedback, testing and encouragement + diff --git a/README.md b/README.md index f2d2d61d..fe222f27 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,11 @@ you have used GLFW 2 in the past, there is a [transition guide](https://www.glfw.org/docs/latest/moving.html) for moving to the GLFW 3 API. +GLFW exists because of the contributions of [many people](CONTRIBUTORS.md) +around the world, whether by reporting bugs, providing community support, adding +features, reviewing or testing code, debugging, proofreading docs, suggesting +features or fixing bugs. + ## Compiling GLFW @@ -126,6 +131,7 @@ information on what to include when reporting a bug. - Added `glfwInitAllocator` for setting a custom memory allocator (#544,#1628,#1947) - Added `GLFWallocator` struct and `GLFWallocatefun`, `GLFWreallocatefun` and `GLFWdeallocatefun` types (#544,#1628,#1947) + - Added `glfwInitVulkanLoader` for using a non-default Vulkan loader (#1374,#1890) - Added `GLFW_RESIZE_NWSE_CURSOR`, `GLFW_RESIZE_NESW_CURSOR`, `GLFW_RESIZE_ALL_CURSOR` and `GLFW_NOT_ALLOWED_CURSOR` cursor shapes (#427) - Added `GLFW_RESIZE_EW_CURSOR` alias for `GLFW_HRESIZE_CURSOR` (#427) @@ -150,6 +156,7 @@ information on what to include when reporting a bug. - Made joystick subsystem initialize at first use (#1284,#1646) - Made `GLFW_DOUBLEBUFFER` a read-only window attribute - Updated the minimum required CMake version to 3.1 + - Updated gamepad mappings from upstream - Disabled tests and examples by default when built as a CMake subdirectory - Renamed `GLFW_USE_WAYLAND` CMake option to `GLFW_BUILD_WAYLAND` (#1958) - Removed `GLFW_USE_OSMESA` CMake option enabling the Null platform (#1958) @@ -195,6 +202,9 @@ information on what to include when reporting a bug. later (#1783,#1796) - [Win32] Bugfix: Compilation with LLVM for Windows failed (#1807,#1824,#1874) - [Win32] Bugfix: The foreground lock timeout was overridden, ignoring the user + - [Win32] Bugfix: Content scale queries could fail silently (#1615) + - [Win32] Bugfix: Content scales could have garbage values if monitor was recently + disconnected (#1615) - [Cocoa] Added support for `VK_EXT_metal_surface` (#1619) - [Cocoa] Added locating the Vulkan loader at runtime in an application bundle - [Cocoa] Moved main menu creation to GLFW initialization time (#1649) @@ -215,7 +225,7 @@ information on what to include when reporting a bug. could leak memory - [Cocoa] Bugfix: Objective-C files were compiled as C with CMake 3.19 (#1787) - [Cocoa] Bugfix: Duplicate video modes were not filtered out (#1830) - - [Cocoa] Bugfix: Menubar was not clickable on macOS 10.15+ until it lost and + - [Cocoa] Bugfix: Menu bar was not clickable on macOS 10.15+ until it lost and regained focus (#1648,#1802) - [Cocoa] Bugfix: Monitor name query could segfault on macOS 11 (#1809,#1833) - [Cocoa] Bugfix: The install name of the installed dylib was relative (#1504) @@ -223,6 +233,7 @@ information on what to include when reporting a bug. related events were emitted - [Cocoa] Bugfix: Moving the cursor programmatically would freeze it for a fraction of a second (#1962) + - [Cocoa] Bugfix: `kIOMasterPortDefault` was deprecated in macOS 12.0 (#1980) - [X11] Bugfix: The CMake files did not check for the XInput headers (#1480) - [X11] Bugfix: Key names were not updated when the keyboard layout changed (#1462,#1528) @@ -245,13 +256,17 @@ information on what to include when reporting a bug. - [X11] Bugfix: XKB path used keysyms instead of physical locations for non-printable keys (#1598) - [X11] Bugfix: Function keys were mapped to `GLFW_KEY_UNKNOWN` for some layout - combinaitons (#1598) + combinations (#1598) - [X11] Bugfix: Keys pressed simultaneously with others were not always reported (#1112,#1415,#1472,#1616) - [X11] Bugfix: Some window attributes were not applied on leaving fullscreen (#1863) - [X11] Bugfix: Changing `GLFW_FLOATING` could leak memory + - [X11] Bugfix: Icon pixel format conversion worked only by accident, relying on + undefined behavior (#1986) + - [X11] Bugfix: Dynamic loading on OpenBSD failed due to soname differences - [Wayland] Added dynamic loading of all Wayland libraries + - [Wayland] Added support for key names via xkbcommon - [Wayland] Removed support for `wl_shell` (#1443) - [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432) - [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled @@ -259,13 +274,24 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: Retrieving partial framebuffer size would segfault - [Wayland] Bugfix: Scrolling offsets were inverted compared to other platforms (#1463) - - [Wayland] Bugfix: Client-Side Decorations were destroyed in the wrong worder + - [Wayland] Bugfix: Client-Side Decorations were destroyed in the wrong order (#1798) - [Wayland] Bugfix: Monitors physical size could report zero (#1784,#1792) - [Wayland] Bugfix: Some keys were not repeating in Wayland (#1908) - [Wayland] Bugfix: Non-arrow cursors are offset from the hotspot (#1706,#1899) + - [Wayland] Bugfix: The `O_CLOEXEC` flag was not defined on FreeBSD + - [Wayland] Bugfix: Key repeat could lead to a race condition (#1710) + - [Wayland] Bugfix: Activating a window would emit two input focus events + - [Wayland] Bugfix: Disable key repeat mechanism when window loses input focus + - [Wayland] Bugfix: Window hiding and showing did not work (#1492,#1731) + - [Wayland] Bugfix: A key being repeated was not released when window lost focus + - [Wayland] Bugfix: Showing a hidden window did not emit a window refresh event + - [Wayland] Bugfix: Full screen window creation did not ignore `GLFW_VISIBLE` + - [Wayland] Bugfix: Some keys were reported as wrong key or `GLFW_KEY_UNKNOWN` + - [Wayland] Bugfix: Text input did not repeat along with key repeat - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled + - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) - [NSGL] Removed enforcement of forward-compatible flag for core contexts - [NSGL] Bugfix: `GLFW_COCOA_RETINA_FRAMEBUFFER` had no effect on newer macOS versions (#1442) @@ -296,227 +322,3 @@ request, please file it in the Finally, if you're interested in helping out with the development of GLFW or porting it to your favorite platform, join us on the forum, GitHub or IRC. - -## Acknowledgements - -GLFW exists because people around the world donated their time and lent their -skills. - - - Bobyshev Alexander - - Laurent Aphecetche - - Matt Arsenault - - ashishgamedev - - David Avedissian - - Keith Bauer - - John Bartholomew - - Coşku Baş - - Niklas Behrens - - Andrew Belt - - Nevyn Bengtsson - - Niklas Bergström - - Denis Bernard - - Doug Binks - - blanco - - Waris Boonyasiriwat - - Kyle Brenneman - - Rok Breulj - - Kai Burjack - - Martin Capitanio - - Nicolas Caramelli - - David Carlier - - Arturo Castro - - Chi-kwan Chan - - Joseph Chua - - Ian Clarkson - - Michał Cichoń - - Lambert Clara - - Anna Clarke - - Yaron Cohen-Tal - - Omar Cornut - - Andrew Corrigan - - Bailey Cosier - - Noel Cower - - CuriouserThing - - Jason Daly - - Jarrod Davis - - Olivier Delannoy - - Paul R. Deppe - - Michael Dickens - - Роман Донченко - - Mario Dorn - - Wolfgang Draxinger - - Jonathan Dummer - - Ralph Eastwood - - Fredrik Ehnbom - - Robin Eklind - - Siavash Eliasi - - Ahmad Fatoum - - Felipe Ferreira - - Michael Fogleman - - Gerald Franz - - Mário Freitas - - GeO4d - - Marcus Geelnard - - Charles Giessen - - Ryan C. Gordon - - Stephen Gowen - - Kovid Goyal - - Eloi Marín Gratacós - - Stefan Gustavson - - Jonathan Hale - - hdf89shfdfs - - Sylvain Hellegouarch - - Matthew Henry - - heromyth - - Lucas Hinderberger - - Paul Holden - - Warren Hu - - Charles Huber - - IntellectualKitty - - Aaron Jacobs - - Erik S. V. Jansson - - Toni Jovanoski - - Arseny Kapoulkine - - Cem Karan - - Osman Keskin - - Koray Kilinc - - Josh Kilmer - - Byunghoon Kim - - Cameron King - - Peter Knut - - Christoph Kubisch - - Yuri Kunde Schlesner - - Rokas Kupstys - - Konstantin Käfer - - Eric Larson - - Francis Lecavalier - - Jong Won Lee - - Robin Leffmann - - Glenn Lewis - - Shane Liesegang - - Anders Lindqvist - - Leon Linhart - - Marco Lizza - - Eyal Lotem - - Aaron Loucks - - Luflosi - - lukect - - Tristam MacDonald - - Hans Mackowiak - - Дмитри Малышев - - Zbigniew Mandziejewicz - - Adam Marcus - - Célestin Marot - - Kyle McDonald - - David V. McKay - - David Medlock - - Bryce Mehring - - Jonathan Mercier - - Marcel Metz - - Liam Middlebrook - - Ave Milia - - Jonathan Miller - - Kenneth Miller - - Bruce Mitchener - - Jack Moffitt - - Jeff Molofee - - Alexander Monakov - - Pierre Morel - - Jon Morton - - Pierre Moulon - - Martins Mozeiko - - Julian Møller - - ndogxj - - n3rdopolis - - Kristian Nielsen - - Kamil Nowakowski - - onox - - Denis Ovod - - Ozzy - - Andri Pálsson - - Peoro - - Braden Pellett - - Christopher Pelloux - - Arturo J. Pérez - - Vladimir Perminov - - Anthony Pesch - - Orson Peters - - Emmanuel Gil Peyrot - - Cyril Pichard - - Keith Pitt - - Stanislav Podgorskiy - - Konstantin Podsvirov - - Nathan Poirier - - Alexandre Pretyman - - Pablo Prietz - - przemekmirek - - pthom - - Guillaume Racicot - - Philip Rideout - - Eddie Ringle - - Max Risuhin - - Jorge Rodriguez - - Jari Ronkainen - - Luca Rood - - Ed Ropple - - Aleksey Rybalkin - - Mikko Rytkönen - - Riku Salminen - - Brandon Schaefer - - Sebastian Schuberth - - Christian Sdunek - - Matt Sealey - - Steve Sexton - - Arkady Shapkin - - Ali Sherief - - Yoshiki Shibukawa - - Dmitri Shuralyov - - Daniel Skorupski - - Anthony Smith - - Bradley Smith - - Cliff Smolinsky - - Patrick Snape - - Erlend Sogge Heggen - - Julian Squires - - Johannes Stein - - Pontus Stenetorp - - Michael Stocker - - Justin Stoecker - - Elviss Strazdins - - Paul Sultana - - Nathan Sweet - - TTK-Bandit - - Jared Tiala - - Sergey Tikhomirov - - Arthur Tombs - - Ioannis Tsakpinis - - Samuli Tuomola - - Matthew Turner - - urraka - - Elias Vanderstuyft - - Stef Velzel - - Jari Vetoniemi - - Ricardo Vieira - - Nicholas Vitovitch - - Simon Voordouw - - Corentin Wallez - - Torsten Walluhn - - Patrick Walton - - Xo Wang - - Jay Weisskopf - - Frank Wille - - Andy Williams - - Joel Winarske - - Richard A. Wilkes - - Tatsuya Yatagawa - - Ryogo Yoshimura - - Lukas Zanner - - Andrey Zholos - - Aihui Zhu - - Santi Zupancic - - Jonas Ådahl - - Lasse Öörni - - Leonard König - - All the unmentioned and anonymous contributors in the GLFW community, for bug - reports, patches, feedback, testing and encouragement - diff --git a/docs/compat.dox b/docs/compat.dox index 5b264b3f..989c4c19 100644 --- a/docs/compat.dox +++ b/docs/compat.dox @@ -104,9 +104,8 @@ integration by libwayland-egl, and keyboard handling by from wayland-protocols to provide additional features if the compositor supports them. -GLFW uses xkbcommon 0.5.0 to provide compose key support. When it has been -built against an older xkbcommon, the compose key will be disabled even if it -has been configured in the compositor. +GLFW uses xkbcommon 0.5.0 to provide key and text input support. Earlier +versions are not supported. GLFW uses the [xdg-shell protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml) diff --git a/docs/compile.dox b/docs/compile.dox index 8f99472e..05da99cf 100644 --- a/docs/compile.dox +++ b/docs/compile.dox @@ -10,8 +10,8 @@ build applications that use GLFW, see @ref build_guide. @section compile_cmake Using CMake -@note GLFW behaves like most other libraries that use CMake so this guide mostly -describes the basic configure/generate/compile sequence. If you are already +GLFW behaves like most other libraries that use CMake so this guide mostly +describes the standard configure, generate and compile sequence. If you are already familiar with this from other projects, you may want to focus on the @ref compile_deps and @ref compile_options sections for GLFW-specific information. @@ -40,7 +40,7 @@ all necessary dependencies for compiling GLFW, but on Unix-like systems like Linux and FreeBSD you will need a few extra packages. -@subsubsection compile_deps_x11 Dependencies for X11 on Unix-like systems +@subsubsection compile_deps_x11 Dependencies for X11 To compile GLFW for X11, you need to have the X11 development packages installed. They are not needed to build or run programs that use GLFW. @@ -74,7 +74,7 @@ install the headers and other development related files for all of X11. Once you have the required dependencies, move on to @ref compile_generate. -@subsubsection compile_deps_wayland Dependencies for Wayland and X11 on Unix-like systems +@subsubsection compile_deps_wayland Dependencies for Wayland and X11 To compile GLFW for both Wayland and X11, you need to have the X11, Wayland and xkbcommon development packages installed. They are not needed to build or run programs that use @@ -131,7 +131,7 @@ A common pattern when building a single configuration is to have a build directory named `build` in the root of the source tree. -@subsubsection compile_generate_gui Generating files with the CMake GUI +@subsubsection compile_generate_gui Generating with the CMake GUI Start the CMake GUI and set the paths to the source and build directories described above. Then press _Configure_ and _Generate_. @@ -148,7 +148,7 @@ Once you have generated the project files or makefiles for your chosen development environment, move on to @ref compile_compile. -@subsubsection compile_generate_cli Generating files with the CMake command-line tool +@subsubsection compile_generate_cli Generating with command-line CMake To make a build directory, pass the source and build directories to the `cmake` command. These can be relative or absolute paths. The build directory is @@ -273,12 +273,8 @@ __GLFW_BUILD_DOCS__ determines whether the GLFW documentation is built along with the library. This is enabled by default if [Doxygen](https://www.doxygen.nl/) is found by CMake during configuration. -@anchor GLFW_VULKAN_STATIC -__GLFW_VULKAN_STATIC__ determines whether to use the Vulkan loader linked -directly with the application. This is disabled by default. - -@subsection compile_options_win32 Windows specific CMake options +@subsection compile_options_win32 Win32 specific CMake options @anchor GLFW_BUILD_WIN32 __GLFW_BUILD_WIN32__ determines whether to include support for Win32 when compiling the @@ -383,10 +379,6 @@ attempts to detect the appropriate platform at initialization. If you are building GLFW as a shared library / dynamic library / DLL then you must also define @b _GLFW_BUILD_DLL. Otherwise, you must not define it. -If you are linking the Vulkan loader directly with your application then you -must also define @b _GLFW_VULKAN_STATIC. Otherwise, GLFW will attempt to use the -external version. - If you are using a custom name for the Vulkan, EGL, GLX, OSMesa, OpenGL, GLESv1 or GLESv2 library, you can override the default names by defining those you need of @b _GLFW_VULKAN_LIBRARY, @b _GLFW_EGL_LIBRARY, @b _GLFW_GLX_LIBRARY, @b diff --git a/docs/extra.css b/docs/extra.css index 05c1938c..1a287343 100644 --- a/docs/extra.css +++ b/docs/extra.css @@ -1 +1,2 @@ -.sm-dox,.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted,.sm-dox ul a:hover{background:none;text-shadow:none}.sm-dox a span.sub-arrow{border-color:#f2f2f2 transparent transparent transparent}.sm-dox a span.sub-arrow:active,.sm-dox a span.sub-arrow:focus,.sm-dox a span.sub-arrow:hover,.sm-dox a:hover span.sub-arrow{border-color:#f60 transparent transparent transparent}.sm-dox ul a span.sub-arrow:active,.sm-dox ul a span.sub-arrow:focus,.sm-dox ul a span.sub-arrow:hover,.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent #f60}.sm-dox ul a:hover{background:#666;text-shadow:none}.sm-dox ul.sm-nowrap a{color:#4d4d4d;text-shadow:none}#main-nav,#main-menu,#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code,.markdownTable code{background:none}#titlearea,.footer,.contents,div.header,.memdoc,table.doxtable td,table.doxtable th,table.markdownTable td,table.markdownTable th,hr,.memSeparator{border:none}#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.reflist dt a.el,.levels span,.directory .levels span{text-shadow:none}.memdoc,dl.reflist dd{box-shadow:none}div.headertitle,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,table.doxtable code,table.markdownTable code{padding:0}#nav-path,.directory .levels,span.lineno{display:none}html,#titlearea,.footer,tr.even,.directory tr.even,.doxtable tr:nth-child(even),tr.markdownTableBody:nth-child(even),.mdescLeft,.mdescRight,.memItemLeft,.memItemRight,code,.markdownTableRowEven{background:#f2f2f2}body{color:#4d4d4d}h1,h2,h2.groupheader,h3,div.toc h3,h4,h5,h6,strong,em{color:#1a1a1a;border-bottom:none}h1{padding-top:.5em;font-size:180%}h2{padding-top:.5em;margin-bottom:0;font-size:140%}h3{padding-top:.5em;margin-bottom:0;font-size:110%}.glfwheader{font-size:16px;min-height:64px;max-width:920px;padding:0 32px;margin:0 auto;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:center;align-content:stretch}#glfwhome{line-height:64px;padding-right:48px;color:#666;font-size:2.5em;background:url("https://www.glfw.org/css/arrow.png") no-repeat right}.glfwnavbar{list-style-type:none;margin:0 0 0 auto;float:right}#glfwhome,.glfwnavbar li{float:left}.glfwnavbar a,.glfwnavbar a:visited{line-height:64px;margin-left:2em;display:block;color:#666}.glfwnavbar{padding-left:0}#glfwhome,.glfwnavbar a,.glfwnavbar a:visited{transition:.35s ease}#titlearea,.footer{color:#666}address.footer{text-align:center;padding:2em;margin-top:3em}#top{background:#666}#main-nav{max-width:960px;margin:0 auto;font-size:13px}#main-menu{max-width:920px;margin:0 auto;font-size:13px}.memtitle{display:none}.memproto,.memname{font-weight:bold;text-shadow:none}#main-menu{min-height:36px;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:center;align-content:stretch}#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li{color:#f2f2f2}#main-menu li ul.sm-nowrap li a{color:#4d4d4d}#main-menu li ul.sm-nowrap li a:hover{color:#f60}#main-menu>li:last-child{margin:0 0 0 auto}.contents{min-height:590px}div.contents,div.header{max-width:920px;margin:0 auto;padding:0 32px;background:#fff none}table.doxtable th,table.markdownTable th,dl.reflist dt{background:linear-gradient(to bottom, #ffa733 0%, #ff6600 100%);box-shadow:inset 0 0 32px #f60;text-shadow:0 -1px 1px #b34700;text-align:left;color:#fff}dl.reflist dt a.el{color:#f60;padding:.2em;border-radius:4px;background-color:#ffe0cc}div.toc{float:none;width:auto}div.toc h3{font-size:1.17em}div.toc ul{padding-left:1.5em}div.toc li{font-size:1em;padding-left:0;list-style-type:disc}div.toc,.memproto,div.qindex,div.ah{background:linear-gradient(to bottom, #f2f2f2 0%, #e6e6e6 100%);box-shadow:inset 0 0 32px #e6e6e6;text-shadow:0 1px 1px #fff;color:#1a1a1a;border:2px solid #e6e6e6;border-radius:4px}.paramname{color:#803300}dl.reflist dt{border:2px solid #f60;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom:none}dl.reflist dd{border:2px solid #f60;border-bottom-right-radius:4px;border-bottom-left-radius:4px;border-top:none}table.doxtable,table.markdownTable{border-collapse:inherit;border-spacing:0;border:2px solid #f60;border-radius:4px}a,a:hover,a:visited,a:visited:hover,.contents a:visited,.el,a.el:visited,#glfwhome:hover,#main-menu a:hover,span.lineno a:hover{color:#f60;text-decoration:none}div.directory{border-collapse:inherit;border-spacing:0;border:2px solid #f60;border-radius:4px}hr,.memSeparator{height:2px;background:linear-gradient(to right, #f2f2f2 0%, #d9d9d9 50%, #f2f2f2 100%)}dl.note,dl.pre,dl.post,dl.invariant{background:linear-gradient(to bottom, #ddfad1 0%, #cbf7ba 100%);box-shadow:inset 0 0 32px #baf5a3;color:#1e5309;border:2px solid #afe699}dl.warning,dl.attention{background:linear-gradient(to bottom, #fae8d1 0%, #f7ddba 100%);box-shadow:inset 0 0 32px #f5d1a3;color:#533309;border:2px solid #e6c499}dl.deprecated,dl.bug{background:linear-gradient(to bottom, #fad1e3 0%, #f7bad6 100%);box-shadow:inset 0 0 32px #f5a3c8;color:#53092a;border:2px solid #e699bb}dl.todo,dl.test{background:linear-gradient(to bottom, #d1ecfa 0%, #bae3f7 100%);box-shadow:inset 0 0 32px #a3daf5;color:#093a53;border:2px solid #99cce6}dl.note,dl.pre,dl.post,dl.invariant,dl.warning,dl.attention,dl.deprecated,dl.bug,dl.todo,dl.test{border-radius:4px;padding:1em;text-shadow:0 1px 1px #fff;margin:1em 0}.note a,.pre a,.post a,.invariant a,.warning a,.attention a,.deprecated a,.bug a,.todo a,.test a,.note a:visited,.pre a:visited,.post a:visited,.invariant a:visited,.warning a:visited,.attention a:visited,.deprecated a:visited,.bug a:visited,.todo a:visited,.test a:visited{color:inherit}div.line{line-height:inherit}div.fragment,pre.fragment{background:#f2f2f2;border-radius:4px;border:none;padding:1em;overflow:auto;border-left:4px solid #ccc;margin:1em 0}.lineno a,.lineno a:visited,.line,pre.fragment{color:#4d4d4d}span.preprocessor,span.comment{color:#007899}a.code,a.code:visited{color:#e64500}span.keyword,span.keywordtype,span.keywordflow{color:#404040;font-weight:bold}span.stringliteral{color:#360099}code{padding:.1em;border-radius:4px}/*# sourceMappingURL=extra.css.map */ +.sm-dox,.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted,.sm-dox ul a:hover{background:none;text-shadow:none}.sm-dox a span.sub-arrow{border-color:#f2f2f2 transparent transparent transparent}.sm-dox a span.sub-arrow:active,.sm-dox a span.sub-arrow:focus,.sm-dox a span.sub-arrow:hover,.sm-dox a:hover span.sub-arrow{border-color:#f60 transparent transparent transparent}.sm-dox ul a span.sub-arrow:active,.sm-dox ul a span.sub-arrow:focus,.sm-dox ul a span.sub-arrow:hover,.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent #f60}.sm-dox ul a:hover{background:#666;text-shadow:none}.sm-dox ul.sm-nowrap a{color:#4d4d4d;text-shadow:none}#main-nav,#main-menu,#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code,.markdownTable code{background:none}#titlearea,.footer,.contents,div.header,.memdoc,table.doxtable td,table.doxtable th,table.markdownTable td,table.markdownTable th,hr,.memSeparator{border:none}#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.reflist dt a.el,.levels span,.directory .levels span{text-shadow:none}.memdoc,dl.reflist dd{box-shadow:none}div.headertitle,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,table.doxtable code,table.markdownTable code{padding:0}#nav-path,.directory .levels,span.lineno{display:none}html,#titlearea,.footer,tr.even,.directory tr.even,.doxtable tr:nth-child(even),tr.markdownTableBody:nth-child(even),.mdescLeft,.mdescRight,.memItemLeft,.memItemRight,code,.markdownTableRowEven{background:#f2f2f2}body{color:#4d4d4d}div.title{font-size:170%;margin:1em 0 0.5em 0}h1,h2,h2.groupheader,h3,div.toc h3,h4,h5,h6,strong,em{color:#1a1a1a;border-bottom:none}h1{padding-top:0.5em;font-size:150%}h2{padding-top:0.5em;margin-bottom:0;font-size:130%}h3{padding-top:0.5em;margin-bottom:0;font-size:110%}.glfwheader{font-size:16px;min-height:64px;max-width:920px;padding:0 32px;margin:0 auto;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:center;align-content:stretch}#glfwhome{line-height:64px;padding-right:48px;color:#666;font-size:2.5em;background:url("https://www.glfw.org/css/arrow.png") no-repeat right}.glfwnavbar{list-style-type:none;margin:0 0 0 auto;float:right}#glfwhome,.glfwnavbar li{float:left}.glfwnavbar a,.glfwnavbar a:visited{line-height:64px;margin-left:2em;display:block;color:#666}.glfwnavbar{padding-left:0}#glfwhome,.glfwnavbar a,.glfwnavbar a:visited{transition:.35s ease}#titlearea,.footer{color:#666}address.footer{text-align:center;padding:2em;margin-top:3em}#top{background:#666}#main-nav{max-width:960px;margin:0 auto;font-size:13px}#main-menu{max-width:920px;margin:0 auto;font-size:13px}.memtitle{display:none}.memproto,.memname{font-weight:bold;text-shadow:none}#main-menu{min-height:36px;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:center;align-content:stretch}#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li{color:#f2f2f2}#main-menu li ul.sm-nowrap li a{color:#4d4d4d}#main-menu li ul.sm-nowrap li a:hover{color:#f60}#main-menu>li:last-child{margin:0 0 0 auto}.contents{min-height:590px}div.contents,div.header{max-width:920px;margin:0 auto;padding:0 32px;background:#fff none}table.doxtable th,table.markdownTable th,dl.reflist dt{background:linear-gradient(to bottom, #ffa733 0%, #f60 100%);box-shadow:inset 0 0 32px #f60;text-shadow:0 -1px 1px #b34700;text-align:left;color:#fff}dl.reflist dt a.el{color:#f60;padding:.2em;border-radius:4px;background-color:#ffe0cc}div.toc{float:right;width:35%}@media screen and (max-width: 600px){div.toc{float:none;width:inherit;margin:0}}div.toc h3{font-size:1.17em}div.toc ul{padding-left:1.5em}div.toc li{font-size:1em;padding-left:0;list-style-type:disc}div.toc li.level2,div.toc li.level3{margin-left:0.5em}div.toc,.memproto,div.qindex,div.ah{background:linear-gradient(to bottom, #f2f2f2 0%, #e6e6e6 100%);box-shadow:inset 0 0 32px #e6e6e6;text-shadow:0 1px 1px #fff;color:#1a1a1a;border:2px solid #e6e6e6;border-radius:4px}.paramname{color:#803300}dl.reflist dt{border:2px solid #f60;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom:none}dl.reflist dd{border:2px solid #f60;border-bottom-right-radius:4px;border-bottom-left-radius:4px;border-top:none}table.doxtable,table.markdownTable{border-collapse:inherit;border-spacing:0;border:2px solid #f60;border-radius:4px}a,a:hover,a:visited,a:visited:hover,.contents a:visited,.el,a.el:visited,#glfwhome:hover,#main-menu a:hover,span.lineno a:hover{color:#f60;text-decoration:none}div.directory{border-collapse:inherit;border-spacing:0;border:2px solid #f60;border-radius:4px}hr,.memSeparator{height:2px;background:linear-gradient(to right, #f2f2f2 0%, #d9d9d9 50%, #f2f2f2 100%)}dl.note,dl.pre,dl.post,dl.invariant{background:linear-gradient(to bottom, #ddfad1 0%, #cbf7ba 100%);box-shadow:inset 0 0 32px #baf5a3;color:#1e5309;border:2px solid #afe699}dl.warning,dl.attention{background:linear-gradient(to bottom, #fae8d1 0%, #f7ddba 100%);box-shadow:inset 0 0 32px #f5d1a3;color:#533309;border:2px solid #e6c499}dl.deprecated,dl.bug{background:linear-gradient(to bottom, #fad1e3 0%, #f7bad6 100%);box-shadow:inset 0 0 32px #f5a3c8;color:#53092a;border:2px solid #e699bb}dl.todo,dl.test{background:linear-gradient(to bottom, #d1ecfa 0%, #bae3f7 100%);box-shadow:inset 0 0 32px #a3daf5;color:#093a53;border:2px solid #99cce6}dl.note,dl.pre,dl.post,dl.invariant,dl.warning,dl.attention,dl.deprecated,dl.bug,dl.todo,dl.test{border-radius:4px;padding:1em;text-shadow:0 1px 1px #fff;margin:1em 0}.note a,.pre a,.post a,.invariant a,.warning a,.attention a,.deprecated a,.bug a,.todo a,.test a,.note a:visited,.pre a:visited,.post a:visited,.invariant a:visited,.warning a:visited,.attention a:visited,.deprecated a:visited,.bug a:visited,.todo a:visited,.test a:visited{color:inherit}div.line{line-height:inherit}div.fragment,pre.fragment{background:#f2f2f2;border-radius:4px;border:none;padding:1em;overflow:auto;border-left:4px solid #ccc;margin:1em 0}.lineno a,.lineno a:visited,.line,pre.fragment{color:#4d4d4d}span.preprocessor,span.comment{color:#007899}a.code,a.code:visited{color:#e64500}span.keyword,span.keywordtype,span.keywordflow{color:#404040;font-weight:bold}span.stringliteral{color:#360099}code{padding:.1em;border-radius:4px} +/*# sourceMappingURL=extra.css.map */ diff --git a/docs/extra.css.map b/docs/extra.css.map index 7d10c5e2..4d9333c2 100644 --- a/docs/extra.css.map +++ b/docs/extra.css.map @@ -1 +1,7 @@ -{"version":3,"sourceRoot":"","sources":["extra.scss"],"names":[],"mappings":"AA8EA,4GACI,gBACA,iBAGJ,yBACC,yDAGD,6HACC,sDAGD,yIACC,sDAGD,mBACI,WA9EuB,KA+EvB,iBAGJ,uBACC,MAzFoB,QA0FjB,iBAGJ,6UACC,gBAGD,mJACC,YAGD,yHACC,iBAGD,sBACC,gBAGD,4LACC,UAGD,yCACC,aAGD,kMACC,WAnHgC,QAsHjC,KACC,MA1HoB,QA6HrB,sDACC,MA/Ge,QAgHf,mBAGD,GACE,iBACA,eAGF,GACE,iBACA,gBACA,eAGF,GACE,iBACA,gBACA,eAGF,YACC,eACA,gBACA,gBACA,eACA,cAEA,aACA,mBACA,eACA,2BACA,mBACA,sBAGD,UACC,iBACA,mBACA,MA/J0B,KAgK1B,gBACA,qEAGD,YACC,qBACA,kBACA,YAGD,yBACC,WAGD,oCACC,iBACA,gBACA,cACA,MAlL0B,KAqL3B,YACC,eAGD,8CACC,qBAGD,mBACC,MA9L0B,KAiM3B,eACC,kBACA,YACA,eAGD,KACC,WAxM0B,KA2M3B,UACC,gBACA,cACA,eAGD,WACC,gBACA,cACA,eAGD,UACI,aAGJ,mBACI,iBACA,iBAGJ,WACC,gBACA,aACA,mBACA,eACA,2BACA,mBACA,sBAGD,mEACC,MA9OgC,QAiPjC,gCACC,MArPoB,QAwPrB,sCACC,MAjOoB,KAoOrB,yBACC,kBAGD,UACC,iBAGD,wBACC,gBACA,cACA,eACA,qBAGD,uDACC,gEACA,+BACA,+BACA,gBACA,MArPgB,KAwPjB,mBACC,MA5PoB,KA6PpB,aACA,kBACA,yBAGD,QACC,WACA,WAGD,WACC,iBAGD,WACC,mBAGD,WACC,cACA,eACA,qBAGD,oCACC,gEACA,kCACA,2BACA,MAlSe,QAmSf,yBACA,kBAGD,WACC,MA3QuB,QA8QxB,cACC,sBACA,2BACA,4BACA,mBAGD,cACC,sBACA,+BACA,8BACA,gBAGD,mCACC,wBACA,iBACA,sBACA,kBAGD,gIACC,MAxToB,KAyTpB,qBAGD,cACC,wBACA,iBACA,sBACA,kBAGD,iBACC,WACA,4EAGD,oCApSC,gEACA,kCACA,cACA,yBAqSD,wBAxSC,gEACA,kCACA,cACA,yBAySD,qBA5SC,gEACA,kCACA,cACA,yBA6SD,gBAhTC,gEACA,kCACA,cACA,yBAiTD,iGACC,kBACA,YACA,2BACA,aAGD,kRACC,cAGD,SACC,oBAGD,0BACC,mBACA,kBACA,YACA,YACA,cACA,2BACA,aAGD,+CACC,MA1YoB,QA6YrB,+BACC,cAGD,sBACC,cAGD,+CACC,cACA,iBAGD,mBACC,cAGD,KACC,aACA","file":"extra.css"} \ No newline at end of file +{ +"version": 3, +"mappings": "AA8EA,2GAA4G,CAC3G,UAAU,CAAC,IAAI,CACf,WAAW,CAAC,IAAI,CAGjB,wBAAyB,CACxB,YAAY,CAAC,2CAAsD,CAGpE,4HAA6H,CAC5H,YAAY,CAAC,wCAAuD,CAGrE,wIAAyI,CACxI,YAAY,CAAC,wCAAuD,CAGrE,kBAAmB,CAClB,UAAU,CA9EgB,IAAa,CA+EvC,WAAW,CAAC,IAAI,CAGjB,sBAAuB,CACtB,KAAK,CAzFe,OAAa,CA0FjC,WAAW,CAAC,IAAI,CAGjB,4UAA6U,CAC5U,UAAU,CAAC,IAAI,CAGhB,kJAAmJ,CAClJ,MAAM,CAAC,IAAI,CAGZ,wHAAyH,CACxH,WAAW,CAAC,IAAI,CAGjB,qBAAsB,CACrB,UAAU,CAAC,IAAI,CAGhB,2LAA4L,CAC3L,OAAO,CAAC,CAAC,CAGV,wCAAyC,CACxC,OAAO,CAAC,IAAI,CAGb,iMAAkM,CACjM,UAAU,CApGW,OAA+B,CAuGrD,IAAK,CACJ,KAAK,CA1He,OAAa,CA6HlC,SAAU,CACN,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,aAAa,CAGzB,qDAAsD,CACrD,KAAK,CApHU,OAAa,CAqH5B,aAAa,CAAC,IAAI,CAGnB,EAAG,CACF,WAAW,CAAC,KAAK,CACjB,SAAS,CAAC,IAAI,CAGf,EAAG,CACF,WAAW,CAAC,KAAK,CACjB,aAAa,CAAC,CAAC,CACf,SAAS,CAAC,IAAI,CAGf,EAAG,CACF,WAAW,CAAC,KAAK,CACjB,aAAa,CAAC,CAAC,CACf,SAAS,CAAC,IAAI,CAGf,WAAY,CACX,SAAS,CAAC,IAAI,CACd,UAAU,CAAC,IAAI,CACf,SAAS,CAAC,KAAK,CACf,OAAO,CAAC,MAAM,CACd,MAAM,CAAC,MAAM,CAEb,OAAO,CAAE,IAAI,CACb,cAAc,CAAE,GAAG,CACnB,SAAS,CAAE,IAAI,CACf,eAAe,CAAE,UAAU,CAC3B,WAAW,CAAE,MAAM,CACnB,aAAa,CAAE,OAAO,CAGvB,SAAU,CACT,WAAW,CAAC,IAAI,CAChB,aAAa,CAAC,IAAI,CAClB,KAAK,CApKqB,IAAa,CAqKvC,SAAS,CAAC,KAAK,CACf,UAAU,CAAC,yDAAyD,CAGrE,WAAY,CACX,eAAe,CAAC,IAAI,CACpB,MAAM,CAAC,UAAU,CACjB,KAAK,CAAC,KAAK,CAGZ,wBAAyB,CACxB,KAAK,CAAC,IAAI,CAGX,mCAAoC,CACnC,WAAW,CAAC,IAAI,CAChB,WAAW,CAAC,GAAG,CACf,OAAO,CAAC,KAAK,CACb,KAAK,CAvLqB,IAAa,CA0LxC,WAAY,CACX,YAAY,CAAE,CAAC,CAGhB,6CAA8C,CAC7C,UAAU,CAAC,SAAS,CAGrB,kBAAmB,CAClB,KAAK,CAnMqB,IAAa,CAsMxC,cAAe,CACd,UAAU,CAAC,MAAM,CACjB,OAAO,CAAC,GAAG,CACX,UAAU,CAAC,GAAG,CAGf,IAAK,CACJ,UAAU,CA7MgB,IAAa,CAgNxC,SAAU,CACT,SAAS,CAAC,KAAK,CACf,MAAM,CAAC,MAAM,CACb,SAAS,CAAC,IAAI,CAGf,UAAW,CACV,SAAS,CAAC,KAAK,CACf,MAAM,CAAC,MAAM,CACb,SAAS,CAAC,IAAI,CAGf,SAAU,CACT,OAAO,CAAC,IAAI,CAGb,kBAAmB,CAClB,WAAW,CAAC,IAAI,CAChB,WAAW,CAAC,IAAI,CAGjB,UAAW,CACV,UAAU,CAAC,IAAI,CACf,OAAO,CAAE,IAAI,CACb,cAAc,CAAE,GAAG,CACnB,SAAS,CAAE,IAAI,CACf,eAAe,CAAE,UAAU,CAC3B,WAAW,CAAE,MAAM,CACnB,aAAa,CAAE,OAAO,CAGvB,kEAAmE,CAClE,KAAK,CApOgB,OAA+B,CAuOrD,+BAAgC,CAC/B,KAAK,CA1Pe,OAAa,CA6PlC,qCAAsC,CACrC,KAAK,CA1NoB,IAAsB,CA6NhD,wBAA2B,CAC1B,MAAM,CAAE,UAAU,CAGnB,SAAU,CACT,UAAU,CAAC,KAAK,CAGjB,uBAAwB,CACvB,SAAS,CAAC,KAAK,CACf,MAAM,CAAC,MAAM,CACb,OAAO,CAAC,MAAM,CACd,UAAU,CAAC,SAA8B,CAG1C,sDAAuD,CACtD,UAAU,CAAC,iDAAoF,CAC/F,UAAU,CAAC,mBAAuC,CAClD,WAAW,CAAC,kBAAgD,CAC5D,UAAU,CAAC,IAAI,CACf,KAAK,CAlPa,IAAe,CAqPlC,kBAAmB,CAClB,KAAK,CArPoB,IAAsB,CAsP/C,OAAO,CAAC,IAAI,CACZ,aAAa,CAAC,GAAG,CACjB,gBAAgB,CAAC,OAAiC,CAGnD,OAAQ,CACP,KAAK,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CAGV,oCAAoC,CACnC,OAAQ,CACP,KAAK,CAAC,IAAI,CACV,KAAK,CAAC,OAAO,CACb,MAAM,CAAC,CAAC,EAIV,UAAW,CACV,SAAS,CAAC,MAAM,CAGjB,UAAW,CACV,YAAY,CAAC,KAAK,CAGnB,UAAW,CACV,SAAS,CAAC,GAAG,CACb,YAAY,CAAC,CAAC,CACd,eAAe,CAAC,IAAI,CAIjB,mCAAqB,CACjB,WAAW,CAAC,KAAK,CAIzB,mCAAoC,CACnC,UAAU,CAAC,oDAAgF,CAC3F,UAAU,CAAC,sBAAqC,CAChD,WAAW,CAAC,cAA8C,CAC1D,KAAK,CArTU,OAAa,CAsT5B,MAAM,CAAC,iBAAgC,CACvC,aAAa,CAAC,GAAG,CAGlB,UAAW,CACV,KAAK,CA9RkB,OAAgC,CAiSxD,aAAc,CACb,MAAM,CAAC,cAA+B,CACtC,sBAAsB,CAAC,GAAG,CAC1B,uBAAuB,CAAC,GAAG,CAC3B,aAAa,CAAC,IAAI,CAGnB,aAAc,CACb,MAAM,CAAC,cAA+B,CACtC,0BAA0B,CAAC,GAAG,CAC9B,yBAAyB,CAAC,GAAG,CAC7B,UAAU,CAAC,IAAI,CAGhB,kCAAmC,CAClC,eAAe,CAAC,OAAO,CACvB,cAAc,CAAC,CAAC,CAChB,MAAM,CAAC,cAA+B,CACtC,aAAa,CAAC,GAAG,CAGlB,+HAAgI,CAC/H,KAAK,CA/ToB,IAAsB,CAgU/C,eAAe,CAAC,IAAI,CAGrB,aAAc,CACb,eAAe,CAAC,OAAO,CACvB,cAAc,CAAC,CAAC,CAChB,MAAM,CAAC,cAA+B,CACtC,aAAa,CAAC,GAAG,CAGlB,gBAAiB,CAChB,MAAM,CAAC,GAAG,CACV,UAAU,CAAC,gEAAiH,CAG7H,mCAAoC,CAvTnC,UAAU,CAAC,oDAAuE,CAClF,UAAU,CAAC,sBAAsC,CACjD,KAAK,CAAC,OAAwB,CAC9B,MAAM,CAAC,iBAAmD,CAwT3D,uBAAwB,CA3TvB,UAAU,CAAC,oDAAuE,CAClF,UAAU,CAAC,sBAAsC,CACjD,KAAK,CAAC,OAAwB,CAC9B,MAAM,CAAC,iBAAmD,CA4T3D,oBAAqB,CA/TpB,UAAU,CAAC,oDAAuE,CAClF,UAAU,CAAC,sBAAsC,CACjD,KAAK,CAAC,OAAwB,CAC9B,MAAM,CAAC,iBAAmD,CAgU3D,eAAgB,CAnUf,UAAU,CAAC,oDAAuE,CAClF,UAAU,CAAC,sBAAsC,CACjD,KAAK,CAAC,OAAwB,CAC9B,MAAM,CAAC,iBAAmD,CAoU3D,gGAAiG,CAChG,aAAa,CAAC,GAAG,CACjB,OAAO,CAAC,GAAG,CACX,WAAW,CAAC,cAAwB,CACpC,MAAM,CAAC,KAAK,CAGb,iRAAkR,CACjR,KAAK,CAAC,OAAO,CAGd,QAAS,CACR,WAAW,CAAC,OAAO,CAGpB,yBAA0B,CACzB,UAAU,CAAC,OAAa,CACxB,aAAa,CAAC,GAAG,CACjB,MAAM,CAAC,IAAI,CACX,OAAO,CAAC,GAAG,CACX,QAAQ,CAAC,IAAI,CACb,WAAW,CAAC,cAAuB,CACnC,MAAM,CAAC,KAAK,CAGb,8CAA+C,CAC9C,KAAK,CA7Ze,OAAa,CAgalC,8BAA+B,CAC9B,KAAK,CAAC,OAAiB,CAGxB,qBAAsB,CACrB,KAAK,CAAC,OAAgB,CAGvB,8CAA+C,CAC9C,KAAK,CAAC,OAA+B,CACrC,WAAW,CAAC,IAAI,CAGjB,kBAAmB,CAClB,KAAK,CAAC,OAAiB,CAGxB,IAAK,CACJ,OAAO,CAAC,IAAI,CACZ,aAAa,CAAC,GAAG", +"sources": ["extra.scss"], +"names": [], +"file": "extra.css" +} diff --git a/docs/extra.scss b/docs/extra.scss index 6c5f3c25..43fe9831 100644 --- a/docs/extra.scss +++ b/docs/extra.scss @@ -135,6 +135,11 @@ body { color:$default-text-color; } +div.title { + font-size: 170%; + margin: 1em 0 0.5em 0; +} + h1,h2,h2.groupheader,h3,div.toc h3,h4,h5,h6,strong,em { color:$heading-color; border-bottom:none; @@ -142,13 +147,13 @@ h1,h2,h2.groupheader,h3,div.toc h3,h4,h5,h6,strong,em { h1 { padding-top:0.5em; - font-size:180%; + font-size:150%; } h2 { padding-top:0.5em; margin-bottom:0; - font-size:140%; + font-size:130%; } h3 { @@ -293,8 +298,16 @@ dl.reflist dt a.el { } div.toc { - float:none; - width:auto; + float:right; + width:35%; +} + +@media screen and (max-width:600px) { + div.toc { + float:none; + width:inherit; + margin:0; + } } div.toc h3 { @@ -311,6 +324,12 @@ div.toc li { list-style-type:disc; } +div.toc { + li.level2, li.level3 { + margin-left:0.5em; + } +} + div.toc,.memproto,div.qindex,div.ah { background:linear-gradient(to bottom,$toc-background-color2 0%,$toc-background-color1 100%); box-shadow:inset 0 0 32px $toc-background-color1; diff --git a/docs/intro.dox b/docs/intro.dox index c50a3722..5cbd7eb0 100644 --- a/docs/intro.dox +++ b/docs/intro.dox @@ -35,6 +35,7 @@ successfully initialized, and only from the main thread. - @ref glfwSetErrorCallback - @ref glfwInitHint - @ref glfwInitAllocator + - @ref glfwInitVulkanLoader - @ref glfwInit - @ref glfwTerminate diff --git a/docs/news.dox b/docs/news.dox index e1160b54..decd888d 100644 --- a/docs/news.dox +++ b/docs/news.dox @@ -150,6 +150,17 @@ GLFW_TRANSPARENT_FRAMEBUFFER on Windows 7 if DWM transparency is off @subsection removals_34 Removals in 3.4 +@subsubsection vulkan_static_34 GLFW_VULKAN_STATIC CMake option has been removed + +This option was used to compile GLFW directly linked with the Vulkan loader, instead of +using dynamic loading to get hold of `vkGetInstanceProcAddr` at initialization. This is +now done by calling the @ref glfwInitVulkanLoader function before initialization. + +If you need backward compatibility, this macro can still be defined for GLFW 3.4 and will +have no effect. The call to @ref glfwInitVulkanLoader can be conditionally enabled in +your code by checking the @ref GLFW_VERSION_MAJOR and @ref GLFW_VERSION_MINOR macros. + + @subsubsection osmesa_option_34 GLFW_USE_OSMESA CMake option has been removed This option was used to compile GLFW for the Null platform. The Null platform is now @@ -177,6 +188,7 @@ then GLFW will fail to initialize. - @ref glfwInitAllocator - @ref glfwGetPlatform - @ref glfwPlatformSupported + - @ref glfwInitVulkanLoader @subsubsection types_34 New types in version 3.4 diff --git a/docs/vulkan.dox b/docs/vulkan.dox index 68e3d5fe..31891036 100644 --- a/docs/vulkan.dox +++ b/docs/vulkan.dox @@ -29,28 +29,34 @@ are also guides for the other areas of the GLFW API. - @ref input_guide -@section vulkan_loader Linking against the Vulkan loader +@section vulkan_loader Finding the Vulkan loader -By default, GLFW will look for the Vulkan loader on demand at runtime via its -standard name (`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other -Unix-like systems and `libvulkan.1.dylib` on macOS). This means that GLFW does -not need to be linked against the loader. However, it also means that if you -are using the static library form of the Vulkan loader GLFW will either fail to -find it or (worse) use the wrong one. +GLFW itself does not ever need to be linked against the Vulkan loader. -The @ref GLFW_VULKAN_STATIC CMake option makes GLFW call the Vulkan loader -directly instead of dynamically loading it at runtime. Not linking against the -Vulkan loader will then be a compile-time error. +By default, GLFW will load the Vulkan loader dynamically at runtime via its standard name: +`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other Unix-like systems and +`libvulkan.1.dylib` on macOS. -@macos Because the Vulkan loader and ICD are not installed globally on macOS, -you need to set up the application bundle according to the LunarG SDK -documentation. This is explained in more detail in the +@macos GLFW will also look up and search the executable subdirectory of your application +bundle. + +If your code is using a Vulkan loader with a different name or in a non-standard location +you will need to direct GLFW to it. Pass your version of `vkGetInstanceProcAddr` to @ref +glfwInitVulkanLoader before initializing GLFW and it will use that function for all Vulkan +entry point retrieval. This prevents GLFW from dynamically loading the Vulkan loader. + +@code +glfwInitVulkanLoader(vkGetInstanceProcAddr); +@endcode + +@macos To make your application be redistributable you will need to set up the application +bundle according to the LunarG SDK documentation. This is explained in more detail in the [SDK documentation for macOS](https://vulkan.lunarg.com/doc/sdk/latest/mac/getting_started.html). -@section vulkan_include Including the Vulkan and GLFW header files +@section vulkan_include Including the Vulkan header file -To include the Vulkan header, define @ref GLFW_INCLUDE_VULKAN before including +To have GLFW include the Vulkan header, define @ref GLFW_INCLUDE_VULKAN before including the GLFW header. @code @@ -66,8 +72,13 @@ your own custom Vulkan header then do this before the GLFW header. #include @endcode -Unless a Vulkan header is included, either by the GLFW header or above it, any -GLFW functions that take or return Vulkan types will not be declared. +Unless a Vulkan header is included, either by the GLFW header or above it, the following +GLFW functions will not be declared, as depend on Vulkan types. + + - @ref glfwInitVulkanLoader + - @ref glfwGetInstanceProcAddress + - @ref glfwGetPhysicalDevicePresentationSupport + - @ref glfwCreateWindowSurface The `VK_USE_PLATFORM_*_KHR` macros do not need to be defined for the Vulkan part of GLFW to work. Define them only if you are using these extensions directly. diff --git a/docs/window.dox b/docs/window.dox index 5e482431..32271e3a 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -447,7 +447,7 @@ The no error mode for OpenGL and OpenGL ES is described in detail by the extension. -@subsubsection window_hints_win32 Windows specific window hints +@subsubsection window_hints_win32 Win32 specific hints @anchor GLFW_WIN32_KEYBOARD_MENU_hint __GLFW_WIN32_KEYBOARD_MENU__ specifies whether to allow access to the window @@ -455,7 +455,7 @@ menu via the Alt+Space and Alt-and-then-Space keyboard shortcuts. This is ignored on other platforms. -@subsubsection window_hints_osx macOS specific window hints +@subsubsection window_hints_osx macOS specific hints @anchor GLFW_COCOA_RETINA_FRAMEBUFFER_hint __GLFW_COCOA_RETINA_FRAMEBUFFER__ specifies whether to use full resolution diff --git a/examples/splitview.c b/examples/splitview.c index 4f0a8a98..990df12c 100644 --- a/examples/splitview.c +++ b/examples/splitview.c @@ -2,7 +2,7 @@ // This is an example program for the GLFW library // // The program uses a "split window" view, rendering four views of the -// same scene in one window (e.g. uesful for 3D modelling software). This +// same scene in one window (e.g. useful for 3D modelling software). This // demo uses scissors to separate the four different rendering areas from // each other. // diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index efd54e0c..72d5fa71 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -190,6 +190,9 @@ extern "C" { #else /*__APPLE__*/ #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif #endif /*__APPLE__*/ @@ -372,7 +375,7 @@ extern "C" { * * The naming of the key codes follow these rules: * - The US keyboard layout is used - * - Names of printable alpha-numeric characters are used (e.g. "A", "R", + * - Names of printable alphanumeric characters are used (e.g. "A", "R", * "3", etc.) * - For non-alphanumeric characters, Unicode:ish names are used (e.g. * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not @@ -1025,7 +1028,7 @@ extern "C" { * and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib). */ #define GLFW_CONTEXT_VERSION_MINOR 0x00022003 -/*! @brief Context client API revision number hint and attribute. +/*! @brief Context client API revision number attribute. * * Context client API revision number * [attribute](@ref GLFW_CONTEXT_REVISION_attrib). @@ -2221,6 +2224,54 @@ GLFWAPI void glfwInitHint(int hint, int value); */ GLFWAPI void glfwInitAllocator(const GLFWallocator* allocator); +#if defined(VK_VERSION_1_0) + +/*! @brief Sets the desired Vulkan `vkGetInstanceProcAddr` function. + * + * This function sets the `vkGetInstanceProcAddr` function that GLFW will use for all + * Vulkan related entry point queries. + * + * This feature is mostly useful on macOS, if your copy of the Vulkan loader is in + * a location where GLFW cannot find it through dynamic loading, or if you are still + * using the static library version of the loader. + * + * If set to `NULL`, GLFW will try to load the Vulkan loader dynamically by its standard + * name and get this function from there. This is the default behavior. + * + * The standard name of the loader is `vulkan-1.dll` on Windows, `libvulkan.so.1` on + * Linux and other Unix-like systems and `libvulkan.1.dylib` on macOS. If your code is + * also loading it via these names then you probably don't need to use this function. + * + * The function address you set is never reset by GLFW, but it only takes effect during + * initialization. Once GLFW has been initialized, any updates will be ignored until the + * library is terminated and initialized again. + * + * @param[in] loader The address of the function to use, or `NULL`. + * + * @par Loader function signature + * @code + * PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance instance, const char* name) + * @endcode + * For more information about this function, see the + * [Vulkan Registry](https://www.khronos.org/registry/vulkan/). + * + * @errors None. + * + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref vulkan_loader + * @sa @ref glfwInit + * + * @since Added in version 3.4. + * + * @ingroup init + */ +GLFWAPI void glfwInitVulkanLoader(PFN_vkGetInstanceProcAddr loader); + +#endif /*VK_VERSION_1_0*/ + /*! @brief Retrieves the version of the GLFW library. * * This function retrieves the major, minor and revision numbers of the GLFW @@ -3713,6 +3764,11 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * GLFW_PLATFORM_ERROR. * + * @remark @wayland Because Wayland wants every frame of the desktop to be + * complete, this function does not immediately make the window visible. + * Instead it will become visible the next time the window framebuffer is + * updated after this call. + * * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide @@ -5652,6 +5708,8 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string); * joystick is not present, does not have a mapping or an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref GLFW_INVALID_ENUM. + * * @pointer_lifetime The returned string is allocated and freed by GLFW. You * should not free it yourself. It is valid until the specified joystick is * disconnected, the gamepad mappings are updated or the library is terminated. @@ -5741,8 +5799,8 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string); * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. * * @pointer_lifetime The returned string is allocated and freed by GLFW. You * should not free it yourself. It is valid until the next call to @ref @@ -6136,9 +6194,6 @@ GLFWAPI int glfwVulkanSupported(void); * returned array, as it is an error to specify an extension more than once in * the `VkInstanceCreateInfo` struct. * - * @remark @macos GLFW currently supports both the `VK_MVK_macos_surface` and - * the newer `VK_EXT_metal_surface` extensions. - * * @pointer_lifetime The returned array is allocated and freed by GLFW. You * should not free it yourself. It is guaranteed to be valid only until the * library is terminated. @@ -6277,17 +6332,20 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should * eliminate almost all occurrences of these errors. * - * @remark @macos This function currently only supports the - * `VK_MVK_macos_surface` extension from MoltenVK. + * @remark @macos GLFW prefers the `VK_EXT_metal_surface` extension, with the + * `VK_MVK_macos_surface` extension as a fallback. The name of the selected + * extension, if any, is included in the array returned by @ref + * glfwGetRequiredInstanceExtensions. * * @remark @macos This function creates and sets a `CAMetalLayer` instance for * the window content view, which is required for MoltenVK to function. * - * @remark @x11 GLFW by default attempts to use the `VK_KHR_xcb_surface` - * extension, if available. You can make it prefer the `VK_KHR_xlib_surface` - * extension by setting the + * @remark @x11 By default GLFW prefers the `VK_KHR_xcb_surface` extension, + * with the `VK_KHR_xlib_surface` extension as a fallback. You can make + * `VK_KHR_xlib_surface` the preferred extension by setting the * [GLFW_X11_XCB_VULKAN_SURFACE](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint) init - * hint. + * hint. The name of the selected extension, if any, is included in the array + * returned by @ref glfwGetRequiredInstanceExtensions. * * @thread_safety This function may be called from any thread. For * synchronization details of Vulkan objects, see the Vulkan specification. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0ab57255..a07ca931 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,10 +65,6 @@ endif() if (GLFW_BUILD_WAYLAND) include(CheckIncludeFiles) include(CheckFunctionExists) - check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H) - if (HAVE_XKBCOMMON_COMPOSE_H) - target_compile_definitions(glfw PRIVATE HAVE_XKBCOMMON_COMPOSE_H) - endif() check_function_exists(memfd_create HAVE_MEMFD_CREATE) if (HAVE_MEMFD_CREATE) target_compile_definitions(glfw PRIVATE HAVE_MEMFD_CREATE) @@ -155,11 +151,6 @@ if (CMAKE_VERSION VERSION_LESS "3.16" AND APPLE) LANGUAGE C) endif() -if (GLFW_VULKAN_STATIC) - target_compile_definitions(glfw PRIVATE _GLFW_VULKAN_STATIC) - list(APPEND glfw_PKG_DEPS "vulkan") -endif() - if (GLFW_BUILD_WIN32) list(APPEND glfw_PKG_LIBS "-lgdi32") endif() @@ -178,7 +169,7 @@ if (GLFW_BUILD_WAYLAND) wayland-client>=0.2.7 wayland-cursor>=0.2.7 wayland-egl>=0.2.7 - xkbcommon) + xkbcommon>=0.5.0) target_include_directories(glfw PRIVATE ${Wayland_INCLUDE_DIRS}) @@ -199,31 +190,37 @@ if (GLFW_BUILD_X11) if (NOT X11_Xrandr_INCLUDE_PATH) message(FATAL_ERROR "RandR headers not found; install libxrandr development package") endif() + target_include_directories(glfw PRIVATE "${X11_Xrandr_INCLUDE_PATH}") # Check for Xinerama (legacy multi-monitor support) if (NOT X11_Xinerama_INCLUDE_PATH) message(FATAL_ERROR "Xinerama headers not found; install libxinerama development package") endif() + target_include_directories(glfw PRIVATE "${X11_Xinerama_INCLUDE_PATH}") # Check for Xkb (X keyboard extension) if (NOT X11_Xkb_INCLUDE_PATH) message(FATAL_ERROR "XKB headers not found; install X11 development package") endif() + target_include_directories(glfw PRIVATE "${X11_Xkb_INCLUDE_PATH}") # Check for Xcursor (cursor creation from RGBA images) if (NOT X11_Xcursor_INCLUDE_PATH) message(FATAL_ERROR "Xcursor headers not found; install libxcursor development package") endif() + target_include_directories(glfw PRIVATE "${X11_Xcursor_INCLUDE_PATH}") # Check for XInput (modern HID input) if (NOT X11_Xi_INCLUDE_PATH) message(FATAL_ERROR "XInput headers not found; install libxi development package") endif() + target_include_directories(glfw PRIVATE "${X11_Xi_INCLUDE_PATH}") # Check for X Shape (custom window input shape) if (NOT X11_Xshape_INCLUDE_PATH) message(FATAL_ERROR "X Shape headers not found; install libxext development package") endif() + target_include_directories(glfw PRIVATE "${X11_Xshape_INCLUDE_PATH}") endif() if (UNIX AND NOT APPLE) diff --git a/src/cocoa_init.m b/src/cocoa_init.m index e97d9596..48bc2c29 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -75,7 +75,6 @@ static void changeToResourcesDirectory(void) // static void createMenuBar(void) { - size_t i; NSString* appName = nil; NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary]; NSString* nameKeys[] = @@ -87,7 +86,7 @@ static void createMenuBar(void) // Try to figure out what the calling application is called - for (i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++) + for (size_t i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++) { id name = bundleInfo[nameKeys[i]]; if (name && @@ -177,8 +176,6 @@ static void createMenuBar(void) // static void createKeyTables(void) { - int scancode; - memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes)); memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes)); @@ -297,7 +294,7 @@ static void createKeyTables(void) _glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY; _glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT; - for (scancode = 0; scancode < 256; scancode++) + for (int scancode = 0; scancode < 256; scancode++) { // Store the reverse translation for faster key name lookup if (_glfw.ns.keycodes[scancode] >= 0) @@ -403,9 +400,7 @@ static GLFWbool initializeTIS(void) - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { - _GLFWwindow* window; - - for (window = _glfw.windowListHead; window; window = window->next) + for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) _glfwInputWindowCloseRequest(window); return NSTerminateCancel; @@ -413,9 +408,7 @@ static GLFWbool initializeTIS(void) - (void)applicationDidChangeScreenParameters:(NSNotification *) notification { - _GLFWwindow* window; - - for (window = _glfw.windowListHead; window; window = window->next) + for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) { if (window->context.client != GLFW_NO_API) [window->context.nsgl.object update]; @@ -450,9 +443,7 @@ static GLFWbool initializeTIS(void) - (void)applicationDidHide:(NSNotification *)notification { - int i; - - for (i = 0; i < _glfw.monitorCount; i++) + for (int i = 0; i < _glfw.monitorCount; i++) _glfwRestoreVideoModeCocoa(_glfw.monitors[i]); } diff --git a/src/cocoa_joystick.m b/src/cocoa_joystick.m index 74f20d02..e09e1efa 100644 --- a/src/cocoa_joystick.m +++ b/src/cocoa_joystick.m @@ -96,20 +96,18 @@ static CFComparisonResult compareElements(const void* fp, // static void closeJoystick(_GLFWjoystick* js) { - int i; - if (!js->present) return; - for (i = 0; i < CFArrayGetCount(js->ns.axes); i++) + for (int i = 0; i < CFArrayGetCount(js->ns.axes); i++) _glfw_free((void*) CFArrayGetValueAtIndex(js->ns.axes, i)); CFRelease(js->ns.axes); - for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++) + for (int i = 0; i < CFArrayGetCount(js->ns.buttons); i++) _glfw_free((void*) CFArrayGetValueAtIndex(js->ns.buttons, i)); CFRelease(js->ns.buttons); - for (i = 0; i < CFArrayGetCount(js->ns.hats); i++) + for (int i = 0; i < CFArrayGetCount(js->ns.hats); i++) _glfw_free((void*) CFArrayGetValueAtIndex(js->ns.hats, i)); CFRelease(js->ns.hats); @@ -127,7 +125,6 @@ static void matchCallback(void* context, int jid; char name[256]; char guid[33]; - CFIndex i; CFTypeRef property; uint32_t vendor = 0, product = 0, version = 0; _GLFWjoystick* js; @@ -185,7 +182,7 @@ static void matchCallback(void* context, CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone); - for (i = 0; i < CFArrayGetCount(elements); i++) + for (CFIndex i = 0; i < CFArrayGetCount(elements); i++) { IOHIDElementRef native = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i); @@ -290,9 +287,7 @@ static void removeCallback(void* context, void* sender, IOHIDDeviceRef device) { - int jid; - - for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) + for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) { if (_glfw.joysticks[jid].ns.device == device) { @@ -386,9 +381,7 @@ GLFWbool _glfwInitJoysticksCocoa(void) void _glfwTerminateJoysticksCocoa(void) { - int jid; - - for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) + for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) closeJoystick(_glfw.joysticks + jid); if (_glfw.ns.hidManager) @@ -403,9 +396,7 @@ int _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode) { if (mode & _GLFW_POLL_AXES) { - CFIndex i; - - for (i = 0; i < CFArrayGetCount(js->ns.axes); i++) + for (CFIndex i = 0; i < CFArrayGetCount(js->ns.axes); i++) { _GLFWjoyelementNS* axis = (_GLFWjoyelementNS*) CFArrayGetValueAtIndex(js->ns.axes, i); @@ -430,9 +421,7 @@ int _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode) if (mode & _GLFW_POLL_BUTTONS) { - CFIndex i; - - for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++) + for (CFIndex i = 0; i < CFArrayGetCount(js->ns.buttons); i++) { _GLFWjoyelementNS* button = (_GLFWjoyelementNS*) CFArrayGetValueAtIndex(js->ns.buttons, i); @@ -441,7 +430,7 @@ int _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode) _glfwInputJoystickButton(js, (int) i, state); } - for (i = 0; i < CFArrayGetCount(js->ns.hats); i++) + for (CFIndex i = 0; i < CFArrayGetCount(js->ns.hats); i++) { const int states[9] = { diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 2109a7fe..70c75aa3 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -58,7 +58,7 @@ static char* getMonitorName(CGDirectDisplayID displayID, NSScreen* screen) io_service_t service; CFDictionaryRef info; - if (IOServiceGetMatchingServices(kIOMasterPortDefault, + if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("IODisplayConnect"), &it) != 0) { @@ -231,7 +231,7 @@ static double getFallbackRefreshRate(CGDirectDisplayID displayID) io_iterator_t it; io_service_t service; - if (IOServiceGetMatchingServices(kIOMasterPortDefault, + if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("IOFramebuffer"), &it) != 0) { diff --git a/src/egl_context.c b/src/egl_context.c index 593a153c..89ea78fa 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -231,6 +231,15 @@ static void swapBuffersEGL(_GLFWwindow* window) return; } +#if defined(_GLFW_WAYLAND) + if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND) + { + // NOTE: Swapping buffers on a hidden window on Wayland makes it visible + if (!window->wl.visible) + return; + } +#endif + eglSwapBuffers(_glfw.egl.display, window->context.egl.surface); } @@ -316,6 +325,8 @@ GLFWbool _glfwInitEGL(void) "libEGL.dylib", #elif defined(__CYGWIN__) "libEGL-1.so", +#elif defined(__OpenBSD__) + "libEGL.so", #else "libEGL.so.1", #endif @@ -472,6 +483,8 @@ GLFWbool _glfwInitEGL(void) extensionSupportedEGL("EGL_KHR_get_all_proc_addresses"); _glfw.egl.KHR_context_flush_control = extensionSupportedEGL("EGL_KHR_context_flush_control"); + _glfw.egl.EXT_present_opaque = + extensionSupportedEGL("EGL_EXT_present_opaque"); return GLFW_TRUE; } @@ -646,6 +659,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, if (!fbconfig->doublebuffer) setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER); + if (_glfw.egl.EXT_present_opaque) + setAttrib(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent); + setAttrib(EGL_NONE, EGL_NONE); native = _glfw.platform.getEGLNativeWindow(window); @@ -686,6 +702,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, "libGLES_CM.dll", #elif defined(_GLFW_COCOA) "libGLESv1_CM.dylib", +#elif defined(__OpenBSD__) + "libGLESv1_CM.so", #else "libGLESv1_CM.so.1", "libGLES_CM.so.1", @@ -703,6 +721,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, "libGLESv2.dylib", #elif defined(__CYGWIN__) "libGLESv2-2.so", +#elif defined(__OpenBSD__) + "libGLESv2.so", #else "libGLESv2.so.2", #endif @@ -714,6 +734,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, _GLFW_OPENGL_LIBRARY, #elif defined(_GLFW_WIN32) #elif defined(_GLFW_COCOA) +#elif defined(__OpenBSD__) + "libGL.so", #else "libGL.so.1", #endif @@ -821,7 +843,7 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle) _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); - if (window->context.client != GLFW_EGL_CONTEXT_API) + if (window->context.source != GLFW_EGL_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return EGL_NO_CONTEXT; @@ -835,7 +857,7 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle) _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); - if (window->context.client != GLFW_EGL_CONTEXT_API) + if (window->context.source != GLFW_EGL_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return EGL_NO_SURFACE; diff --git a/src/glx_context.c b/src/glx_context.c index 734c818a..9c032552 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -55,7 +55,7 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* nativeConfigs; _GLFWfbconfig* usableConfigs; const _GLFWfbconfig* closest; - int i, nativeCount, usableCount; + int nativeCount, usableCount; const char* vendor; GLFWbool trustWindowBit = GLFW_TRUE; @@ -76,7 +76,7 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired, usableConfigs = _glfw_calloc(nativeCount, sizeof(_GLFWfbconfig)); usableCount = 0; - for (i = 0; i < nativeCount; i++) + for (int i = 0; i < nativeCount; i++) { const GLXFBConfig n = nativeConfigs[i]; _GLFWfbconfig* u = usableConfigs + usableCount; @@ -258,13 +258,14 @@ static void destroyContextGLX(_GLFWwindow* window) // GLFWbool _glfwInitGLX(void) { - int i; const char* sonames[] = { #if defined(_GLFW_GLX_LIBRARY) _GLFW_GLX_LIBRARY, #elif defined(__CYGWIN__) "libGL-1.so", +#elif defined(__OpenBSD__) + "libGL.so", #else "libGL.so.1", "libGL.so", @@ -275,7 +276,7 @@ GLFWbool _glfwInitGLX(void) if (_glfw.glx.handle) return GLFW_TRUE; - for (i = 0; sonames[i]; i++) + for (int i = 0; sonames[i]; i++) { _glfw.glx.handle = _glfwPlatformLoadModule(sonames[i]); if (_glfw.glx.handle) @@ -687,7 +688,7 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle) return NULL; } - if (window->context.client != GLFW_NATIVE_CONTEXT_API) + if (window->context.source != GLFW_NATIVE_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return NULL; @@ -707,7 +708,7 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle) return None; } - if (window->context.client != GLFW_NATIVE_CONTEXT_API) + if (window->context.source != GLFW_NATIVE_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return None; diff --git a/src/init.c b/src/init.c index cdb7ae41..80f424a8 100644 --- a/src/init.c +++ b/src/init.c @@ -36,16 +36,15 @@ #include -// The global variables below comprise all mutable global data in GLFW -// -// Any other global variable is a bug +// NOTE: The global variables below comprise all mutable global data in GLFW +// Any other mutable global variable is a bug -// Global state shared between compilation units of GLFW +// This contains all mutable state shared between compilation units of GLFW // _GLFWlibrary _glfw = { GLFW_FALSE }; // These are outside of _glfw so they can be used before initialization and -// after termination +// after termination without special handling when _glfw is cleared to zero // static _GLFWerror _glfwMainThreadError; static GLFWerrorfun _glfwErrorCallback; @@ -55,6 +54,7 @@ static _GLFWinitconfig _glfwInitHints = GLFW_TRUE, // hat buttons GLFW_ANGLE_PLATFORM_TYPE_NONE, // ANGLE backend GLFW_ANY_PLATFORM, // preferred platform + NULL, // vkGetInstanceProcAddr function { GLFW_TRUE, // macOS menu bar GLFW_TRUE // macOS bundle chdir @@ -140,6 +140,37 @@ static void terminate(void) ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// +// Encode a Unicode code point to a UTF-8 stream +// Based on cutef8 by Jeff Bezanson (Public Domain) +// +size_t _glfwEncodeUTF8(char* s, uint32_t codepoint) +{ + size_t count = 0; + + if (codepoint < 0x80) + s[count++] = (char) codepoint; + else if (codepoint < 0x800) + { + s[count++] = (codepoint >> 6) | 0xc0; + s[count++] = (codepoint & 0x3f) | 0x80; + } + else if (codepoint < 0x10000) + { + s[count++] = (codepoint >> 12) | 0xe0; + s[count++] = ((codepoint >> 6) & 0x3f) | 0x80; + s[count++] = (codepoint & 0x3f) | 0x80; + } + else if (codepoint < 0x110000) + { + s[count++] = (codepoint >> 18) | 0xf0; + s[count++] = ((codepoint >> 12) & 0x3f) | 0x80; + s[count++] = ((codepoint >> 6) & 0x3f) | 0x80; + s[count++] = (codepoint & 0x3f) | 0x80; + } + + return count; +} + char* _glfw_strdup(const char* source) { const size_t length = strlen(source); @@ -404,6 +435,11 @@ GLFWAPI void glfwInitAllocator(const GLFWallocator* allocator) memset(&_glfwInitAllocator, 0, sizeof(GLFWallocator)); } +GLFWAPI void glfwInitVulkanLoader(PFN_vkGetInstanceProcAddr loader) +{ + _glfwInitHints.vulkanLoader = loader; +} + GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev) { if (major != NULL) @@ -440,7 +476,7 @@ GLFWAPI int glfwGetError(const char** description) GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun) { - _GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun); + _GLFW_SWAP(GLFWerrorfun, _glfwErrorCallback, cbfun); return cbfun; } diff --git a/src/input.c b/src/input.c index f2604c86..6a2c3e1d 100644 --- a/src/input.c +++ b/src/input.c @@ -295,7 +295,7 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m // Notifies shared code of a Unicode codepoint input event // The 'plain' parameter determines whether to emit a regular character event // -void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain) +void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool plain) { if (codepoint < 32 || (codepoint > 126 && codepoint < 160)) return; @@ -522,90 +522,102 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) _GLFW_REQUIRE_INIT(); - if (mode == GLFW_CURSOR) + switch (mode) { - if (value != GLFW_CURSOR_NORMAL && - value != GLFW_CURSOR_HIDDEN && - value != GLFW_CURSOR_DISABLED) + case GLFW_CURSOR: { - _glfwInputError(GLFW_INVALID_ENUM, - "Invalid cursor mode 0x%08X", - value); - return; - } - - if (window->cursorMode == value) - return; - - window->cursorMode = value; - - _glfw.platform.getCursorPos(window, - &window->virtualCursorPosX, - &window->virtualCursorPosY); - _glfw.platform.setCursorMode(window, value); - } - else if (mode == GLFW_STICKY_KEYS) - { - value = value ? GLFW_TRUE : GLFW_FALSE; - if (window->stickyKeys == value) - return; - - if (!value) - { - int i; - - // Release all sticky keys - for (i = 0; i <= GLFW_KEY_LAST; i++) + if (value != GLFW_CURSOR_NORMAL && + value != GLFW_CURSOR_HIDDEN && + value != GLFW_CURSOR_DISABLED) { - if (window->keys[i] == _GLFW_STICK) - window->keys[i] = GLFW_RELEASE; + _glfwInputError(GLFW_INVALID_ENUM, + "Invalid cursor mode 0x%08X", + value); + return; } + + if (window->cursorMode == value) + return; + + window->cursorMode = value; + + _glfw.platform.getCursorPos(window, + &window->virtualCursorPosX, + &window->virtualCursorPosY); + _glfw.platform.setCursorMode(window, value); + return; } - window->stickyKeys = value; - } - else if (mode == GLFW_STICKY_MOUSE_BUTTONS) - { - value = value ? GLFW_TRUE : GLFW_FALSE; - if (window->stickyMouseButtons == value) - return; - - if (!value) + case GLFW_STICKY_KEYS: { - int i; + value = value ? GLFW_TRUE : GLFW_FALSE; + if (window->stickyKeys == value) + return; - // Release all sticky mouse buttons - for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) + if (!value) { - if (window->mouseButtons[i] == _GLFW_STICK) - window->mouseButtons[i] = GLFW_RELEASE; + 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; + return; } - window->stickyMouseButtons = value; - } - else if (mode == GLFW_LOCK_KEY_MODS) - { - window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE; - } - else if (mode == GLFW_RAW_MOUSE_MOTION) - { - if (!_glfw.platform.rawMouseMotionSupported()) + case GLFW_STICKY_MOUSE_BUTTONS: { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Raw mouse motion is not supported on this system"); + value = value ? GLFW_TRUE : GLFW_FALSE; + 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; return; } - value = value ? GLFW_TRUE : GLFW_FALSE; - if (window->rawMouseMotion == value) + case GLFW_LOCK_KEY_MODS: + { + window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE; return; + } - window->rawMouseMotion = value; - _glfw.platform.setRawMouseMotion(window, value); + case GLFW_RAW_MOUSE_MOTION: + { + if (!_glfw.platform.rawMouseMotionSupported()) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Raw mouse motion is not supported on this system"); + return; + } + + value = value ? GLFW_TRUE : GLFW_FALSE; + if (window->rawMouseMotion == value) + return; + + window->rawMouseMotion = value; + _glfw.platform.setRawMouseMotion(window, value); + return; + } } - else - _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); + + _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); } GLFWAPI int glfwRawMouseMotionSupported(void) @@ -856,7 +868,7 @@ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun) assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.key, cbfun); + _GLFW_SWAP(GLFWkeyfun, window->callbacks.key, cbfun); return cbfun; } @@ -866,7 +878,7 @@ GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun) assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.character, cbfun); + _GLFW_SWAP(GLFWcharfun, window->callbacks.character, cbfun); return cbfun; } @@ -876,7 +888,7 @@ GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmods assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.charmods, cbfun); + _GLFW_SWAP(GLFWcharmodsfun, window->callbacks.charmods, cbfun); return cbfun; } @@ -887,7 +899,7 @@ GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle, assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.mouseButton, cbfun); + _GLFW_SWAP(GLFWmousebuttonfun, window->callbacks.mouseButton, cbfun); return cbfun; } @@ -898,7 +910,7 @@ GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle, assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.cursorPos, cbfun); + _GLFW_SWAP(GLFWcursorposfun, window->callbacks.cursorPos, cbfun); return cbfun; } @@ -909,7 +921,7 @@ GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle, assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.cursorEnter, cbfun); + _GLFW_SWAP(GLFWcursorenterfun, window->callbacks.cursorEnter, cbfun); return cbfun; } @@ -920,7 +932,7 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle, assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.scroll, cbfun); + _GLFW_SWAP(GLFWscrollfun, window->callbacks.scroll, cbfun); return cbfun; } @@ -930,7 +942,7 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun) assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.drop, cbfun); + _GLFW_SWAP(GLFWdropfun, window->callbacks.drop, cbfun); return cbfun; } @@ -1154,7 +1166,7 @@ GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun) if (!initJoysticks()) return NULL; - _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun); + _GLFW_SWAP(GLFWjoystickfun, _glfw.callbacks.joystick, cbfun); return cbfun; } diff --git a/src/internal.h b/src/internal.h index 45ae45ab..f8548fa3 100644 --- a/src/internal.h +++ b/src/internal.h @@ -177,6 +177,7 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint); #define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098 #define EGL_PLATFORM_X11_EXT 0x31d5 #define EGL_PLATFORM_WAYLAND_EXT 0x31d8 +#define EGL_PRESENT_OPAQUE_EXT 0x31df #define EGL_PLATFORM_ANGLE_ANGLE 0x3202 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203 #define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320d @@ -323,15 +324,9 @@ typedef struct VkExtensionProperties typedef void (APIENTRY * PFN_vkVoidFunction)(void); -#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 +typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*); +typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*); +#define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr #include "platform.h" @@ -357,12 +352,12 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void); } // Swaps the provided pointers -#define _GLFW_SWAP_POINTERS(x, y) \ - { \ - void* t; \ - t = x; \ - x = y; \ - y = t; \ +#define _GLFW_SWAP(type, x, y) \ + { \ + type t; \ + t = x; \ + x = y; \ + y = t; \ } // Per-thread error structure @@ -383,6 +378,7 @@ struct _GLFWinitconfig GLFWbool hatButtons; int angleType; int platformID; + PFN_vkGetInstanceProcAddr vulkanLoader; struct { GLFWbool menubar; GLFWbool chdir; @@ -808,6 +804,7 @@ struct _GLFWlibrary GLFWbool EXT_platform_base; GLFWbool EXT_platform_x11; GLFWbool EXT_platform_wayland; + GLFWbool EXT_present_opaque; GLFWbool ANGLE_platform_angle; GLFWbool ANGLE_platform_angle_opengl; GLFWbool ANGLE_platform_angle_d3d; @@ -854,10 +851,7 @@ struct _GLFWlibrary GLFWbool available; void* handle; char* extensions[2]; -#if !defined(_GLFW_VULKAN_STATIC) - PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties; PFN_vkGetInstanceProcAddr GetInstanceProcAddr; -#endif GLFWbool KHR_surface; GLFWbool KHR_win32_surface; GLFWbool MVK_macos_surface; @@ -925,7 +919,7 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor); void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods); void _glfwInputChar(_GLFWwindow* window, - unsigned int codepoint, int mods, GLFWbool plain); + uint32_t codepoint, int mods, GLFWbool plain); void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset); void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods); void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos); @@ -1001,6 +995,8 @@ GLFWbool _glfwInitVulkan(int mode); void _glfwTerminateVulkan(void); const char* _glfwGetVulkanResultString(VkResult result); +size_t _glfwEncodeUTF8(char* s, uint32_t codepoint); + char* _glfw_strdup(const char* source); float _glfw_fminf(float a, float b); float _glfw_fmaxf(float a, float b); diff --git a/src/linux_joystick.c b/src/linux_joystick.c index 6ea63942..da04e9c3 100644 --- a/src/linux_joystick.c +++ b/src/linux_joystick.c @@ -363,9 +363,7 @@ GLFWbool _glfwInitJoysticksLinux(void) void _glfwTerminateJoysticksLinux(void) { - int jid; - - for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) + for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) { _GLFWjoystick* js = _glfw.joysticks + jid; if (js->present) diff --git a/src/monitor.c b/src/monitor.c index 31921b46..e6f47d65 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -419,7 +419,7 @@ GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle) GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(_glfw.callbacks.monitor, cbfun); + _GLFW_SWAP(GLFWmonitorfun, _glfw.callbacks.monitor, cbfun); return cbfun; } diff --git a/src/nsgl_context.m b/src/nsgl_context.m index 694937c6..f85ef67b 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -365,7 +365,7 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle) return nil; } - if (window->context.client != GLFW_NATIVE_CONTEXT_API) + if (window->context.source != GLFW_NATIVE_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return nil; diff --git a/src/null_platform.h b/src/null_platform.h index 30e50a85..fca7c11f 100644 --- a/src/null_platform.h +++ b/src/null_platform.h @@ -116,7 +116,6 @@ GLFWbool _glfwRawMouseMotionSupportedNull(void); void _glfwShowWindowNull(_GLFWwindow* window); void _glfwRequestWindowAttentionNull(_GLFWwindow* window); void _glfwRequestWindowAttentionNull(_GLFWwindow* window); -void _glfwUnhideWindowNull(_GLFWwindow* window); void _glfwHideWindowNull(_GLFWwindow* window); void _glfwFocusWindowNull(_GLFWwindow* window); int _glfwWindowFocusedNull(_GLFWwindow* window); diff --git a/src/null_window.c b/src/null_window.c index 10c5293f..710d4c9c 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -409,10 +409,6 @@ void _glfwRequestWindowAttentionNull(_GLFWwindow* window) { } -void _glfwUnhideWindowNull(_GLFWwindow* window) -{ -} - void _glfwHideWindowNull(_GLFWwindow* window) { if (_glfw.null.focusedWindow == window) diff --git a/src/osmesa_context.c b/src/osmesa_context.c index cf742f89..161d9fd8 100644 --- a/src/osmesa_context.c +++ b/src/osmesa_context.c @@ -124,6 +124,8 @@ GLFWbool _glfwInitOSMesa(void) "libOSMesa.8.dylib", #elif defined(__CYGWIN__) "libOSMesa-8.so", +#elif defined(__OpenBSD__) + "libOSMesa.so", #else "libOSMesa.so.8", "libOSMesa.so.6", @@ -302,7 +304,7 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width, _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); - if (window->context.client != GLFW_OSMESA_CONTEXT_API) + if (window->context.source != GLFW_OSMESA_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return GLFW_FALSE; @@ -341,7 +343,7 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle, _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); - if (window->context.client != GLFW_OSMESA_CONTEXT_API) + if (window->context.source != GLFW_OSMESA_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return GLFW_FALSE; @@ -373,7 +375,7 @@ GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle) _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - if (window->context.client != GLFW_OSMESA_CONTEXT_API) + if (window->context.source != GLFW_OSMESA_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return NULL; diff --git a/src/platform.c b/src/platform.c index 34fb7acd..d0bbd06d 100644 --- a/src/platform.c +++ b/src/platform.c @@ -72,32 +72,37 @@ GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform) // Only allow the Null platform if specifically requested if (desiredID == GLFW_PLATFORM_NULL) return _glfwConnectNull(desiredID, platform); - - // If there is only one platform available for auto-selection, let it emit the error - // on failure as the platform-specific error description may be more helpful - if (desiredID == GLFW_ANY_PLATFORM && count == 1) - return supportedPlatforms[0].connect(supportedPlatforms[0].ID, platform); - - for (i = 0; i < count; i++) + else if (count == 0) { - if (desiredID == GLFW_ANY_PLATFORM || desiredID == supportedPlatforms[i].ID) - { - if (supportedPlatforms[i].connect(desiredID, platform)) - return GLFW_TRUE; - else if (desiredID == supportedPlatforms[i].ID) - return GLFW_FALSE; - } + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "This binary only supports the Null platform"); + return GLFW_FALSE; } if (desiredID == GLFW_ANY_PLATFORM) { - if (count) - _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "Failed to detect any supported platform"); - else - _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "This binary only supports the Null platform"); + // If there is exactly one platform available for auto-selection, let it emit the + // error on failure as the platform-specific error description may be more helpful + if (count == 1) + return supportedPlatforms[0].connect(supportedPlatforms[0].ID, platform); + + for (i = 0; i < count; i++) + { + if (supportedPlatforms[i].connect(desiredID, platform)) + return GLFW_TRUE; + } + + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "Failed to detect any supported platform"); } else + { + for (i = 0; i < count; i++) + { + if (supportedPlatforms[i].ID == desiredID) + return supportedPlatforms[i].connect(desiredID, platform); + } + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "The requested platform is not supported"); + } return GLFW_FALSE; } diff --git a/src/vulkan.c b/src/vulkan.c index 51789249..f02b1ede 100644 --- a/src/vulkan.c +++ b/src/vulkan.c @@ -45,45 +45,52 @@ GLFWbool _glfwInitVulkan(int mode) { VkResult err; VkExtensionProperties* ep; + PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; uint32_t i, count; if (_glfw.vk.available) return GLFW_TRUE; -#if !defined(_GLFW_VULKAN_STATIC) + if (_glfw.hints.init.vulkanLoader) + _glfw.vk.GetInstanceProcAddr = _glfw.hints.init.vulkanLoader; + else + { #if defined(_GLFW_VULKAN_LIBRARY) - _glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY); + _glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY); #elif defined(_GLFW_WIN32) - _glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll"); + _glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll"); #elif defined(_GLFW_COCOA) - _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib"); - if (!_glfw.vk.handle) - _glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa(); + _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib"); + if (!_glfw.vk.handle) + _glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa(); +#elif defined(__OpenBSD__) + _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so"); #else - _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1"); + _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1"); #endif - if (!_glfw.vk.handle) - { - if (mode == _GLFW_REQUIRE_LOADER) - _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found"); + if (!_glfw.vk.handle) + { + if (mode == _GLFW_REQUIRE_LOADER) + _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found"); - return GLFW_FALSE; + return GLFW_FALSE; + } + + _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) + _glfwPlatformGetModuleSymbol(_glfw.vk.handle, "vkGetInstanceProcAddr"); + if (!_glfw.vk.GetInstanceProcAddr) + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "Vulkan: Loader does not export vkGetInstanceProcAddr"); + + _glfwTerminateVulkan(); + return GLFW_FALSE; + } } - _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) - _glfwPlatformGetModuleSymbol(_glfw.vk.handle, "vkGetInstanceProcAddr"); - if (!_glfw.vk.GetInstanceProcAddr) - { - _glfwInputError(GLFW_API_UNAVAILABLE, - "Vulkan: Loader does not export vkGetInstanceProcAddr"); - - _glfwTerminateVulkan(); - return GLFW_FALSE; - } - - _glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties) + vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties) vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"); - if (!_glfw.vk.EnumerateInstanceExtensionProperties) + if (!vkEnumerateInstanceExtensionProperties) { _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties"); @@ -91,7 +98,6 @@ GLFWbool _glfwInitVulkan(int mode) _glfwTerminateVulkan(); return GLFW_FALSE; } -#endif // _GLFW_VULKAN_STATIC err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL); if (err) @@ -151,10 +157,8 @@ GLFWbool _glfwInitVulkan(int mode) void _glfwTerminateVulkan(void) { -#if !defined(_GLFW_VULKAN_STATIC) if (_glfw.vk.handle) _glfwPlatformFreeModule(_glfw.vk.handle); -#endif } const char* _glfwGetVulkanResultString(VkResult result) @@ -252,17 +256,16 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) return NULL; + // NOTE: Vulkan 1.0 and 1.1 vkGetInstanceProcAddr cannot return itself + if (strcmp(procname, "vkGetInstanceProcAddr") == 0) + return (GLFWvkproc) vkGetInstanceProcAddr; + proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname); -#if defined(_GLFW_VULKAN_STATIC) if (!proc) { - if (strcmp(procname, "vkGetInstanceProcAddr") == 0) - return (GLFWvkproc) vkGetInstanceProcAddr; + if (_glfw.vk.handle) + proc = (GLFWvkproc) _glfwPlatformGetModuleSymbol(_glfw.vk.handle, procname); } -#else - if (!proc) - proc = (GLFWvkproc) _glfwPlatformGetModuleSymbol(_glfw.vk.handle, procname); -#endif return proc; } diff --git a/src/wgl_context.c b/src/wgl_context.c index 774f45bd..6586db10 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -322,14 +322,12 @@ static void swapBuffersWGL(_GLFWwindow* window) { if (!window->monitor) { - if (IsWindowsVistaOrGreater()) + // HACK: Use DwmFlush when desktop composition is enabled on Windows Vista and 7 + if (!IsWindows8OrGreater() && IsWindowsVistaOrGreater()) { - // DWM Composition is always enabled on Win8+ - BOOL enabled = IsWindows8OrGreater(); + BOOL enabled = FALSE; - // HACK: Use DwmFlush when desktop composition is enabled - if (enabled || - (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)) + if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled) { int count = abs(window->context.wgl.interval); while (count--) @@ -349,15 +347,13 @@ static void swapIntervalWGL(int interval) if (!window->monitor) { - if (IsWindowsVistaOrGreater()) + // HACK: Disable WGL swap interval when desktop composition is enabled on Windows + // Vista and 7 to avoid interfering with DWM vsync + if (!IsWindows8OrGreater() && IsWindowsVistaOrGreater()) { - // DWM Composition is always enabled on Win8+ - BOOL enabled = IsWindows8OrGreater(); + BOOL enabled = FALSE; - // HACK: Disable WGL swap interval when desktop composition is enabled to - // avoid interfering with DWM vsync - if (enabled || - (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)) + if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled) interval = 0; } } @@ -783,7 +779,7 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle) return NULL; } - if (window->context.client != GLFW_NATIVE_CONTEXT_API) + if (window->context.source != GLFW_NATIVE_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return NULL; diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 17359a5f..cdee49a9 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -317,8 +317,19 @@ void _glfwGetHMONITORContentScaleWin32(HMONITOR handle, float* xscale, float* ys { UINT xdpi, ydpi; + if (xscale) + *xscale = 0.f; + if (yscale) + *yscale = 0.f; + if (IsWindows8Point1OrGreater()) - GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); + { + if (GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi) != S_OK) + { + _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to query monitor DPI"); + return; + } + } else { const HDC dc = GetDC(NULL); diff --git a/src/win32_platform.h b/src/win32_platform.h index 20e40d74..a7130377 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -428,7 +428,7 @@ typedef struct _GLFWwindowWin32 // The last received cursor position, regardless of source int lastCursorPosX, lastCursorPosY; - // The last recevied high surrogate when decoding pairs of UTF-16 messages + // The last received high surrogate when decoding pairs of UTF-16 messages WCHAR highSurrogate; } _GLFWwindowWin32; diff --git a/src/win32_window.c b/src/win32_window.c index ae7710a2..b3da6b2a 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -649,7 +649,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, window->win32.highSurrogate = (WCHAR) wParam; else { - unsigned int codepoint = 0; + uint32_t codepoint = 0; if (wParam >= 0xdc00 && wParam <= 0xdfff) { @@ -683,7 +683,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, return TRUE; } - _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GLFW_TRUE); + _glfwInputChar(window, (uint32_t) wParam, getKeyMods(), GLFW_TRUE); return 0; } @@ -1304,8 +1304,12 @@ static int createNativeWindow(_GLFWwindow* window, { float xscale, yscale; _glfwGetWindowContentScaleWin32(window, &xscale, &yscale); - rect.right = (int) (rect.right * xscale); - rect.bottom = (int) (rect.bottom * yscale); + + if (xscale > 0.f && yscale > 0.f) + { + rect.right = (int) (rect.right * xscale); + rect.bottom = (int) (rect.bottom * yscale); + } } ClientToScreen(window->win32.handle, (POINT*) &rect.left); @@ -1645,8 +1649,7 @@ void _glfwGetWindowFrameSizeWin32(_GLFWwindow* window, *bottom = rect.bottom - height; } -void _glfwGetWindowContentScaleWin32(_GLFWwindow* window, - float* xscale, float* yscale) +void _glfwGetWindowContentScaleWin32(_GLFWwindow* window, float* xscale, float* yscale) { const HANDLE handle = MonitorFromWindow(window->win32.handle, MONITOR_DEFAULTTONEAREST); diff --git a/src/window.c b/src/window.c index c9845eca..a65ed760 100644 --- a/src/window.c +++ b/src/window.c @@ -882,35 +882,41 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value) value = value ? GLFW_TRUE : GLFW_FALSE; - if (attrib == GLFW_AUTO_ICONIFY) - window->autoIconify = value; - else if (attrib == GLFW_RESIZABLE) + switch (attrib) { - window->resizable = value; - if (!window->monitor) - _glfw.platform.setWindowResizable(window, value); + case GLFW_AUTO_ICONIFY: + window->autoIconify = value; + return; + + case GLFW_RESIZABLE: + window->resizable = value; + if (!window->monitor) + _glfw.platform.setWindowResizable(window, value); + return; + + case GLFW_DECORATED: + window->decorated = value; + if (!window->monitor) + _glfw.platform.setWindowDecorated(window, value); + return; + + case GLFW_FLOATING: + window->floating = value; + if (!window->monitor) + _glfw.platform.setWindowFloating(window, value); + return; + + case GLFW_FOCUS_ON_SHOW: + window->focusOnShow = value; + return; + + case GLFW_MOUSE_PASSTHROUGH: + window->mousePassthrough = value; + _glfw.platform.setWindowMousePassthrough(window, value); + return; } - else if (attrib == GLFW_DECORATED) - { - window->decorated = value; - if (!window->monitor) - _glfw.platform.setWindowDecorated(window, value); - } - else if (attrib == GLFW_FLOATING) - { - window->floating = value; - if (!window->monitor) - _glfw.platform.setWindowFloating(window, value); - } - else if (attrib == GLFW_FOCUS_ON_SHOW) - window->focusOnShow = value; - else if (attrib == GLFW_MOUSE_PASSTHROUGH) - { - window->mousePassthrough = value; - _glfw.platform.setWindowMousePassthrough(window, value); - } - else - _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); + + _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); } GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle) @@ -986,7 +992,7 @@ GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle, assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.pos, cbfun); + _GLFW_SWAP(GLFWwindowposfun, window->callbacks.pos, cbfun); return cbfun; } @@ -997,7 +1003,7 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle, assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.size, cbfun); + _GLFW_SWAP(GLFWwindowsizefun, window->callbacks.size, cbfun); return cbfun; } @@ -1008,7 +1014,7 @@ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle, assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.close, cbfun); + _GLFW_SWAP(GLFWwindowclosefun, window->callbacks.close, cbfun); return cbfun; } @@ -1019,7 +1025,7 @@ GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle, assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.refresh, cbfun); + _GLFW_SWAP(GLFWwindowrefreshfun, window->callbacks.refresh, cbfun); return cbfun; } @@ -1030,7 +1036,7 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle, assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.focus, cbfun); + _GLFW_SWAP(GLFWwindowfocusfun, window->callbacks.focus, cbfun); return cbfun; } @@ -1041,7 +1047,7 @@ GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle, assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.iconify, cbfun); + _GLFW_SWAP(GLFWwindowiconifyfun, window->callbacks.iconify, cbfun); return cbfun; } @@ -1052,7 +1058,7 @@ GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle, assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.maximize, cbfun); + _GLFW_SWAP(GLFWwindowmaximizefun, window->callbacks.maximize, cbfun); return cbfun; } @@ -1063,7 +1069,7 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.fbsize, cbfun); + _GLFW_SWAP(GLFWframebuffersizefun, window->callbacks.fbsize, cbfun); return cbfun; } @@ -1074,7 +1080,7 @@ GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.scale, cbfun); + _GLFW_SWAP(GLFWwindowcontentscalefun, window->callbacks.scale, cbfun); return cbfun; } diff --git a/src/wl_init.c b/src/wl_init.c index 031e5d52..e7756385 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -207,12 +207,12 @@ static void pointerHandleMotion(void* data, return; x = wl_fixed_to_double(sx); y = wl_fixed_to_double(sy); + window->wl.cursorPosX = x; + window->wl.cursorPosY = y; switch (window->wl.decorations.focus) { case mainWindow: - window->wl.cursorPosX = x; - window->wl.cursorPosY = y; _glfwInputCursorPos(window, x, y); _glfw.wl.cursorPreviousName = NULL; return; @@ -272,9 +272,7 @@ static void pointerHandleButton(void* data, if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP; else - { xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); - } break; case leftDecoration: if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) @@ -303,6 +301,7 @@ static void pointerHandleButton(void* data, { xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, serial, edges); + return; } } else if (button == BTN_RIGHT) @@ -378,11 +377,8 @@ static void keyboardHandleKeymap(void* data, { struct xkb_keymap* keymap; struct xkb_state* state; - -#ifdef HAVE_XKBCOMMON_COMPOSE_H struct xkb_compose_table* composeTable; struct xkb_compose_state* composeState; -#endif char* mapStr; const char* locale; @@ -431,7 +427,6 @@ static void keyboardHandleKeymap(void* data, if (!locale) locale = "C"; -#ifdef HAVE_XKBCOMMON_COMPOSE_H composeTable = xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); @@ -451,7 +446,6 @@ static void keyboardHandleKeymap(void* data, _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to create XKB compose table"); } -#endif xkb_keymap_unref(_glfw.wl.xkb.keymap); xkb_state_unref(_glfw.wl.xkb.state); @@ -505,20 +499,22 @@ static void keyboardHandleLeave(void* data, if (!window) return; + struct itimerspec timer = {}; + timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL); + _glfw.wl.serial = serial; _glfw.wl.keyboardFocus = NULL; _glfwInputWindowFocus(window, GLFW_FALSE); } -static int toGLFWKeyCode(uint32_t key) +static int translateKey(uint32_t scancode) { - if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0])) - return _glfw.wl.keycodes[key]; + if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0])) + return _glfw.wl.keycodes[scancode]; return GLFW_KEY_UNKNOWN; } -#ifdef HAVE_XKBCOMMON_COMPOSE_H static xkb_keysym_t composeSymbol(xkb_keysym_t sym) { if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState) @@ -538,77 +534,65 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym) return sym; } } -#endif -static GLFWbool inputChar(_GLFWwindow* window, uint32_t key) +GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode) { - uint32_t code, numSyms; - long cp; - const xkb_keysym_t *syms; - xkb_keysym_t sym; + const xkb_keysym_t* keysyms; + const xkb_keycode_t keycode = scancode + 8; - code = key + 8; - numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms); - - if (numSyms == 1) + if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1) { -#ifdef HAVE_XKBCOMMON_COMPOSE_H - sym = composeSymbol(syms[0]); -#else - sym = syms[0]; -#endif - cp = _glfwKeySym2Unicode(sym); - if (cp != -1) + const xkb_keysym_t keysym = composeSymbol(keysyms[0]); + const uint32_t codepoint = _glfwKeySym2Unicode(keysym); + if (codepoint != GLFW_INVALID_CODEPOINT) { const int mods = _glfw.wl.xkb.modifiers; const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); - _glfwInputChar(window, cp, mods, plain); + _glfwInputChar(window, codepoint, mods, plain); } } - return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, code); + return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode); } static void keyboardHandleKey(void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t time, - uint32_t key, + uint32_t scancode, uint32_t state) { - int keyCode; - int action; _GLFWwindow* window = _glfw.wl.keyboardFocus; - GLFWbool shouldRepeat; - struct itimerspec timer = {}; - if (!window) return; - keyCode = toGLFWKeyCode(key); - action = state == WL_KEYBOARD_KEY_STATE_PRESSED - ? GLFW_PRESS : GLFW_RELEASE; + const int key = translateKey(scancode); + const int action = + state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE; _glfw.wl.serial = serial; - _glfwInputKey(window, keyCode, key, action, - _glfw.wl.xkb.modifiers); + _glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers); + + struct itimerspec timer = {}; if (action == GLFW_PRESS) { - shouldRepeat = inputChar(window, key); + const GLFWbool shouldRepeat = _glfwInputTextWayland(window, scancode); if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0) { - _glfw.wl.keyboardLastKey = keyCode; - _glfw.wl.keyboardLastScancode = key; + _glfw.wl.keyboardLastKey = key; + _glfw.wl.keyboardLastScancode = scancode; if (_glfw.wl.keyboardRepeatRate > 1) timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate; else timer.it_interval.tv_sec = 1; + timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000; timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000; } } + timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL); } @@ -620,9 +604,6 @@ static void keyboardHandleModifiers(void* data, uint32_t modsLocked, uint32_t group) { - xkb_mod_mask_t mask; - unsigned int modifiers = 0; - _glfw.wl.serial = serial; if (!_glfw.wl.xkb.keymap) @@ -636,24 +617,29 @@ static void keyboardHandleModifiers(void* data, 0, group); - mask = xkb_state_serialize_mods(_glfw.wl.xkb.state, - XKB_STATE_MODS_DEPRESSED | - XKB_STATE_LAYOUT_DEPRESSED | - XKB_STATE_MODS_LATCHED | - XKB_STATE_LAYOUT_LATCHED); + const xkb_mod_mask_t mask = + xkb_state_serialize_mods(_glfw.wl.xkb.state, + XKB_STATE_MODS_DEPRESSED | + XKB_STATE_LAYOUT_DEPRESSED | + XKB_STATE_MODS_LATCHED | + XKB_STATE_LAYOUT_LATCHED); + + unsigned int mods = 0; + if (mask & _glfw.wl.xkb.controlMask) - modifiers |= GLFW_MOD_CONTROL; + mods |= GLFW_MOD_CONTROL; if (mask & _glfw.wl.xkb.altMask) - modifiers |= GLFW_MOD_ALT; + mods |= GLFW_MOD_ALT; if (mask & _glfw.wl.xkb.shiftMask) - modifiers |= GLFW_MOD_SHIFT; + mods |= GLFW_MOD_SHIFT; if (mask & _glfw.wl.xkb.superMask) - modifiers |= GLFW_MOD_SUPER; + mods |= GLFW_MOD_SUPER; if (mask & _glfw.wl.xkb.capsLockMask) - modifiers |= GLFW_MOD_CAPS_LOCK; + mods |= GLFW_MOD_CAPS_LOCK; if (mask & _glfw.wl.xkb.numLockMask) - modifiers |= GLFW_MOD_NUM_LOCK; - _glfw.wl.xkb.modifiers = modifiers; + mods |= GLFW_MOD_NUM_LOCK; + + _glfw.wl.xkb.modifiers = mods; } #ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION @@ -886,10 +872,9 @@ static void registryHandleGlobalRemove(void *data, struct wl_registry *registry, uint32_t name) { - int i; _GLFWmonitor* monitor; - for (i = 0; i < _glfw.monitorCount; ++i) + for (int i = 0; i < _glfw.monitorCount; ++i) { monitor = _glfw.monitors[i]; if (monitor->wl.name == name) @@ -910,8 +895,6 @@ static const struct wl_registry_listener registryListener = { // static void createKeyTables(void) { - int scancode; - memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes)); memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes)); @@ -973,7 +956,7 @@ static void createKeyTables(void) _glfw.wl.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT; _glfw.wl.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER; _glfw.wl.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER; - _glfw.wl.keycodes[KEY_MENU] = GLFW_KEY_MENU; + _glfw.wl.keycodes[KEY_COMPOSE] = GLFW_KEY_MENU; _glfw.wl.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK; _glfw.wl.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK; _glfw.wl.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN; @@ -1016,7 +999,7 @@ static void createKeyTables(void) _glfw.wl.keycodes[KEY_F23] = GLFW_KEY_F23; _glfw.wl.keycodes[KEY_F24] = GLFW_KEY_F24; _glfw.wl.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE; - _glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY; + _glfw.wl.keycodes[KEY_KPASTERISK] = GLFW_KEY_KP_MULTIPLY; _glfw.wl.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT; _glfw.wl.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD; _glfw.wl.keycodes[KEY_KP0] = GLFW_KEY_KP_0; @@ -1029,11 +1012,12 @@ static void createKeyTables(void) _glfw.wl.keycodes[KEY_KP7] = GLFW_KEY_KP_7; _glfw.wl.keycodes[KEY_KP8] = GLFW_KEY_KP_8; _glfw.wl.keycodes[KEY_KP9] = GLFW_KEY_KP_9; - _glfw.wl.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL; + _glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_DECIMAL; _glfw.wl.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL; _glfw.wl.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER; + _glfw.wl.keycodes[KEY_102ND] = GLFW_KEY_WORLD_2; - for (scancode = 0; scancode < 256; scancode++) + for (int scancode = 0; scancode < 256; scancode++) { if (_glfw.wl.keycodes[scancode] > 0) _glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode; @@ -1290,6 +1274,8 @@ int _glfwInitWayland(void) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index"); _glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats"); + _glfw.wl.xkb.keymap_key_get_syms_by_level = (PFN_xkb_keymap_key_get_syms_by_level) + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_get_syms_by_level"); _glfw.wl.xkb.state_new = (PFN_xkb_state_new) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_new"); _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref) @@ -1300,8 +1286,8 @@ int _glfwInitWayland(void) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_update_mask"); _glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_serialize_mods"); - -#ifdef HAVE_XKBCOMMON_COMPOSE_H + _glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout) + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_key_get_layout"); _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale"); _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref) @@ -1316,7 +1302,6 @@ int _glfwInitWayland(void) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_status"); _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym"); -#endif _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display); wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL); @@ -1339,7 +1324,7 @@ int _glfwInitWayland(void) _glfw.wl.timerfd = -1; if (_glfw.wl.seatVersion >= 4) - _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); if (!_glfw.wl.wmBase) { @@ -1373,7 +1358,7 @@ int _glfwInitWayland(void) wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm); _glfw.wl.cursorSurface = wl_compositor_create_surface(_glfw.wl.compositor); - _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); } if (_glfw.wl.seat && _glfw.wl.dataDeviceManager) @@ -1404,10 +1389,8 @@ void _glfwTerminateWayland(void) _glfw.wl.egl.handle = NULL; } -#ifdef HAVE_XKBCOMMON_COMPOSE_H if (_glfw.wl.xkb.composeState) xkb_compose_state_unref(_glfw.wl.xkb.composeState); -#endif if (_glfw.wl.xkb.keymap) xkb_keymap_unref(_glfw.wl.xkb.keymap); if (_glfw.wl.xkb.state) diff --git a/src/wl_platform.h b/src/wl_platform.h index 1e36a794..7565411b 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -26,9 +26,7 @@ #include #include -#ifdef HAVE_XKBCOMMON_COMPOSE_H #include -#endif typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; @@ -163,24 +161,27 @@ typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*); typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*); typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t); +typedef int (* PFN_xkb_keymap_key_get_syms_by_level)(struct xkb_keymap*,xkb_keycode_t,xkb_layout_index_t,xkb_level_index_t,const xkb_keysym_t**); typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*); typedef void (* PFN_xkb_state_unref)(struct xkb_state*); typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**); typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t); typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component); +typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t); #define xkb_context_new _glfw.wl.xkb.context_new #define xkb_context_unref _glfw.wl.xkb.context_unref #define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string #define xkb_keymap_unref _glfw.wl.xkb.keymap_unref #define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index #define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats +#define xkb_keymap_key_get_syms_by_level _glfw.wl.xkb.keymap_key_get_syms_by_level #define xkb_state_new _glfw.wl.xkb.state_new #define xkb_state_unref _glfw.wl.xkb.state_unref #define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms #define xkb_state_update_mask _glfw.wl.xkb.state_update_mask #define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods +#define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout -#ifdef HAVE_XKBCOMMON_COMPOSE_H typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags); typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*); typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags); @@ -195,7 +196,6 @@ typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_st #define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed #define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status #define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym -#endif #define _GLFW_DECORATION_WIDTH 4 #define _GLFW_DECORATION_TOP 24 @@ -311,6 +311,7 @@ typedef struct _GLFWlibraryWayland int timerfd; short int keycodes[256]; short int scancodes[GLFW_KEY_LAST + 1]; + char keynames[GLFW_KEY_LAST + 1][5]; struct { void* handle; @@ -318,9 +319,7 @@ typedef struct _GLFWlibraryWayland struct xkb_keymap* keymap; struct xkb_state* state; -#ifdef HAVE_XKBCOMMON_COMPOSE_H struct xkb_compose_state* composeState; -#endif xkb_mod_mask_t controlMask; xkb_mod_mask_t altMask; @@ -336,13 +335,14 @@ typedef struct _GLFWlibraryWayland PFN_xkb_keymap_unref keymap_unref; PFN_xkb_keymap_mod_get_index keymap_mod_get_index; PFN_xkb_keymap_key_repeats keymap_key_repeats; + PFN_xkb_keymap_key_get_syms_by_level keymap_key_get_syms_by_level; PFN_xkb_state_new state_new; PFN_xkb_state_unref state_unref; PFN_xkb_state_key_get_syms state_key_get_syms; PFN_xkb_state_update_mask state_update_mask; PFN_xkb_state_serialize_mods state_serialize_mods; + PFN_xkb_state_key_get_layout state_key_get_layout; -#ifdef HAVE_XKBCOMMON_COMPOSE_H PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale; PFN_xkb_compose_table_unref compose_table_unref; PFN_xkb_compose_state_new compose_state_new; @@ -350,7 +350,6 @@ typedef struct _GLFWlibraryWayland PFN_xkb_compose_state_feed compose_state_feed; PFN_xkb_compose_state_get_status compose_state_get_status; PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym; -#endif } xkb; _GLFWwindow* pointerFocus; @@ -496,4 +495,5 @@ GLFWbool _glfwGetGammaRampWayland(_GLFWmonitor* monitor, GLFWgammaramp* ramp); void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); void _glfwAddOutputWayland(uint32_t name, uint32_t version); +GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode); diff --git a/src/wl_window.c b/src/wl_window.c index bf57ce53..b2aa1800 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -144,9 +144,8 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image) int stride = image->width * 4; int length = image->width * image->height * 4; void* data; - int fd, i; - fd = createAnonymousFile(length); + const int fd = createAnonymousFile(length); if (fd < 0) { _glfwInputError(GLFW_PLATFORM_ERROR, @@ -169,7 +168,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image) close(fd); unsigned char* source = (unsigned char*) image->pixels; unsigned char* target = data; - for (i = 0; i < image->width * image->height; i++, source += 4) + for (int i = 0; i < image->width * image->height; i++, source += 4) { unsigned int alpha = source[3]; @@ -347,7 +346,6 @@ static void resizeWindow(_GLFWwindow* window) static void checkScaleChange(_GLFWwindow* window) { int scale = 1; - int i; int monitorScale; // Check if we will be able to set the buffer scale or not. @@ -355,7 +353,7 @@ static void checkScaleChange(_GLFWwindow* window) return; // Get the scale factor from the highest scale monitor. - for (i = 0; i < window->wl.monitorsCount; ++i) + for (int i = 0; i < window->wl.monitorsCount; ++i) { monitorScale = window->wl.monitors[i]->wl.scale; if (scale < monitorScale) @@ -397,10 +395,9 @@ static void surfaceHandleLeave(void *data, { _GLFWwindow* window = data; _GLFWmonitor* monitor = wl_output_get_user_data(output); - GLFWbool found; - int i; + GLFWbool found = GLFW_FALSE; - for (i = 0, found = GLFW_FALSE; i < window->wl.monitorsCount - 1; ++i) + for (int i = 0; i < window->wl.monitorsCount - 1; ++i) { if (monitor == window->wl.monitors[i]) found = GLFW_TRUE; @@ -435,35 +432,6 @@ static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable) } } -static GLFWbool createSurface(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig) -{ - window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor); - if (!window->wl.surface) - return GLFW_FALSE; - - wl_surface_add_listener(window->wl.surface, - &surfaceListener, - window); - - wl_surface_set_user_data(window->wl.surface, window); - - window->wl.native = wl_egl_window_create(window->wl.surface, - wndconfig->width, - wndconfig->height); - if (!window->wl.native) - return GLFW_FALSE; - - window->wl.width = wndconfig->width; - window->wl.height = wndconfig->height; - window->wl.scale = 1; - - if (!window->wl.transparent) - setOpaqueRegion(window); - - return GLFW_TRUE; -} - static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, int refreshRate) { @@ -540,7 +508,6 @@ static void xdgToplevelHandleConfigure(void* data, } if (fullscreen && activated) window->wl.wasFullscreen = GLFW_TRUE; - _glfwInputWindowFocus(window, activated); } static void xdgToplevelHandleClose(void* data, @@ -648,6 +615,46 @@ static GLFWbool createXdgSurface(_GLFWwindow* window) return GLFW_TRUE; } +static GLFWbool createSurface(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) +{ + window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor); + if (!window->wl.surface) + return GLFW_FALSE; + + wl_surface_add_listener(window->wl.surface, + &surfaceListener, + window); + + wl_surface_set_user_data(window->wl.surface, window); + + window->wl.native = wl_egl_window_create(window->wl.surface, + wndconfig->width, + wndconfig->height); + if (!window->wl.native) + return GLFW_FALSE; + + window->wl.width = wndconfig->width; + window->wl.height = wndconfig->height; + window->wl.scale = 1; + window->wl.title = _glfw_strdup(wndconfig->title); + + window->wl.transparent = fbconfig->transparent; + if (!window->wl.transparent) + setOpaqueRegion(window); + + if (window->monitor || wndconfig->visible) + { + if (!createXdgSurface(window)) + return GLFW_FALSE; + + window->wl.visible = GLFW_TRUE; + } + + return GLFW_TRUE; +} + static void setCursorImage(_GLFWwindow* window, _GLFWcursorWayland* cursorWayland) { @@ -712,22 +719,19 @@ static void incrementCursorImage(_GLFWwindow* window) static void handleEvents(int timeout) { - struct wl_display* display = _glfw.wl.display; - struct pollfd fds[] = { - { wl_display_get_fd(display), POLLIN }, + struct pollfd fds[] = + { + { wl_display_get_fd(_glfw.wl.display), POLLIN }, { _glfw.wl.timerfd, POLLIN }, { _glfw.wl.cursorTimerfd, POLLIN }, }; - ssize_t read_ret; - uint64_t repeats, i; - while (wl_display_prepare_read(display) != 0) - wl_display_dispatch_pending(display); + while (wl_display_prepare_read(_glfw.wl.display) != 0) + wl_display_dispatch_pending(_glfw.wl.display); - // If an error different from EAGAIN happens, we have likely been - // disconnected from the Wayland session, try to handle that the best we - // can. - if (wl_display_flush(display) < 0 && errno != EAGAIN) + // If an error other than EAGAIN happens, we have likely been disconnected + // from the Wayland session; try to handle that the best we can. + if (wl_display_flush(_glfw.wl.display) < 0 && errno != EAGAIN) { _GLFWwindow* window = _glfw.windowListHead; while (window) @@ -735,7 +739,8 @@ static void handleEvents(int timeout) _glfwInputWindowCloseRequest(window); window = window->next; } - wl_display_cancel_read(display); + + wl_display_cancel_read(_glfw.wl.display); return; } @@ -743,46 +748,41 @@ static void handleEvents(int timeout) { if (fds[0].revents & POLLIN) { - wl_display_read_events(display); - wl_display_dispatch_pending(display); + wl_display_read_events(_glfw.wl.display); + wl_display_dispatch_pending(_glfw.wl.display); } else - { - wl_display_cancel_read(display); - } + wl_display_cancel_read(_glfw.wl.display); if (fds[1].revents & POLLIN) { - read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats)); - if (read_ret != 8) - return; + uint64_t repeats; - if (_glfw.wl.keyboardFocus) + if (read(_glfw.wl.timerfd, &repeats, sizeof(repeats)) == 8) { - for (i = 0; i < repeats; ++i) + for (uint64_t i = 0; i < repeats; i++) { _glfwInputKey(_glfw.wl.keyboardFocus, _glfw.wl.keyboardLastKey, _glfw.wl.keyboardLastScancode, - GLFW_REPEAT, + GLFW_PRESS, _glfw.wl.xkb.modifiers); + _glfwInputTextWayland(_glfw.wl.keyboardFocus, + _glfw.wl.keyboardLastScancode); } } } if (fds[2].revents & POLLIN) { - read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)); - if (read_ret != 8) - return; + uint64_t repeats; - incrementCursorImage(_glfw.wl.pointerFocus); + if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8) + incrementCursorImage(_glfw.wl.pointerFocus); } } else - { - wl_display_cancel_read(display); - } + wl_display_cancel_read(_glfw.wl.display); } ////////////////////////////////////////////////////////////////////////// @@ -794,9 +794,7 @@ int _glfwCreateWindowWayland(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { - window->wl.transparent = fbconfig->transparent; - - if (!createSurface(window, wndconfig)) + if (!createSurface(window, wndconfig, fbconfig)) return GLFW_FALSE; if (ctxconfig->client != GLFW_NO_API) @@ -818,29 +816,6 @@ int _glfwCreateWindowWayland(_GLFWwindow* window, } } - if (wndconfig->title) - window->wl.title = _glfw_strdup(wndconfig->title); - - if (wndconfig->visible) - { - if (!createXdgSurface(window)) - return GLFW_FALSE; - - window->wl.visible = GLFW_TRUE; - } - else - { - window->wl.xdg.surface = NULL; - window->wl.xdg.toplevel = NULL; - window->wl.visible = GLFW_FALSE; - } - - window->wl.currentCursor = NULL; - - window->wl.monitors = _glfw_calloc(1, sizeof(_GLFWmonitor*)); - window->wl.monitorsCount = 0; - window->wl.monitorsSize = 1; - return GLFW_TRUE; } @@ -1027,21 +1002,24 @@ void _glfwShowWindowWayland(_GLFWwindow* window) { if (!window->wl.visible) { - createXdgSurface(window); + // NOTE: The XDG surface and role are created here so command-line applications + // with off-screen windows do not appear in for example the Unity dock + if (!window->wl.xdg.toplevel) + createXdgSurface(window); + window->wl.visible = GLFW_TRUE; + _glfwInputWindowDamage(window); } } void _glfwHideWindowWayland(_GLFWwindow* window) { - if (window->wl.xdg.toplevel) + if (window->wl.visible) { - xdg_toplevel_destroy(window->wl.xdg.toplevel); - xdg_surface_destroy(window->wl.xdg.surface); - window->wl.xdg.toplevel = NULL; - window->wl.xdg.surface = NULL; + window->wl.visible = GLFW_FALSE; + wl_surface_attach(window->wl.surface, NULL, 0, 0); + wl_surface_commit(window->wl.surface); } - window->wl.visible = GLFW_FALSE; } void _glfwRequestWindowAttentionWayland(_GLFWwindow* window) @@ -1217,10 +1195,57 @@ void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode) const char* _glfwGetScancodeNameWayland(int scancode) { - // TODO - _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, - "Wayland: Key names not yet implemented"); - return NULL; + if (scancode < 0 || scancode > 255 || + _glfw.wl.keycodes[scancode] == GLFW_KEY_UNKNOWN) + { + _glfwInputError(GLFW_INVALID_VALUE, + "Wayland: Invalid scancode %i", + scancode); + return NULL; + } + + const int key = _glfw.wl.keycodes[scancode]; + const xkb_keycode_t keycode = scancode + 8; + const xkb_layout_index_t layout = + xkb_state_key_get_layout(_glfw.wl.xkb.state, keycode); + if (layout == XKB_LAYOUT_INVALID) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to retrieve layout for key name"); + return NULL; + } + + const xkb_keysym_t* keysyms = NULL; + xkb_keymap_key_get_syms_by_level(_glfw.wl.xkb.keymap, + keycode, + layout, + 0, + &keysyms); + if (keysyms == NULL) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to retrieve keysym for key name"); + return NULL; + } + + const uint32_t codepoint = _glfwKeySym2Unicode(keysyms[0]); + if (codepoint == GLFW_INVALID_CODEPOINT) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to retrieve codepoint for key name"); + return NULL; + } + + const size_t count = _glfwEncodeUTF8(_glfw.wl.keynames[key], codepoint); + if (count == 0) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to encode codepoint for key name"); + return NULL; + } + + _glfw.wl.keynames[key][count] = '\0'; + return _glfw.wl.keynames[key]; } int _glfwGetKeyScancodeWayland(int key) diff --git a/src/x11_init.c b/src/x11_init.c index bedd1bc9..acfa7933 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -209,7 +209,7 @@ static int translateKeySyms(const KeySym* keysyms, int width) // static void createKeyTables(void) { - int scancode, scancodeMin, scancodeMax; + int scancodeMin, scancodeMax; memset(_glfw.x11.keycodes, -1, sizeof(_glfw.x11.keycodes)); memset(_glfw.x11.scancodes, -1, sizeof(_glfw.x11.scancodes)); @@ -355,7 +355,7 @@ static void createKeyTables(void) }; // Find the X11 key code -> GLFW key code mapping - for (scancode = scancodeMin; scancode <= scancodeMax; scancode++) + for (int scancode = scancodeMin; scancode <= scancodeMax; scancode++) { int key = GLFW_KEY_UNKNOWN; @@ -414,7 +414,7 @@ static void createKeyTables(void) scancodeMax - scancodeMin + 1, &width); - for (scancode = scancodeMin; scancode <= scancodeMax; scancode++) + for (int scancode = scancodeMin; scancode <= scancodeMax; scancode++) { // Translate the un-translated key codes using traditional X11 KeySym // lookups @@ -601,7 +601,11 @@ static void detectEWMH(void) // static GLFWbool initExtensions(void) { +#if defined(__OpenBSD__) + _glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so"); +#else _glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so.1"); +#endif if (_glfw.x11.vidmode.handle) { _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) @@ -621,6 +625,8 @@ static GLFWbool initExtensions(void) #if defined(__CYGWIN__) _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi-6.so"); +#elif defined(__OpenBSD__) + _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so"); #else _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so.6"); #endif @@ -651,6 +657,8 @@ static GLFWbool initExtensions(void) #if defined(__CYGWIN__) _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr-2.so"); +#elif defined(__OpenBSD__) + _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so"); #else _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so.2"); #endif @@ -743,6 +751,8 @@ static GLFWbool initExtensions(void) #if defined(__CYGWIN__) _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor-1.so"); +#elif defined(__OpenBSD__) + _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so"); #else _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so.1"); #endif @@ -764,6 +774,8 @@ static GLFWbool initExtensions(void) #if defined(__CYGWIN__) _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama-1.so"); +#elif defined(__OpenBSD__) + _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so"); #else _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so.1"); #endif @@ -817,6 +829,8 @@ static GLFWbool initExtensions(void) { #if defined(__CYGWIN__) _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb-1.so"); +#elif defined(__OpenBSD__) + _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so"); #else _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so.1"); #endif @@ -830,6 +844,8 @@ static GLFWbool initExtensions(void) #if defined(__CYGWIN__) _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender-1.so"); +#elif defined(__OpenBSD__) + _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so"); #else _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so.1"); #endif @@ -857,6 +873,8 @@ static GLFWbool initExtensions(void) #if defined(__CYGWIN__) _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext-6.so"); +#elif defined(__OpenBSD__) + _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so"); #else _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so.6"); #endif @@ -1072,7 +1090,6 @@ void _glfwInputErrorX11(int error, const char* message) // Cursor _glfwCreateNativeCursorX11(const GLFWimage* image, int xhot, int yhot) { - int i; Cursor cursor; if (!_glfw.x11.xcursor.handle) @@ -1088,7 +1105,7 @@ Cursor _glfwCreateNativeCursorX11(const GLFWimage* image, int xhot, int yhot) unsigned char* source = (unsigned char*) image->pixels; XcursorPixel* target = native->pixels; - for (i = 0; i < image->width * image->height; i++, target++, source += 4) + for (int i = 0; i < image->width * image->height; i++, target++, source += 4) { unsigned int alpha = source[3]; @@ -1204,6 +1221,8 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform) #if defined(__CYGWIN__) void* module = _glfwPlatformLoadModule("libX11-6.so"); +#elif defined(__OpenBSD__) + void* module = _glfwPlatformLoadModule("libX11.so"); #else void* module = _glfwPlatformLoadModule("libX11.so.6"); #endif diff --git a/src/x11_window.c b/src/x11_window.c index 3c74a813..61e4fd6d 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -429,44 +429,13 @@ static char** parseUriList(char* text, int* count) return paths; } -// Encode a Unicode code point to a UTF-8 stream -// Based on cutef8 by Jeff Bezanson (Public Domain) -// -static size_t encodeUTF8(char* s, unsigned int ch) -{ - size_t count = 0; - - if (ch < 0x80) - s[count++] = (char) ch; - else if (ch < 0x800) - { - s[count++] = (ch >> 6) | 0xc0; - s[count++] = (ch & 0x3f) | 0x80; - } - else if (ch < 0x10000) - { - s[count++] = (ch >> 12) | 0xe0; - s[count++] = ((ch >> 6) & 0x3f) | 0x80; - s[count++] = (ch & 0x3f) | 0x80; - } - else if (ch < 0x110000) - { - s[count++] = (ch >> 18) | 0xf0; - s[count++] = ((ch >> 12) & 0x3f) | 0x80; - s[count++] = ((ch >> 6) & 0x3f) | 0x80; - s[count++] = (ch & 0x3f) | 0x80; - } - - return count; -} - // Decode a Unicode code point from a UTF-8 stream // Based on cutef8 by Jeff Bezanson (Public Domain) // -static unsigned int decodeUTF8(const char** s) +static uint32_t decodeUTF8(const char** s) { - unsigned int ch = 0, count = 0; - static const unsigned int offsets[] = + uint32_t codepoint = 0, count = 0; + static const uint32_t offsets[] = { 0x00000000u, 0x00003080u, 0x000e2080u, 0x03c82080u, 0xfa082080u, 0x82082080u @@ -474,13 +443,13 @@ static unsigned int decodeUTF8(const char** s) do { - ch = (ch << 6) + (unsigned char) **s; + codepoint = (codepoint << 6) + (unsigned char) **s; (*s)++; count++; } while ((**s & 0xc0) == 0x80); assert(count <= 6); - return ch - offsets[count - 1]; + return codepoint - offsets[count - 1]; } // Convert the specified Latin-1 string to UTF-8 @@ -497,7 +466,7 @@ static char* convertLatin1toUTF8(const char* source) char* tp = target; for (sp = source; *sp; sp++) - tp += encodeUTF8(tp, *sp); + tp += _glfwEncodeUTF8(tp, *sp); return target; } @@ -788,7 +757,6 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, // static Atom writeTargetToProperty(const XSelectionRequestEvent* request) { - int i; char* selectionString = NULL; const Atom formats[] = { _glfw.x11.UTF8_STRING, XA_STRING }; const int formatCount = sizeof(formats) / sizeof(formats[0]); @@ -831,14 +799,13 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request) // Multiple conversions were requested Atom* targets; - unsigned long i, count; + const unsigned long count = + _glfwGetWindowPropertyX11(request->requestor, + request->property, + _glfw.x11.ATOM_PAIR, + (unsigned char**) &targets); - count = _glfwGetWindowPropertyX11(request->requestor, - request->property, - _glfw.x11.ATOM_PAIR, - (unsigned char**) &targets); - - for (i = 0; i < count; i += 2) + for (unsigned long i = 0; i < count; i += 2) { int j; @@ -896,7 +863,7 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request) // Conversion to a data target was requested - for (i = 0; i < formatCount; i++) + for (int i = 0; i < formatCount; i++) { if (request->target == formats[i]) { @@ -1319,9 +1286,9 @@ static void processEvent(XEvent *event) _glfwInputKey(window, key, keycode, GLFW_PRESS, mods); - const long character = _glfwKeySym2Unicode(keysym); - if (character != -1) - _glfwInputChar(window, character, mods, plain); + const uint32_t codepoint = _glfwKeySym2Unicode(keysym); + if (codepoint != GLFW_INVALID_CODEPOINT) + _glfwInputChar(window, codepoint, mods, plain); } return; @@ -1588,7 +1555,7 @@ static void processEvent(XEvent *event) else if (event->xclient.message_type == _glfw.x11.XdndEnter) { // A drag operation has entered the window - unsigned long i, count; + unsigned long count; Atom* formats = NULL; const GLFWbool list = event->xclient.data.l[1] & 1; @@ -1612,7 +1579,7 @@ static void processEvent(XEvent *event) formats = (Atom*) event->xclient.data.l + 2; } - for (i = 0; i < count; i++) + for (unsigned int i = 0; i < count; i++) { if (formats[i] == _glfw.x11.text_uri_list) { @@ -1718,12 +1685,12 @@ static void processEvent(XEvent *event) if (result) { - int i, count; + int count; char** paths = parseUriList(data, &count); _glfwInputDrop(window, count, (const char**) paths); - for (i = 0; i < count; i++) + for (int i = 0; i < count; i++) _glfw_free(paths[i]); _glfw_free(paths); } @@ -2102,28 +2069,34 @@ void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* imag { if (count) { - int i, j, longCount = 0; + int longCount = 0; - for (i = 0; i < count; i++) + for (int i = 0; i < count; i++) longCount += 2 + images[i].width * images[i].height; - long* icon = _glfw_calloc(longCount, sizeof(long)); - long* target = icon; + unsigned long* icon = _glfw_calloc(longCount, sizeof(unsigned long)); + unsigned long* target = icon; - for (i = 0; i < count; i++) + for (int i = 0; i < count; i++) { *target++ = images[i].width; *target++ = images[i].height; - for (j = 0; j < images[i].width * images[i].height; j++) + for (int j = 0; j < images[i].width * images[i].height; j++) { - *target++ = (images[i].pixels[j * 4 + 0] << 16) | - (images[i].pixels[j * 4 + 1] << 8) | - (images[i].pixels[j * 4 + 2] << 0) | - (images[i].pixels[j * 4 + 3] << 24); + *target++ = (((unsigned long) images[i].pixels[j * 4 + 0]) << 16) | + (((unsigned long) images[i].pixels[j * 4 + 1]) << 8) | + (((unsigned long) images[i].pixels[j * 4 + 2]) << 0) | + (((unsigned long) images[i].pixels[j * 4 + 3]) << 24); } } + // NOTE: XChangeProperty expects 32-bit values like the image data above to be + // placed in the 32 least significant bits of individual longs. This is + // true even if long is 64-bit and a WM protocol calls for "packed" data. + // This is because of a historical mistake that then became part of the Xlib + // ABI. Xlib will pack these values into a regular array of 32-bit values + // before sending it over the wire. XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_ICON, XA_CARDINAL, 32, @@ -2537,7 +2510,6 @@ int _glfwWindowVisibleX11(_GLFWwindow* window) int _glfwWindowMaximizedX11(_GLFWwindow* window) { Atom* states; - unsigned long i; GLFWbool maximized = GLFW_FALSE; if (!_glfw.x11.NET_WM_STATE || @@ -2553,7 +2525,7 @@ int _glfwWindowMaximizedX11(_GLFWwindow* window) XA_ATOM, (unsigned char**) &states); - for (i = 0; i < count; i++) + for (unsigned long i = 0; i < count; i++) { if (states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT || states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ) @@ -2651,18 +2623,19 @@ void _glfwSetWindowFloatingX11(_GLFWwindow* window, GLFWbool enabled) else { Atom* states = NULL; - unsigned long i, count; - - count = _glfwGetWindowPropertyX11(window->x11.handle, - _glfw.x11.NET_WM_STATE, - XA_ATOM, - (unsigned char**) &states); + const unsigned long count = + _glfwGetWindowPropertyX11(window->x11.handle, + _glfw.x11.NET_WM_STATE, + XA_ATOM, + (unsigned char**) &states); // NOTE: We don't check for failure as this property may not exist yet // and that's fine (and we'll create it implicitly with append) if (enabled) { + unsigned long i; + for (i = 0; i < count; i++) { if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE) @@ -2680,20 +2653,16 @@ void _glfwSetWindowFloatingX11(_GLFWwindow* window, GLFWbool enabled) } else if (states) { - for (i = 0; i < count; i++) + for (unsigned long i = 0; i < count; i++) { if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE) + { + states[i] = states[count - 1]; + XChangeProperty(_glfw.x11.display, window->x11.handle, + _glfw.x11.NET_WM_STATE, XA_ATOM, 32, + PropModeReplace, (unsigned char*) states, count - 1); break; - } - - if (i < count) - { - states[i] = states[count - 1]; - count--; - - XChangeProperty(_glfw.x11.display, window->x11.handle, - _glfw.x11.NET_WM_STATE, XA_ATOM, 32, - PropModeReplace, (unsigned char*) states, count); + } } } @@ -2899,11 +2868,11 @@ const char* _glfwGetScancodeNameX11(int scancode) if (keysym == NoSymbol) return NULL; - const long ch = _glfwKeySym2Unicode(keysym); - if (ch == -1) + const uint32_t codepoint = _glfwKeySym2Unicode(keysym); + if (codepoint == GLFW_INVALID_CODEPOINT) return NULL; - const size_t count = encodeUTF8(_glfw.x11.keynames[key], (unsigned int) ch); + const size_t count = _glfwEncodeUTF8(_glfw.x11.keynames[key], codepoint); if (count == 0) return NULL; diff --git a/src/xkb_unicode.c b/src/xkb_unicode.c index 2772ea09..1b2482cd 100644 --- a/src/xkb_unicode.c +++ b/src/xkb_unicode.c @@ -907,7 +907,7 @@ static const struct codepair { // Convert XKB KeySym to Unicode // -long _glfwKeySym2Unicode(unsigned int keysym) +uint32_t _glfwKeySym2Unicode(unsigned int keysym) { int min = 0; int max = sizeof(keysymtab) / sizeof(struct codepair) - 1; @@ -937,6 +937,6 @@ long _glfwKeySym2Unicode(unsigned int keysym) } // No matching Unicode value found - return -1; + return GLFW_INVALID_CODEPOINT; } diff --git a/src/xkb_unicode.h b/src/xkb_unicode.h index 76d83ffd..b07408f6 100644 --- a/src/xkb_unicode.h +++ b/src/xkb_unicode.h @@ -24,5 +24,7 @@ // //======================================================================== -long _glfwKeySym2Unicode(unsigned int keysym); +#define GLFW_INVALID_CODEPOINT 0xffffffffu + +uint32_t _glfwKeySym2Unicode(unsigned int keysym); diff --git a/tests/gamma.c b/tests/gamma.c index 734955cd..d1f6dc27 100644 --- a/tests/gamma.c +++ b/tests/gamma.c @@ -113,6 +113,12 @@ int main(int argc, char** argv) { const GLFWgammaramp* ramp = glfwGetGammaRamp(monitor); + if (!ramp) + { + glfwTerminate(); + exit(EXIT_FAILURE); + } + const size_t array_size = ramp->size * sizeof(short); orig_ramp.size = ramp->size; orig_ramp.red = malloc(array_size); diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c index a76ca1c2..14347e4b 100644 --- a/tests/glfwinfo.c +++ b/tests/glfwinfo.c @@ -462,7 +462,9 @@ int main(int argc, char** argv) switch (ch) { case PLATFORM: - if (strcasecmp(optarg, PLATFORM_NAME_WIN32) == 0) + if (strcasecmp(optarg, PLATFORM_NAME_ANY) == 0) + platform = GLFW_ANY_PLATFORM; + else if (strcasecmp(optarg, PLATFORM_NAME_WIN32) == 0) platform = GLFW_PLATFORM_WIN32; else if (strcasecmp(optarg, PLATFORM_NAME_COCOA) == 0) platform = GLFW_PLATFORM_COCOA; diff --git a/tests/iconify.c b/tests/iconify.c index e5a428a0..32fd44f2 100644 --- a/tests/iconify.c +++ b/tests/iconify.c @@ -38,7 +38,7 @@ #include "getopt.h" -static int windowed_xpos, windowed_ypos, windowed_width, windowed_height; +static int windowed_xpos, windowed_ypos, windowed_width = 640, windowed_height = 480; static void usage(void) { @@ -181,8 +181,8 @@ static GLFWwindow* create_window(GLFWmonitor* monitor) } else { - width = 640; - height = 480; + width = windowed_width; + height = windowed_height; } window = glfwCreateWindow(width, height, "Iconify", monitor, NULL); diff --git a/tests/window.c b/tests/window.c index 3e2bc671..83baff46 100644 --- a/tests/window.c +++ b/tests/window.c @@ -121,7 +121,7 @@ int main(int argc, char** argv) nk_glfw3_new_frame(); if (nk_begin(nk, "main", area, 0)) { - nk_layout_row_dynamic(nk, 30, 4); + nk_layout_row_dynamic(nk, 30, 5); if (nk_button_label(nk, "Toggle Fullscreen")) { @@ -149,6 +149,16 @@ int main(int argc, char** argv) glfwIconifyWindow(window); if (nk_button_label(nk, "Restore")) glfwRestoreWindow(window); + if (nk_button_label(nk, "Hide (briefly)")) + { + glfwHideWindow(window); + + const double time = glfwGetTime() + 3.0; + while (glfwGetTime() < time) + glfwWaitEventsTimeout(1.0); + + glfwShowWindow(window); + } nk_layout_row_dynamic(nk, 30, 1);