Merge branch 'master' into merge-request-egl-config

This commit is contained in:
Tim 2022-04-01 15:30:43 +02:00 committed by GitHub
commit 55d398da97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 732 additions and 349 deletions

View File

@ -73,8 +73,8 @@ jobs:
- name: Build shared library
run: cmake --build build-shared --parallel
build-windows-win32-vs2019:
name: Win32 (Windows, VS2019)
build-windows-win32-vs2022:
name: Win32 (Windows, VS2022)
runs-on: windows-latest
env:
CFLAGS: /WX
@ -82,12 +82,12 @@ jobs:
- uses: actions/checkout@v2
- name: Configure static library
run: cmake -S . -B build-static -G "Visual Studio 16 2019"
run: cmake -S . -B build-static -G "Visual Studio 17 2022"
- name: Build static library
run: cmake --build build-static --parallel
- name: Configure shared library
run: cmake -S . -B build-shared -G "Visual Studio 16 2019" -D BUILD_SHARED_LIBS=ON
run: cmake -S . -B build-shared -G "Visual Studio 17 2022" -D BUILD_SHARED_LIBS=ON
- name: Build shared library
run: cmake --build build-shared --parallel

View File

@ -10,6 +10,7 @@ video tutorials.
- Matt Arsenault
- ashishgamedev
- David Avedissian
- Luca Bacci
- Keith Bauer
- John Bartholomew
- Coşku Baş
@ -29,6 +30,7 @@ video tutorials.
- David Carlier
- Arturo Castro
- Chi-kwan Chan
- TheChocolateOre
- Joseph Chua
- Ian Clarkson
- Michał Cichoń
@ -68,6 +70,7 @@ video tutorials.
- Ryan C. Gordon
- Stephen Gowen
- Kovid Goyal
- Kevin Grandemange
- Eloi Marín Gratacós
- Stefan Gustavson
- Andrew Gutekanst
@ -81,10 +84,14 @@ video tutorials.
- Paul Holden
- Warren Hu
- Charles Huber
- Brent Huisman
- illustris
- InKryption
- IntellectualKitty
- Aaron Jacobs
- JannikGM
- Erik S. V. Jansson
- jjYBdx4IL
- Toni Jovanoski
- Arseny Kapoulkine
- Cem Karan
@ -183,13 +190,16 @@ video tutorials.
- Ali Sherief
- Yoshiki Shibukawa
- Dmitri Shuralyov
- Joao da Silva
- Daniel Sieger
- Daniel Skorupski
- Slemmie
- Anthony Smith
- Bradley Smith
- Cliff Smolinsky
- Patrick Snape
- Erlend Sogge Heggen
- Olivier Sohn
- Julian Squires
- Johannes Stein
- Pontus Stenetorp
@ -202,6 +212,7 @@ video tutorials.
- Jared Tiala
- Sergey Tikhomirov
- Arthur Tombs
- TronicLabs
- Ioannis Tsakpinis
- Samuli Tuomola
- Matthew Turner

View File

@ -205,6 +205,16 @@ information on what to include when reporting a bug.
- [Win32] Bugfix: Content scale queries could fail silently (#1615)
- [Win32] Bugfix: Content scales could have garbage values if monitor was recently
disconnected (#1615)
- [Win32] Bugfix: A window created maximized and undecorated would cover the whole
monitor (#1806)
- [Win32] Bugfix: The default restored window position was lost when creating a maximized
window
- [Win32] Bugfix: `glfwMaximizeWindow` would make a hidden window visible
- [Win32] Bugfix: `Alt+PrtSc` would emit `GLFW_KEY_UNKNOWN` and a different
scancode than `PrtSc` (#1993)
- [Win32] Bugfix: `GLFW_KEY_PAUSE` scancode from `glfwGetKeyScancode` did not
match event scancode (#1993)
- [Win32] Bugfix: Instance-local operations used executable instance (#469,#1296,#1395)
- [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)
@ -235,6 +245,7 @@ information on what to include when reporting a bug.
a fraction of a second (#1962)
- [Cocoa] Bugfix: `kIOMasterPortDefault` was deprecated in macOS 12.0 (#1980)
- [Cocoa] Bugfix: `kUTTypeURL` was deprecated in macOS 12.0 (#2003)
- [Cocoa] Bugfix: A connected Apple AirPlay would emit a useless error (#1791)
- [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)
@ -266,6 +277,14 @@ information on what to include when reporting a bug.
- [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
- [X11] Bugfix: Waiting for events would fail if file descriptor was too large
(#2024)
- [X11] Bugfix: Joystick events could lead to busy-waiting (#1872)
- [X11] Bugfix: `glfwWaitEvents*` did not continue for joystick events
- [X11] Bugfix: `glfwPostEmptyEvent` could be ignored due to race condition
(#379,#1281,#1285,#2033)
- [X11] Bugfix: Dynamic loading on NetBSD failed due to soname differences
- [X11] Bugfix: Left shift of int constant relied on undefined behavior (#1951)
- [Wayland] Added dynamic loading of all Wayland libraries
- [Wayland] Added support for key names via xkbcommon
- [Wayland] Removed support for `wl_shell` (#1443)
@ -290,6 +309,7 @@ information on what to include when reporting a bug.
- [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
- [Wayland] Bugfix: `glfwPostEmptyEvent` sometimes had no effect (#1520,#1521)
- [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)
@ -305,6 +325,7 @@ information on what to include when reporting a bug.
(#1380)
- [EGL] Bugfix: The `GLFW_DOUBLEBUFFER` context attribute was ignored (#1843)
- [EGL] Made it possible to query the `EGLConfig` that was chosen to create a given window via `glfwGetEGLConfig`
- [GLX] Bugfix: Context creation failed if GLX 1.4 was not exported by GLX library
## Contact

View File

@ -68,8 +68,10 @@ install the `xorgproto` package.
pkg install xorgproto
@endcode
On Cygwin the `xorgproto` package in the Devel section of the GUI installer will
install the headers and other development related files for all of X11.
On Cygwin the `libXcursor-devel`, `libXi-devel`, `libXinerama-devel`,
`libXrandr-devel` and `libXrender-devel` packages in the Libs section of the GUI
installer will install all the headers and other development related files GLFW
requires for X11.
Once you have the required dependencies, move on to @ref compile_generate.

View File

@ -821,7 +821,7 @@ The second value is always the human-readable name of the gamepad.
All subsequent values are in the form `<field>:<value>` and describe the layout
of the mapping. These fields may not all be present and may occur in any order.
The button fields are `a`, `b`, `c`, `d`, `back`, `start`, `guide`, `dpup`,
The button fields are `a`, `b`, `x`, `y`, `back`, `start`, `guide`, `dpup`,
`dpright`, `dpdown`, `dpleft`, `leftshoulder`, `rightshoulder`, `leftstick` and
`rightstick`.

View File

@ -144,6 +144,12 @@ GLFW_TRANSPARENT_FRAMEBUFFER on Windows 7 if DWM transparency is off
(the Transparency setting under Personalization > Window Color).
@subsubsection emptyevents_34 Empty events on X11 no longer roundtrip to server
Events posted with @ref glfwPostEmptyEvent now use a separate unnamed pipe
instead of sending an X11 client event to the helper window.
@subsection deprecations_34 Deprecations in version 3.4
@subsection removals_34 Removals in 3.4

View File

@ -3258,7 +3258,8 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
* count is zero.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR and @ref
* GLFW_FEATURE_UNAVAILABLE (see remarks).
*
* @pointer_lifetime The specified image data is copied before this function
* returns.
@ -4892,8 +4893,8 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
* @return The handle of the created cursor, 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_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
*
* @pointer_lifetime The specified image data is copied before this function
* returns.

View File

@ -82,9 +82,10 @@ extern "C" {
*************************************************************************/
#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
// example to allow applications to correctly declare a GL_KHR_debug callback)
// but windows.h assumes no one will define APIENTRY before it does
/* This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
* example to allow applications to correctly declare a GL_KHR_debug callback)
* but windows.h assumes no one will define APIENTRY before it does
*/
#if defined(GLFW_APIENTRY_DEFINED)
#undef APIENTRY
#undef GLFW_APIENTRY_DEFINED
@ -111,12 +112,22 @@ extern "C" {
/* NSGL is declared by Cocoa.h */
#endif
#if defined(GLFW_EXPOSE_NATIVE_GLX)
/* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by
* default it also acts as an OpenGL header
* However, glx.h will include gl.h, which will define it unconditionally
*/
#undef GLAPIENTRY
#include <GL/glx.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_EGL)
#include <EGL/egl.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
/* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by
* default it also acts as an OpenGL header
* However, osmesa.h will include gl.h, which will define it unconditionally
*/
#undef GLAPIENTRY
#include <GL/osmesa.h>
#endif

View File

@ -60,6 +60,7 @@ if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND)
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_sources(glfw PRIVATE linux_joystick.h linux_joystick.c)
endif()
target_sources(glfw PRIVATE posix_poll.h posix_poll.c)
endif()
if (GLFW_BUILD_WAYLAND)

View File

@ -98,11 +98,7 @@ static char* getMonitorName(CGDirectDisplayID displayID, NSScreen* screen)
IOObjectRelease(it);
if (!service)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to find service port for display");
return _glfw_strdup("Display");
}
CFDictionaryRef names =
CFDictionaryGetValue(info, CFSTR(kDisplayProductName));

View File

@ -325,7 +325,7 @@ GLFWbool _glfwInitEGL(void)
"libEGL.dylib",
#elif defined(__CYGWIN__)
"libEGL-1.so",
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
"libEGL.so",
#else
"libEGL.so.1",
@ -506,7 +506,7 @@ void _glfwTerminateEGL(void)
}
}
#define setAttrib(a, v) \
#define SET_ATTRIB(a, v) \
{ \
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
@ -584,13 +584,13 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
{
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
EGL_NO_RESET_NOTIFICATION_KHR);
SET_ATTRIB(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
EGL_NO_RESET_NOTIFICATION_KHR);
}
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
{
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
EGL_LOSE_CONTEXT_ON_RESET_KHR);
SET_ATTRIB(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
EGL_LOSE_CONTEXT_ON_RESET_KHR);
}
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
@ -599,42 +599,42 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (ctxconfig->noerror)
{
if (_glfw.egl.KHR_create_context_no_error)
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
SET_ATTRIB(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
}
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
SET_ATTRIB(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
SET_ATTRIB(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
}
if (mask)
setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
SET_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
if (flags)
setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
SET_ATTRIB(EGL_CONTEXT_FLAGS_KHR, flags);
}
else
{
if (ctxconfig->client == GLFW_OPENGL_ES_API)
setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
SET_ATTRIB(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
}
if (_glfw.egl.KHR_context_flush_control)
{
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
{
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
SET_ATTRIB(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
}
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
{
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
SET_ATTRIB(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
}
}
setAttrib(EGL_NONE, EGL_NONE);
SET_ATTRIB(EGL_NONE, EGL_NONE);
window->context.egl.handle = eglCreateContext(_glfw.egl.display,
config, share, attribs);
@ -653,16 +653,16 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (fbconfig->sRGB)
{
if (_glfw.egl.KHR_gl_colorspace)
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
SET_ATTRIB(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
}
if (!fbconfig->doublebuffer)
setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
SET_ATTRIB(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
if (_glfw.egl.EXT_present_opaque)
setAttrib(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent);
SET_ATTRIB(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent);
setAttrib(EGL_NONE, EGL_NONE);
SET_ATTRIB(EGL_NONE, EGL_NONE);
native = _glfw.platform.getEGLNativeWindow(window);
// HACK: ANGLE does not implement eglCreatePlatformWindowSurfaceEXT
@ -702,7 +702,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
"libGLES_CM.dll",
#elif defined(_GLFW_COCOA)
"libGLESv1_CM.dylib",
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
"libGLESv1_CM.so",
#else
"libGLESv1_CM.so.1",
@ -721,7 +721,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
"libGLESv2.dylib",
#elif defined(__CYGWIN__)
"libGLESv2-2.so",
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
"libGLESv2.so",
#else
"libGLESv2.so.2",
@ -734,7 +734,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
_GLFW_OPENGL_LIBRARY,
#elif defined(_GLFW_WIN32)
#elif defined(_GLFW_COCOA)
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
"libGL.so",
#else
"libGL.so.1",
@ -782,7 +782,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
return GLFW_TRUE;
}
#undef setAttrib
#undef SET_ATTRIB
// Returns the Visual and depth of the chosen EGLConfig
//

View File

@ -259,7 +259,7 @@ GLFWbool _glfwInitGLX(void)
_GLFW_GLX_LIBRARY,
#elif defined(__CYGWIN__)
"libGL-1.so",
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
"libGL.so",
#else
"libGL.so.1",
@ -308,10 +308,6 @@ GLFWbool _glfwInitGLX(void)
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXCreateWindow");
_glfw.glx.DestroyWindow = (PFNGLXDESTROYWINDOWPROC)
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXDestroyWindow");
_glfw.glx.GetProcAddress = (PFNGLXGETPROCADDRESSPROC)
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetProcAddress");
_glfw.glx.GetProcAddressARB = (PFNGLXGETPROCADDRESSPROC)
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetProcAddressARB");
_glfw.glx.GetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetVisualFromFBConfig");
@ -327,8 +323,6 @@ GLFWbool _glfwInitGLX(void)
!_glfw.glx.CreateNewContext ||
!_glfw.glx.CreateWindow ||
!_glfw.glx.DestroyWindow ||
!_glfw.glx.GetProcAddress ||
!_glfw.glx.GetProcAddressARB ||
!_glfw.glx.GetVisualFromFBConfig)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
@ -336,6 +330,12 @@ GLFWbool _glfwInitGLX(void)
return GLFW_FALSE;
}
// NOTE: Unlike GLX 1.3 entry points these are not required to be present
_glfw.glx.GetProcAddress = (PFNGLXGETPROCADDRESSPROC)
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetProcAddress");
_glfw.glx.GetProcAddressARB = (PFNGLXGETPROCADDRESSPROC)
_glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetProcAddressARB");
if (!glXQueryExtension(_glfw.x11.display,
&_glfw.glx.errorBase,
&_glfw.glx.eventBase))
@ -435,7 +435,7 @@ void _glfwTerminateGLX(void)
}
}
#define setAttrib(a, v) \
#define SET_ATTRIB(a, v) \
{ \
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
@ -523,13 +523,13 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
{
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
{
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
GLX_NO_RESET_NOTIFICATION_ARB);
SET_ATTRIB(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
GLX_NO_RESET_NOTIFICATION_ARB);
}
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
{
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
GLX_LOSE_CONTEXT_ON_RESET_ARB);
SET_ATTRIB(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
GLX_LOSE_CONTEXT_ON_RESET_ARB);
}
flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
@ -542,13 +542,13 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
{
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
{
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
SET_ATTRIB(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
}
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
{
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
SET_ATTRIB(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
}
}
}
@ -556,7 +556,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
if (ctxconfig->noerror)
{
if (_glfw.glx.ARB_create_context_no_error)
setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
SET_ATTRIB(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
}
// NOTE: Only request an explicitly versioned context when necessary, as
@ -564,17 +564,17 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
// highest version supported by the driver
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
setAttrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
setAttrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
SET_ATTRIB(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
SET_ATTRIB(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
}
if (mask)
setAttrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
SET_ATTRIB(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
if (flags)
setAttrib(GLX_CONTEXT_FLAGS_ARB, flags);
SET_ATTRIB(GLX_CONTEXT_FLAGS_ARB, flags);
setAttrib(None, None);
SET_ATTRIB(None, None);
window->context.glx.handle =
_glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
@ -631,7 +631,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
return GLFW_TRUE;
}
#undef setAttrib
#undef SET_ATTRIB
// Returns the Visual and depth of the chosen GLXFBConfig
//

View File

@ -179,6 +179,16 @@ char* _glfw_strdup(const char* source)
return result;
}
int _glfw_min(int a, int b)
{
return a < b ? a : b;
}
int _glfw_max(int a, int b)
{
return a > b ? a : b;
}
float _glfw_fminf(float a, float b)
{
if (a != a)

View File

@ -764,9 +764,16 @@ GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
_GLFWcursor* cursor;
assert(image != NULL);
assert(image->pixels != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (image->width <= 0 || image->height <= 0)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid image dimensions for cursor");
return NULL;
}
cursor = _glfw_calloc(1, sizeof(_GLFWcursor));
cursor->next = _glfw.cursorListHead;
_glfw.cursorListHead = cursor;

View File

@ -998,6 +998,8 @@ const char* _glfwGetVulkanResultString(VkResult result);
size_t _glfwEncodeUTF8(char* s, uint32_t codepoint);
char* _glfw_strdup(const char* source);
int _glfw_min(int a, int b);
int _glfw_max(int a, int b);
float _glfw_fminf(float a, float b);
float _glfw_fmaxf(float a, float b);

View File

@ -188,45 +188,45 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
// No-error contexts (GL_KHR_no_error) are not yet supported by macOS but
// are not a hard constraint, so ignore and continue
#define addAttrib(a) \
#define ADD_ATTRIB(a) \
{ \
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
}
#define setAttrib(a, v) { addAttrib(a); addAttrib(v); }
#define SET_ATTRIB(a, v) { ADD_ATTRIB(a); ADD_ATTRIB(v); }
NSOpenGLPixelFormatAttribute attribs[40];
int index = 0;
addAttrib(NSOpenGLPFAAccelerated);
addAttrib(NSOpenGLPFAClosestPolicy);
ADD_ATTRIB(NSOpenGLPFAAccelerated);
ADD_ATTRIB(NSOpenGLPFAClosestPolicy);
if (ctxconfig->nsgl.offline)
{
addAttrib(NSOpenGLPFAAllowOfflineRenderers);
ADD_ATTRIB(NSOpenGLPFAAllowOfflineRenderers);
// NOTE: This replaces the NSSupportsAutomaticGraphicsSwitching key in
// Info.plist for unbundled applications
// HACK: This assumes that NSOpenGLPixelFormat will remain
// a straightforward wrapper of its CGL counterpart
addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
ADD_ATTRIB(kCGLPFASupportsAutomaticGraphicsSwitching);
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
if (ctxconfig->major >= 4)
{
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
}
else
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
if (ctxconfig->major >= 3)
{
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
}
if (ctxconfig->major <= 2)
{
if (fbconfig->auxBuffers != GLFW_DONT_CARE)
setAttrib(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
SET_ATTRIB(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
fbconfig->accumGreenBits != GLFW_DONT_CARE &&
@ -238,7 +238,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
fbconfig->accumBlueBits +
fbconfig->accumAlphaBits;
setAttrib(NSOpenGLPFAAccumSize, accumBits);
SET_ATTRIB(NSOpenGLPFAAccumSize, accumBits);
}
}
@ -256,17 +256,17 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
else if (colorBits < 15)
colorBits = 15;
setAttrib(NSOpenGLPFAColorSize, colorBits);
SET_ATTRIB(NSOpenGLPFAColorSize, colorBits);
}
if (fbconfig->alphaBits != GLFW_DONT_CARE)
setAttrib(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
SET_ATTRIB(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
if (fbconfig->depthBits != GLFW_DONT_CARE)
setAttrib(NSOpenGLPFADepthSize, fbconfig->depthBits);
SET_ATTRIB(NSOpenGLPFADepthSize, fbconfig->depthBits);
if (fbconfig->stencilBits != GLFW_DONT_CARE)
setAttrib(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
SET_ATTRIB(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
if (fbconfig->stereo)
{
@ -275,33 +275,33 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
"NSGL: Stereo rendering is deprecated");
return GLFW_FALSE;
#else
addAttrib(NSOpenGLPFAStereo);
ADD_ATTRIB(NSOpenGLPFAStereo);
#endif
}
if (fbconfig->doublebuffer)
addAttrib(NSOpenGLPFADoubleBuffer);
ADD_ATTRIB(NSOpenGLPFADoubleBuffer);
if (fbconfig->samples != GLFW_DONT_CARE)
{
if (fbconfig->samples == 0)
{
setAttrib(NSOpenGLPFASampleBuffers, 0);
SET_ATTRIB(NSOpenGLPFASampleBuffers, 0);
}
else
{
setAttrib(NSOpenGLPFASampleBuffers, 1);
setAttrib(NSOpenGLPFASamples, fbconfig->samples);
SET_ATTRIB(NSOpenGLPFASampleBuffers, 1);
SET_ATTRIB(NSOpenGLPFASamples, fbconfig->samples);
}
}
// NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
// framebuffer, so there's no need (and no way) to request it
addAttrib(0);
ADD_ATTRIB(0);
#undef addAttrib
#undef setAttrib
#undef ADD_ATTRIB
#undef SET_ATTRIB
window->context.nsgl.pixelFormat =
[[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];

View File

@ -39,15 +39,15 @@ static void applySizeLimits(_GLFWwindow* window, int* width, int* height)
*height = (int) (*width / ratio);
}
if (window->minwidth != GLFW_DONT_CARE && *width < window->minwidth)
*width = window->minwidth;
else if (window->maxwidth != GLFW_DONT_CARE && *width > window->maxwidth)
*width = window->maxwidth;
if (window->minwidth != GLFW_DONT_CARE)
*width = _glfw_max(*width, window->minwidth);
else if (window->maxwidth != GLFW_DONT_CARE)
*width = _glfw_min(*width, window->maxwidth);
if (window->minheight != GLFW_DONT_CARE && *height < window->minheight)
*height = window->minheight;
else if (window->maxheight != GLFW_DONT_CARE && *height > window->maxheight)
*height = window->maxheight;
if (window->minheight != GLFW_DONT_CARE)
*height = _glfw_min(*height, window->minheight);
else if (window->maxheight != GLFW_DONT_CARE)
*height = _glfw_max(*height, window->maxheight);
}
static void fitToMonitor(_GLFWwindow* window)

View File

@ -124,7 +124,7 @@ GLFWbool _glfwInitOSMesa(void)
"libOSMesa.8.dylib",
#elif defined(__CYGWIN__)
"libOSMesa-8.so",
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
"libOSMesa.so",
#else
"libOSMesa.so.8",
@ -190,7 +190,7 @@ void _glfwTerminateOSMesa(void)
}
}
#define setAttrib(a, v) \
#define SET_ATTRIB(a, v) \
{ \
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
@ -221,24 +221,24 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
{
int index = 0, attribs[40];
setAttrib(OSMESA_FORMAT, OSMESA_RGBA);
setAttrib(OSMESA_DEPTH_BITS, fbconfig->depthBits);
setAttrib(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
setAttrib(OSMESA_ACCUM_BITS, accumBits);
SET_ATTRIB(OSMESA_FORMAT, OSMESA_RGBA);
SET_ATTRIB(OSMESA_DEPTH_BITS, fbconfig->depthBits);
SET_ATTRIB(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
SET_ATTRIB(OSMESA_ACCUM_BITS, accumBits);
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
{
setAttrib(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
SET_ATTRIB(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
}
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
{
setAttrib(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
SET_ATTRIB(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
}
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
setAttrib(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
setAttrib(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
SET_ATTRIB(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
SET_ATTRIB(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
}
if (ctxconfig->forward)
@ -248,7 +248,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
return GLFW_FALSE;
}
setAttrib(0, 0);
SET_ATTRIB(0, 0);
window->context.osmesa.handle =
OSMesaCreateContextAttribs(attribs, share);
@ -287,7 +287,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
return GLFW_TRUE;
}
#undef setAttrib
#undef SET_ATTRIB
//////////////////////////////////////////////////////////////////////////

81
src/posix_poll.c Normal file
View File

@ -0,0 +1,81 @@
//========================================================================
// GLFW 3.4 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2022 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#define _GNU_SOURCE
#include "internal.h"
#include <signal.h>
#include <time.h>
#include <errno.h>
GLFWbool _glfwPollPOSIX(struct pollfd* fds, nfds_t count, double* timeout)
{
for (;;)
{
if (timeout)
{
const uint64_t base = _glfwPlatformGetTimerValue();
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__)
const time_t seconds = (time_t) *timeout;
const long nanoseconds = (long) ((*timeout - seconds) * 1e9);
const struct timespec ts = { seconds, nanoseconds };
const int result = ppoll(fds, count, &ts, NULL);
#elif defined(__NetBSD__)
const time_t seconds = (time_t) *timeout;
const long nanoseconds = (long) ((*timeout - seconds) * 1e9);
const struct timespec ts = { seconds, nanoseconds };
const int result = pollts(fds, count, &ts, NULL);
#else
const int milliseconds = (int) (*timeout * 1e3);
const int result = poll(fds, count, milliseconds);
#endif
const int error = errno; // clock_gettime may overwrite our error
*timeout -= (_glfwPlatformGetTimerValue() - base) /
(double) _glfwPlatformGetTimerFrequency();
if (result > 0)
return GLFW_TRUE;
else if (result == -1 && error != EINTR && error != EAGAIN)
return GLFW_FALSE;
else if (*timeout <= 0.0)
return GLFW_FALSE;
}
else
{
const int result = poll(fds, count, -1);
if (result > 0)
return GLFW_TRUE;
else if (result == -1 && errno != EINTR && errno != EAGAIN)
return GLFW_FALSE;
}
}
}

32
src/posix_poll.h Normal file
View File

@ -0,0 +1,32 @@
//========================================================================
// GLFW 3.4 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2022 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include <poll.h>
GLFWbool _glfwPollPOSIX(struct pollfd* fds, nfds_t count, double* timeout);

View File

@ -63,7 +63,7 @@ GLFWbool _glfwInitVulkan(int mode)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib");
if (!_glfw.vk.handle)
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa();
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so");
#else
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1");

View File

@ -52,12 +52,12 @@ static int findPixelFormatAttribValueWGL(const int* attribs,
return 0;
}
#define addAttrib(a) \
#define ADD_ATTRIB(a) \
{ \
assert((size_t) attribCount < sizeof(attribs) / sizeof(attribs[0])); \
attribs[attribCount++] = a; \
}
#define findAttribValue(a) \
#define FIND_ATTRIB_VALUE(a) \
findPixelFormatAttribValueWGL(attribs, attribCount, values, a)
// Return a list of available and usable framebuffer configs
@ -84,41 +84,41 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
return 0;
}
addAttrib(WGL_SUPPORT_OPENGL_ARB);
addAttrib(WGL_DRAW_TO_WINDOW_ARB);
addAttrib(WGL_PIXEL_TYPE_ARB);
addAttrib(WGL_ACCELERATION_ARB);
addAttrib(WGL_RED_BITS_ARB);
addAttrib(WGL_RED_SHIFT_ARB);
addAttrib(WGL_GREEN_BITS_ARB);
addAttrib(WGL_GREEN_SHIFT_ARB);
addAttrib(WGL_BLUE_BITS_ARB);
addAttrib(WGL_BLUE_SHIFT_ARB);
addAttrib(WGL_ALPHA_BITS_ARB);
addAttrib(WGL_ALPHA_SHIFT_ARB);
addAttrib(WGL_DEPTH_BITS_ARB);
addAttrib(WGL_STENCIL_BITS_ARB);
addAttrib(WGL_ACCUM_BITS_ARB);
addAttrib(WGL_ACCUM_RED_BITS_ARB);
addAttrib(WGL_ACCUM_GREEN_BITS_ARB);
addAttrib(WGL_ACCUM_BLUE_BITS_ARB);
addAttrib(WGL_ACCUM_ALPHA_BITS_ARB);
addAttrib(WGL_AUX_BUFFERS_ARB);
addAttrib(WGL_STEREO_ARB);
addAttrib(WGL_DOUBLE_BUFFER_ARB);
ADD_ATTRIB(WGL_SUPPORT_OPENGL_ARB);
ADD_ATTRIB(WGL_DRAW_TO_WINDOW_ARB);
ADD_ATTRIB(WGL_PIXEL_TYPE_ARB);
ADD_ATTRIB(WGL_ACCELERATION_ARB);
ADD_ATTRIB(WGL_RED_BITS_ARB);
ADD_ATTRIB(WGL_RED_SHIFT_ARB);
ADD_ATTRIB(WGL_GREEN_BITS_ARB);
ADD_ATTRIB(WGL_GREEN_SHIFT_ARB);
ADD_ATTRIB(WGL_BLUE_BITS_ARB);
ADD_ATTRIB(WGL_BLUE_SHIFT_ARB);
ADD_ATTRIB(WGL_ALPHA_BITS_ARB);
ADD_ATTRIB(WGL_ALPHA_SHIFT_ARB);
ADD_ATTRIB(WGL_DEPTH_BITS_ARB);
ADD_ATTRIB(WGL_STENCIL_BITS_ARB);
ADD_ATTRIB(WGL_ACCUM_BITS_ARB);
ADD_ATTRIB(WGL_ACCUM_RED_BITS_ARB);
ADD_ATTRIB(WGL_ACCUM_GREEN_BITS_ARB);
ADD_ATTRIB(WGL_ACCUM_BLUE_BITS_ARB);
ADD_ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB);
ADD_ATTRIB(WGL_AUX_BUFFERS_ARB);
ADD_ATTRIB(WGL_STEREO_ARB);
ADD_ATTRIB(WGL_DOUBLE_BUFFER_ARB);
if (_glfw.wgl.ARB_multisample)
addAttrib(WGL_SAMPLES_ARB);
ADD_ATTRIB(WGL_SAMPLES_ARB);
if (ctxconfig->client == GLFW_OPENGL_API)
{
if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB)
addAttrib(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
ADD_ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
}
else
{
if (_glfw.wgl.EXT_colorspace)
addAttrib(WGL_COLORSPACE_EXT);
ADD_ATTRIB(WGL_COLORSPACE_EXT);
}
}
else
@ -152,48 +152,48 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
return 0;
}
if (!findAttribValue(WGL_SUPPORT_OPENGL_ARB) ||
!findAttribValue(WGL_DRAW_TO_WINDOW_ARB))
if (!FIND_ATTRIB_VALUE(WGL_SUPPORT_OPENGL_ARB) ||
!FIND_ATTRIB_VALUE(WGL_DRAW_TO_WINDOW_ARB))
{
continue;
}
if (findAttribValue(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB)
if (FIND_ATTRIB_VALUE(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB)
continue;
if (findAttribValue(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB)
if (FIND_ATTRIB_VALUE(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB)
continue;
if (findAttribValue(WGL_DOUBLE_BUFFER_ARB) != fbconfig->doublebuffer)
if (FIND_ATTRIB_VALUE(WGL_DOUBLE_BUFFER_ARB) != fbconfig->doublebuffer)
continue;
u->redBits = findAttribValue(WGL_RED_BITS_ARB);
u->greenBits = findAttribValue(WGL_GREEN_BITS_ARB);
u->blueBits = findAttribValue(WGL_BLUE_BITS_ARB);
u->alphaBits = findAttribValue(WGL_ALPHA_BITS_ARB);
u->redBits = FIND_ATTRIB_VALUE(WGL_RED_BITS_ARB);
u->greenBits = FIND_ATTRIB_VALUE(WGL_GREEN_BITS_ARB);
u->blueBits = FIND_ATTRIB_VALUE(WGL_BLUE_BITS_ARB);
u->alphaBits = FIND_ATTRIB_VALUE(WGL_ALPHA_BITS_ARB);
u->depthBits = findAttribValue(WGL_DEPTH_BITS_ARB);
u->stencilBits = findAttribValue(WGL_STENCIL_BITS_ARB);
u->depthBits = FIND_ATTRIB_VALUE(WGL_DEPTH_BITS_ARB);
u->stencilBits = FIND_ATTRIB_VALUE(WGL_STENCIL_BITS_ARB);
u->accumRedBits = findAttribValue(WGL_ACCUM_RED_BITS_ARB);
u->accumGreenBits = findAttribValue(WGL_ACCUM_GREEN_BITS_ARB);
u->accumBlueBits = findAttribValue(WGL_ACCUM_BLUE_BITS_ARB);
u->accumAlphaBits = findAttribValue(WGL_ACCUM_ALPHA_BITS_ARB);
u->accumRedBits = FIND_ATTRIB_VALUE(WGL_ACCUM_RED_BITS_ARB);
u->accumGreenBits = FIND_ATTRIB_VALUE(WGL_ACCUM_GREEN_BITS_ARB);
u->accumBlueBits = FIND_ATTRIB_VALUE(WGL_ACCUM_BLUE_BITS_ARB);
u->accumAlphaBits = FIND_ATTRIB_VALUE(WGL_ACCUM_ALPHA_BITS_ARB);
u->auxBuffers = findAttribValue(WGL_AUX_BUFFERS_ARB);
u->auxBuffers = FIND_ATTRIB_VALUE(WGL_AUX_BUFFERS_ARB);
if (findAttribValue(WGL_STEREO_ARB))
if (FIND_ATTRIB_VALUE(WGL_STEREO_ARB))
u->stereo = GLFW_TRUE;
if (_glfw.wgl.ARB_multisample)
u->samples = findAttribValue(WGL_SAMPLES_ARB);
u->samples = FIND_ATTRIB_VALUE(WGL_SAMPLES_ARB);
if (ctxconfig->client == GLFW_OPENGL_API)
{
if (_glfw.wgl.ARB_framebuffer_sRGB ||
_glfw.wgl.EXT_framebuffer_sRGB)
{
if (findAttribValue(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
if (FIND_ATTRIB_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
u->sRGB = GLFW_TRUE;
}
}
@ -201,7 +201,7 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
{
if (_glfw.wgl.EXT_colorspace)
{
if (findAttribValue(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
if (FIND_ATTRIB_VALUE(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
u->sRGB = GLFW_TRUE;
}
}
@ -290,8 +290,8 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
return pixelFormat;
}
#undef addAttrib
#undef findAttribValue
#undef ADD_ATTRIB
#undef FIND_ATTRIB_VALUE
static void makeContextCurrentWGL(_GLFWwindow* window)
{
@ -523,7 +523,7 @@ void _glfwTerminateWGL(void)
_glfwPlatformFreeModule(_glfw.wgl.instance);
}
#define setAttrib(a, v) \
#define SET_ATTRIB(a, v) \
{ \
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
@ -631,13 +631,13 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
{
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
{
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_NO_RESET_NOTIFICATION_ARB);
SET_ATTRIB(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_NO_RESET_NOTIFICATION_ARB);
}
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
{
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_LOSE_CONTEXT_ON_RESET_ARB);
SET_ATTRIB(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_LOSE_CONTEXT_ON_RESET_ARB);
}
flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
@ -650,13 +650,13 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
{
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
{
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
SET_ATTRIB(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
}
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
{
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
SET_ATTRIB(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
}
}
}
@ -664,7 +664,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
if (ctxconfig->noerror)
{
if (_glfw.wgl.ARB_create_context_no_error)
setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
SET_ATTRIB(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
}
// NOTE: Only request an explicitly versioned context when necessary, as
@ -672,17 +672,17 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
// highest version supported by the driver
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
}
if (flags)
setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
SET_ATTRIB(WGL_CONTEXT_FLAGS_ARB, flags);
if (mask)
setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
setAttrib(0, 0);
SET_ATTRIB(0, 0);
window->context.wgl.handle =
wglCreateContextAttribsARB(window->context.wgl.dc, share, attribs);
@ -765,7 +765,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
return GLFW_TRUE;
}
#undef setAttrib
#undef SET_ATTRIB
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
{

View File

@ -71,6 +71,16 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
//
static GLFWbool loadLibraries(void)
{
if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(const WCHAR*) &_glfw,
(HMODULE*) &_glfw.win32.instance))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to retrieve own module handle");
return GLFW_FALSE;
}
_glfw.win32.user32.instance = _glfwPlatformLoadModule("user32.dll");
if (!_glfw.win32.user32.instance)
{
@ -91,6 +101,8 @@ static GLFWbool loadLibraries(void)
_glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetDpiForWindow");
_glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
_glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
_glfw.win32.user32.GetSystemMetricsForDpi_ = (PFN_GetSystemMetricsForDpi)
_glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetSystemMetricsForDpi");
_glfw.win32.dinput8.instance = _glfwPlatformLoadModule("dinput8.dll");
if (_glfw.win32.dinput8.instance)
@ -251,7 +263,6 @@ static void createKeyTables(void)
_glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN;
_glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP;
_glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE;
_glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE;
_glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE;
_glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB;
_glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK;
@ -333,7 +344,7 @@ static GLFWbool createHelperWindow(void)
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
0, 0, 1, 1,
NULL, NULL,
GetModuleHandleW(NULL),
_glfw.win32.instance,
NULL);
if (!_glfw.win32.helperWindowHandle)
@ -483,7 +494,7 @@ void _glfwUpdateKeyNamesWin32(void)
vk = vks[key - GLFW_KEY_KP_0];
}
else
vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK);
vk = MapVirtualKeyW(scancode, MAPVK_VSC_TO_VK);
length = ToUnicode(vk, scancode, state,
chars, sizeof(chars) / sizeof(WCHAR),
@ -506,7 +517,8 @@ void _glfwUpdateKeyNamesWin32(void)
}
}
// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h
// Replacement for IsWindowsVersionOrGreater, as we cannot rely on the
// application having a correct embedded manifest
//
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
{
@ -626,7 +638,7 @@ int _glfwInitWin32(void)
createKeyTables();
_glfwUpdateKeyNamesWin32();
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
if (_glfwIsWindows10Version1703OrGreaterWin32())
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
else if (IsWindows8Point1OrGreater())
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);

View File

@ -574,7 +574,7 @@ GLFWbool _glfwInitJoysticksWin32(void)
{
if (_glfw.win32.dinput8.instance)
{
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
if (FAILED(DirectInput8Create(_glfw.win32.instance,
DIRECTINPUT_VERSION,
&IID_IDirectInput8W,
(void**) &_glfw.win32.dinput8.api,

View File

@ -381,7 +381,7 @@ void _glfwGetMonitorWorkareaWin32(_GLFWmonitor* monitor,
int* width, int* height)
{
MONITORINFO mi = { sizeof(mi) };
GetMonitorInfo(monitor->win32.handle, &mi);
GetMonitorInfoW(monitor->win32.handle, &mi);
if (xpos)
*xpos = mi.rcWork.left;

View File

@ -162,7 +162,9 @@ typedef enum
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
// Replacement for versionhelpers.h macros, as we cannot rely on the
// application having a correct embedded manifest
//
#define IsWindowsVistaOrGreater() \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA), \
LOBYTE(_WIN32_WINNT_VISTA), 0)
@ -176,9 +178,11 @@ typedef enum
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINBLUE), \
LOBYTE(_WIN32_WINNT_WINBLUE), 0)
#define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32() \
// Windows 10 Anniversary Update
#define _glfwIsWindows10Version1607OrGreaterWin32() \
_glfwIsWindows10BuildOrGreaterWin32(14393)
#define _glfwIsWindows10CreatorsUpdateOrGreaterWin32() \
// Windows 10 Creators Update
#define _glfwIsWindows10Version1703OrGreaterWin32() \
_glfwIsWindows10BuildOrGreaterWin32(15063)
// HACK: Define macros that some xinput.h variants don't
@ -283,12 +287,14 @@ typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
typedef int (WINAPI * PFN_GetSystemMetricsForDpi)(int,UINT);
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
#define GetSystemMetricsForDpi _glfw.win32.user32.GetSystemMetricsForDpi_
// dwmapi.dll function pointer typedefs
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
@ -436,6 +442,7 @@ typedef struct _GLFWwindowWin32
//
typedef struct _GLFWlibraryWin32
{
HINSTANCE instance;
HWND helperWindowHandle;
HDEVNOTIFY deviceNotificationHandle;
int acquiredMonitorCount;
@ -471,6 +478,7 @@ typedef struct _GLFWlibraryWin32
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
PFN_GetDpiForWindow GetDpiForWindow_;
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
PFN_GetSystemMetricsForDpi GetSystemMetricsForDpi_;
} user32;
struct {

View File

@ -97,8 +97,7 @@ static const GLFWimage* chooseImage(int count, const GLFWimage* images,
// Creates an RGBA icon or cursor
//
static HICON createIcon(const GLFWimage* image,
int xhot, int yhot, GLFWbool icon)
static HICON createIcon(const GLFWimage* image, int xhot, int yhot, GLFWbool icon)
{
int i;
HDC dc;
@ -194,7 +193,7 @@ static void getFullWindowSize(DWORD style, DWORD exStyle,
{
RECT rect = { 0, 0, contentWidth, contentHeight };
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
if (_glfwIsWindows10Version1607OrGreaterWin32())
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
else
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
@ -211,7 +210,7 @@ static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
UINT dpi = USER_DEFAULT_SCREEN_DPI;
const float ratio = (float) window->numer / (float) window->denom;
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
if (_glfwIsWindows10Version1607OrGreaterWin32())
dpi = GetDpiForWindow(window->win32.handle);
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
@ -354,7 +353,7 @@ static void updateWindowStyles(const _GLFWwindow* window)
GetClientRect(window->win32.handle, &rect);
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
if (_glfwIsWindows10Version1607OrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, style, FALSE,
getWindowExStyle(window),
@ -434,7 +433,7 @@ static int getKeyMods(void)
static void fitToMonitor(_GLFWwindow* window)
{
MONITORINFO mi = { sizeof(mi) };
GetMonitorInfo(window->monitor->win32.handle, &mi);
GetMonitorInfoW(window->monitor->win32.handle, &mi);
SetWindowPos(window->win32.handle, HWND_TOPMOST,
mi.rcMonitor.left,
mi.rcMonitor.top,
@ -453,8 +452,8 @@ static void acquireMonitor(_GLFWwindow* window)
// HACK: When mouse trails are enabled the cursor becomes invisible when
// the OpenGL ICD switches to page flipping
SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);
SystemParametersInfoW(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
SystemParametersInfoW(SPI_SETMOUSETRAILS, 0, 0, 0);
}
if (!window->monitor->window)
@ -477,17 +476,66 @@ static void releaseMonitor(_GLFWwindow* window)
SetThreadExecutionState(ES_CONTINUOUS);
// HACK: Restore mouse trail length saved in acquireMonitor
SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
SystemParametersInfoW(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
}
_glfwInputMonitorWindow(window->monitor, NULL);
_glfwRestoreVideoModeWin32(window->monitor);
}
// Manually maximize the window, for when SW_MAXIMIZE cannot be used
//
static void maximizeWindowManually(_GLFWwindow* window)
{
RECT rect;
DWORD style;
MONITORINFO mi = { sizeof(mi) };
GetMonitorInfoW(MonitorFromWindow(window->win32.handle,
MONITOR_DEFAULTTONEAREST), &mi);
rect = mi.rcWork;
if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)
{
rect.right = _glfw_min(rect.right, rect.left + window->maxwidth);
rect.bottom = _glfw_min(rect.bottom, rect.top + window->maxheight);
}
style = GetWindowLongW(window->win32.handle, GWL_STYLE);
style |= WS_MAXIMIZE;
SetWindowLongW(window->win32.handle, GWL_STYLE, style);
if (window->decorated)
{
const DWORD exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
if (_glfwIsWindows10Version1607OrGreaterWin32())
{
const UINT dpi = GetDpiForWindow(window->win32.handle);
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
OffsetRect(&rect, 0, GetSystemMetricsForDpi(SM_CYCAPTION, dpi));
}
else
{
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
OffsetRect(&rect, 0, GetSystemMetrics(SM_CYCAPTION));
}
rect.bottom = _glfw_min(rect.bottom, mi.rcWork.bottom);
}
SetWindowPos(window->win32.handle, HWND_TOP,
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
// Window callback function (handles window messages)
//
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
_GLFWwindow* window = GetPropW(hWnd, L"GLFW");
if (!window)
@ -499,7 +547,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
{
case WM_NCCREATE:
{
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
if (_glfwIsWindows10Version1607OrGreaterWin32())
{
const CREATESTRUCTW* cs = (const CREATESTRUCTW*) lParam;
const _GLFWwndconfig* wndconfig = cs->lpCreateParams;
@ -704,6 +752,14 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
scancode = MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC);
}
// HACK: Alt+PrtSc has a different scancode than just PrtSc
if (scancode == 0x54)
scancode = 0x137;
// HACK: Ctrl+Pause has a different scancode than just Pause
if (scancode == 0x146)
scancode = 0x45;
key = _glfw.win32.keycodes[scancode];
// The Ctrl keys require special handling
@ -1045,7 +1101,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (window->monitor)
break;
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
if (_glfwIsWindows10Version1607OrGreaterWin32())
dpi = GetDpiForWindow(window->win32.handle);
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
@ -1073,7 +1129,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
ZeroMemory(&mi, sizeof(mi));
mi.cbSize = sizeof(mi);
GetMonitorInfo(mh, &mi);
GetMonitorInfoW(mh, &mi);
mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;
mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;
@ -1120,7 +1176,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
break;
// Adjust the window size to keep the content area size constant
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
if (_glfwIsWindows10Version1703OrGreaterWin32())
{
RECT source = {0}, target = {0};
SIZE* size = (SIZE*) lParam;
@ -1151,7 +1207,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
// need it to compensate for non-client area scaling
if (!window->monitor &&
(window->win32.scaleToMonitor ||
_glfwIsWindows10CreatorsUpdateOrGreaterWin32()))
_glfwIsWindows10Version1703OrGreaterWin32()))
{
RECT* suggested = (RECT*) lParam;
SetWindowPos(window->win32.handle, HWND_TOP,
@ -1265,7 +1321,7 @@ static int createNativeWindow(_GLFWwindow* window,
fullWidth, fullHeight,
NULL, // No parent window
NULL, // No window menu
GetModuleHandleW(NULL),
_glfw.win32.instance,
(LPVOID) wndconfig);
_glfw_free(wideTitle);
@ -1292,18 +1348,22 @@ static int createNativeWindow(_GLFWwindow* window,
window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
window->win32.keymenu = wndconfig->win32.keymenu;
// Adjust window rect to account for DPI scaling of the window frame and
// (if enabled) DPI scaling of the content area
// This cannot be done until we know what monitor the window was placed on
if (!window->monitor)
{
RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
WINDOWPLACEMENT wp = { sizeof(wp) };
const HMONITOR mh = MonitorFromWindow(window->win32.handle,
MONITOR_DEFAULTTONEAREST);
// Adjust window rect to account for DPI scaling of the window frame and
// (if enabled) DPI scaling of the content area
// This cannot be done until we know what monitor the window was placed on
// Only update the restored window rect as the window may be maximized
if (wndconfig->scaleToMonitor)
{
float xscale, yscale;
_glfwGetWindowContentScaleWin32(window, &xscale, &yscale);
_glfwGetHMONITORContentScaleWin32(mh, &xscale, &yscale);
if (xscale > 0.f && yscale > 0.f)
{
@ -1312,10 +1372,7 @@ static int createNativeWindow(_GLFWwindow* window,
}
}
ClientToScreen(window->win32.handle, (POINT*) &rect.left);
ClientToScreen(window->win32.handle, (POINT*) &rect.right);
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
if (_glfwIsWindows10Version1607OrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
GetDpiForWindow(window->win32.handle));
@ -1323,11 +1380,30 @@ static int createNativeWindow(_GLFWwindow* window,
else
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
// Only update the restored window rect as the window may be maximized
GetWindowPlacement(window->win32.handle, &wp);
OffsetRect(&rect,
wp.rcNormalPosition.left - rect.left,
wp.rcNormalPosition.top - rect.top);
wp.rcNormalPosition = rect;
wp.showCmd = SW_HIDE;
SetWindowPlacement(window->win32.handle, &wp);
// Adjust rect of maximized undecorated window, because by default Windows will
// make such a window cover the whole monitor instead of its workarea
if (wndconfig->maximized && !wndconfig->decorated)
{
MONITORINFO mi = { sizeof(mi) };
GetMonitorInfoW(mh, &mi);
SetWindowPos(window->win32.handle, HWND_TOP,
mi.rcWork.left,
mi.rcWork.top,
mi.rcWork.right - mi.rcWork.left,
mi.rcWork.bottom - mi.rcWork.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
}
DragAcceptFiles(window->win32.handle, TRUE);
@ -1353,7 +1429,7 @@ GLFWbool _glfwRegisterWindowClassWin32(void)
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) windowProc;
wc.hInstance = GetModuleHandleW(NULL);
wc.hInstance = _glfw.win32.instance;
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
wc.lpszClassName = _GLFW_WNDCLASSNAME;
@ -1383,7 +1459,7 @@ GLFWbool _glfwRegisterWindowClassWin32(void)
//
void _glfwUnregisterWindowClassWin32(void)
{
UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));
UnregisterClassW(_GLFW_WNDCLASSNAME, _glfw.win32.instance);
}
int _glfwCreateWindowWin32(_GLFWwindow* window,
@ -1465,8 +1541,7 @@ void _glfwSetWindowTitleWin32(_GLFWwindow* window, const char* title)
_glfw_free(wideTitle);
}
void _glfwSetWindowIconWin32(_GLFWwindow* window,
int count, const GLFWimage* images)
void _glfwSetWindowIconWin32(_GLFWwindow* window, int count, const GLFWimage* images)
{
HICON bigIcon = NULL, smallIcon = NULL;
@ -1488,8 +1563,8 @@ void _glfwSetWindowIconWin32(_GLFWwindow* window,
smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM);
}
SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
SendMessageW(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
SendMessageW(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
if (window->win32.bigIcon)
DestroyIcon(window->win32.bigIcon);
@ -1519,7 +1594,7 @@ void _glfwSetWindowPosWin32(_GLFWwindow* window, int xpos, int ypos)
{
RECT rect = { xpos, ypos, xpos, ypos };
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
if (_glfwIsWindows10Version1607OrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
@ -1560,7 +1635,7 @@ void _glfwSetWindowSizeWin32(_GLFWwindow* window, int width, int height)
{
RECT rect = { 0, 0, width, height };
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
if (_glfwIsWindows10Version1607OrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
@ -1579,8 +1654,8 @@ void _glfwSetWindowSizeWin32(_GLFWwindow* window, int width, int height)
}
void _glfwSetWindowSizeLimitsWin32(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight)
int minwidth, int minheight,
int maxwidth, int maxheight)
{
RECT area;
@ -1618,8 +1693,8 @@ void _glfwGetFramebufferSizeWin32(_GLFWwindow* window, int* width, int* height)
}
void _glfwGetWindowFrameSizeWin32(_GLFWwindow* window,
int* left, int* top,
int* right, int* bottom)
int* left, int* top,
int* right, int* bottom)
{
RECT rect;
int width, height;
@ -1627,7 +1702,7 @@ void _glfwGetWindowFrameSizeWin32(_GLFWwindow* window,
_glfwGetWindowSizeWin32(window, &width, &height);
SetRect(&rect, 0, 0, width, height);
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
if (_glfwIsWindows10Version1607OrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
@ -1668,7 +1743,10 @@ void _glfwRestoreWindowWin32(_GLFWwindow* window)
void _glfwMaximizeWindowWin32(_GLFWwindow* window)
{
ShowWindow(window->win32.handle, SW_MAXIMIZE);
if (IsWindowVisible(window->win32.handle))
ShowWindow(window->win32.handle, SW_MAXIMIZE);
else
maximizeWindowManually(window);
}
void _glfwShowWindowWin32(_GLFWwindow* window)
@ -1713,7 +1791,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
{
RECT rect = { xpos, ypos, xpos + width, ypos + height };
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
if (_glfwIsWindows10Version1607OrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
@ -1755,7 +1833,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
acquireMonitor(window);
GetMonitorInfo(window->monitor->win32.handle, &mi);
GetMonitorInfoW(window->monitor->win32.handle, &mi);
SetWindowPos(window->win32.handle, HWND_TOPMOST,
mi.rcMonitor.left,
mi.rcMonitor.top,
@ -1784,7 +1862,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
else
after = HWND_NOTOPMOST;
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
if (_glfwIsWindows10Version1607OrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
@ -2052,7 +2130,7 @@ void _glfwWaitEventsTimeoutWin32(double timeout)
void _glfwPostEmptyEventWin32(void)
{
PostMessage(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
PostMessageW(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
}
void _glfwGetCursorPosWin32(_GLFWwindow* window, double* xpos, double* ypos)
@ -2113,8 +2191,8 @@ int _glfwGetKeyScancodeWin32(int key)
}
int _glfwCreateCursorWin32(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot)
const GLFWimage* image,
int xhot, int yhot)
{
cursor->win32.handle = (HCURSOR) createIcon(image, xhot, yhot, GLFW_FALSE);
if (!cursor->win32.handle)
@ -2369,7 +2447,7 @@ VkResult _glfwCreateWindowSurfaceWin32(VkInstance instance,
memset(&sci, 0, sizeof(sci));
sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
sci.hinstance = GetModuleHandle(NULL);
sci.hinstance = _glfw.win32.instance;
sci.hwnd = window->win32.handle;
err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);

View File

@ -514,12 +514,33 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,
int count, const GLFWimage* images)
{
int i;
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(count >= 0);
assert(count == 0 || images != NULL);
_GLFW_REQUIRE_INIT();
if (count < 0)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid image count for window icon");
return;
}
for (i = 0; i < count; i++)
{
assert(images[i].pixels != NULL);
if (images[i].width <= 0 || images[i].height <= 0)
{
_glfwInputError(GLFW_INVALID_VALUE,
"Invalid image dimensions for window icon");
return;
}
}
_glfw.platform.setWindowIcon(window, count, images);
}

View File

@ -57,11 +57,6 @@
#include "wayland-idle-inhibit-unstable-v1-client-protocol-code.h"
static inline int min(int n1, int n2)
{
return n1 < n2 ? n1 : n2;
}
static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
int* which)
{
@ -788,7 +783,7 @@ static void registryHandleGlobal(void* data,
{
if (strcmp(interface, "wl_compositor") == 0)
{
_glfw.wl.compositorVersion = min(3, version);
_glfw.wl.compositorVersion = _glfw_min(3, version);
_glfw.wl.compositor =
wl_registry_bind(registry, name, &wl_compositor_interface,
_glfw.wl.compositorVersion);
@ -811,7 +806,7 @@ static void registryHandleGlobal(void* data,
{
if (!_glfw.wl.seat)
{
_glfw.wl.seatVersion = min(4, version);
_glfw.wl.seatVersion = _glfw_min(4, version);
_glfw.wl.seat =
wl_registry_bind(registry, name, &wl_seat_interface,
_glfw.wl.seatVersion);
@ -1367,14 +1362,15 @@ int _glfwInitWayland(void)
wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
_glfw.wl.seat);
wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL);
_glfw.wl.clipboardString = _glfw_calloc(4096, 1);
_glfw.wl.clipboardSize = 4096;
_glfw.wl.clipboardString = _glfw_calloc(_glfw.wl.clipboardSize, 1);
if (!_glfw.wl.clipboardString)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
_glfwInputError(GLFW_OUT_OF_MEMORY,
"Wayland: Unable to allocate clipboard memory");
return GLFW_FALSE;
}
_glfw.wl.clipboardSize = 4096;
}
return GLFW_TRUE;
@ -1460,9 +1456,7 @@ void _glfwTerminateWayland(void)
if (_glfw.wl.cursorTimerfd >= 0)
close(_glfw.wl.cursorTimerfd);
if (_glfw.wl.clipboardString)
_glfw_free(_glfw.wl.clipboardString);
if (_glfw.wl.clipboardSendString)
_glfw_free(_glfw.wl.clipboardSendString);
_glfw_free(_glfw.wl.clipboardString);
_glfw_free(_glfw.wl.clipboardSendString);
}

View File

@ -43,6 +43,7 @@ typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWa
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
#include "xkb_unicode.h"
#include "posix_poll.h"
typedef int (* PFN_wl_display_flush)(struct wl_display *display);
typedef void (* PFN_wl_display_cancel_read)(struct wl_display *display);

View File

@ -345,26 +345,21 @@ static void resizeWindow(_GLFWwindow* window)
static void checkScaleChange(_GLFWwindow* window)
{
int scale = 1;
int monitorScale;
// Check if we will be able to set the buffer scale or not.
if (_glfw.wl.compositorVersion < 3)
return;
// Get the scale factor from the highest scale monitor.
for (int i = 0; i < window->wl.monitorsCount; ++i)
{
monitorScale = window->wl.monitors[i]->wl.scale;
if (scale < monitorScale)
scale = monitorScale;
}
int maxScale = 1;
for (int i = 0; i < window->wl.monitorsCount; i++)
maxScale = _glfw_max(window->wl.monitors[i]->wl.scale, maxScale);
// Only change the framebuffer size if the scale changed.
if (scale != window->wl.scale)
if (window->wl.scale != maxScale)
{
window->wl.scale = scale;
wl_surface_set_buffer_scale(window->wl.surface, scale);
window->wl.scale = maxScale;
wl_surface_set_buffer_scale(window->wl.surface, maxScale);
resizeWindow(window);
}
}
@ -717,8 +712,28 @@ static void incrementCursorImage(_GLFWwindow* window)
}
}
static void handleEvents(int timeout)
static GLFWbool flushDisplay(void)
{
while (wl_display_flush(_glfw.wl.display) == -1)
{
if (errno != EAGAIN)
return GLFW_FALSE;
struct pollfd fd = { wl_display_get_fd(_glfw.wl.display), POLLOUT };
while (poll(&fd, 1, -1) == -1)
{
if (errno != EINTR && errno != EAGAIN)
return GLFW_FALSE;
}
}
return GLFW_TRUE;
}
static void handleEvents(double* timeout)
{
GLFWbool event = GLFW_FALSE;
struct pollfd fds[] =
{
{ wl_display_get_fd(_glfw.wl.display), POLLIN },
@ -726,30 +741,38 @@ static void handleEvents(int timeout)
{ _glfw.wl.cursorTimerfd, POLLIN },
};
while (wl_display_prepare_read(_glfw.wl.display) != 0)
wl_display_dispatch_pending(_glfw.wl.display);
// 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)
while (!event)
{
_GLFWwindow* window = _glfw.windowListHead;
while (window)
while (wl_display_prepare_read(_glfw.wl.display) != 0)
wl_display_dispatch_pending(_glfw.wl.display);
// 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 (!flushDisplay())
{
_glfwInputWindowCloseRequest(window);
window = window->next;
wl_display_cancel_read(_glfw.wl.display);
_GLFWwindow* window = _glfw.windowListHead;
while (window)
{
_glfwInputWindowCloseRequest(window);
window = window->next;
}
return;
}
wl_display_cancel_read(_glfw.wl.display);
return;
}
if (!_glfwPollPOSIX(fds, 3, timeout))
{
wl_display_cancel_read(_glfw.wl.display);
return;
}
if (poll(fds, 3, timeout) > 0)
{
if (fds[0].revents & POLLIN)
{
wl_display_read_events(_glfw.wl.display);
wl_display_dispatch_pending(_glfw.wl.display);
if (wl_display_dispatch_pending(_glfw.wl.display) > 0)
event = GLFW_TRUE;
}
else
wl_display_cancel_read(_glfw.wl.display);
@ -770,6 +793,8 @@ static void handleEvents(int timeout)
_glfwInputTextWayland(_glfw.wl.keyboardFocus,
_glfw.wl.keyboardLastScancode);
}
event = GLFW_TRUE;
}
}
@ -778,11 +803,12 @@ static void handleEvents(int timeout)
uint64_t repeats;
if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
{
incrementCursorImage(_glfw.wl.pointerFocus);
event = GLFW_TRUE;
}
}
}
else
wl_display_cancel_read(_glfw.wl.display);
}
//////////////////////////////////////////////////////////////////////////
@ -1149,22 +1175,24 @@ GLFWbool _glfwRawMouseMotionSupportedWayland(void)
void _glfwPollEventsWayland(void)
{
handleEvents(0);
double timeout = 0.0;
handleEvents(&timeout);
}
void _glfwWaitEventsWayland(void)
{
handleEvents(-1);
handleEvents(NULL);
}
void _glfwWaitEventsTimeoutWayland(double timeout)
{
handleEvents((int) (timeout * 1e3));
handleEvents(&timeout);
}
void _glfwPostEmptyEventWayland(void)
{
wl_display_sync(_glfw.wl.display);
flushDisplay();
}
void _glfwGetCursorPosWayland(_GLFWwindow* window, double* xpos, double* ypos)
@ -1675,7 +1703,7 @@ static GLFWbool growClipboardString(void)
clipboard = _glfw_realloc(clipboard, _glfw.wl.clipboardSize * 2);
if (!clipboard)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
_glfwInputError(GLFW_OUT_OF_MEMORY,
"Wayland: Impossible to grow clipboard string");
return GLFW_FALSE;
}
@ -1710,9 +1738,9 @@ const char* _glfwGetClipboardStringWayland(void)
close(fds[1]);
// XXX: this is a huge hack, this function shouldnt be synchronous!
handleEvents(-1);
handleEvents(NULL);
while (1)
for (;;)
{
// Grow the clipboard if we need to paste something bigger, there is no
// shrink operation yet.

View File

@ -35,6 +35,8 @@
#include <stdio.h>
#include <locale.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
// Translate the X11 KeySyms for a key to a GLFW key code
@ -601,7 +603,7 @@ static void detectEWMH(void)
//
static GLFWbool initExtensions(void)
{
#if defined(__OpenBSD__)
#if defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so");
#else
_glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so.1");
@ -625,7 +627,7 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__)
_glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi-6.so");
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so");
#else
_glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so.6");
@ -657,7 +659,7 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__)
_glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr-2.so");
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so");
#else
_glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so.2");
@ -751,7 +753,7 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__)
_glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor-1.so");
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so");
#else
_glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so.1");
@ -774,7 +776,7 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__)
_glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama-1.so");
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so");
#else
_glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so.1");
@ -829,7 +831,7 @@ static GLFWbool initExtensions(void)
{
#if defined(__CYGWIN__)
_glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb-1.so");
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so");
#else
_glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so.1");
@ -844,7 +846,7 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__)
_glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender-1.so");
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so");
#else
_glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so.1");
@ -873,7 +875,7 @@ static GLFWbool initExtensions(void)
#if defined(__CYGWIN__)
_glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext-6.so");
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so");
#else
_glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so.6");
@ -1042,6 +1044,37 @@ static Window createHelperWindow(void)
CWEventMask, &wa);
}
// Create the pipe for empty events without assumuing the OS has pipe2(2)
//
static GLFWbool createEmptyEventPipe(void)
{
if (pipe(_glfw.x11.emptyEventPipe) != 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Failed to create empty event pipe: %s",
strerror(errno));
return GLFW_FALSE;
}
for (int i = 0; i < 2; i++)
{
const int sf = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFL, 0);
const int df = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFD, 0);
if (sf == -1 || df == -1 ||
fcntl(_glfw.x11.emptyEventPipe[i], F_SETFL, sf | O_NONBLOCK) == -1 ||
fcntl(_glfw.x11.emptyEventPipe[i], F_SETFD, df | FD_CLOEXEC) == -1)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Failed to set flags for empty event pipe: %s",
strerror(errno));
return GLFW_FALSE;
}
}
return GLFW_TRUE;
}
// X error handler
//
static int errorHandler(Display *display, XErrorEvent* event)
@ -1221,7 +1254,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform)
#if defined(__CYGWIN__)
void* module = _glfwPlatformLoadModule("libX11-6.so");
#elif defined(__OpenBSD__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
void* module = _glfwPlatformLoadModule("libX11.so");
#else
void* module = _glfwPlatformLoadModule("libX11.so.6");
@ -1491,6 +1524,9 @@ int _glfwInitX11(void)
getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY);
if (!createEmptyEventPipe())
return GLFW_FALSE;
if (!initExtensions())
return GLFW_FALSE;
@ -1604,5 +1640,11 @@ void _glfwTerminateX11(void)
_glfwPlatformFreeModule(_glfw.x11.xlib.handle);
_glfw.x11.xlib.handle = NULL;
}
if (_glfw.x11.emptyEventPipe[0] || _glfw.x11.emptyEventPipe[1])
{
close(_glfw.x11.emptyEventPipe[0]);
close(_glfw.x11.emptyEventPipe[1]);
}
}

View File

@ -453,6 +453,7 @@ typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSur
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
#include "xkb_unicode.h"
#include "posix_poll.h"
#define GLFW_X11_WINDOW_STATE _GLFWwindowX11 x11;
#define GLFW_X11_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11;
@ -582,6 +583,7 @@ typedef struct _GLFWlibraryX11
double restoreCursorPosX, restoreCursorPosY;
// The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow;
int emptyEventPipe[2];
// Window manager atoms
Atom NET_SUPPORTED;

View File

@ -32,7 +32,7 @@
#include <X11/cursorfont.h>
#include <X11/Xmd.h>
#include <sys/select.h>
#include <poll.h>
#include <string.h>
#include <stdio.h>
@ -56,50 +56,79 @@
#define _GLFW_XDND_VERSION 5
// Wait for data to arrive using select
// Wait for event data to arrive on the X11 display socket
// This avoids blocking other threads via the per-display Xlib lock that also
// covers GLX functions
//
static GLFWbool waitForEvent(double* timeout)
static GLFWbool waitForX11Event(double* timeout)
{
fd_set fds;
const int fd = ConnectionNumber(_glfw.x11.display);
int count = fd + 1;
struct pollfd fd = { ConnectionNumber(_glfw.x11.display), POLLIN };
while (!XPending(_glfw.x11.display))
{
if (!_glfwPollPOSIX(&fd, 1, timeout))
return GLFW_FALSE;
}
return GLFW_TRUE;
}
// Wait for event data to arrive on any event file descriptor
// This avoids blocking other threads via the per-display Xlib lock that also
// covers GLX functions
//
static GLFWbool waitForAnyEvent(double* timeout)
{
nfds_t count = 2;
struct pollfd fds[3] =
{
{ ConnectionNumber(_glfw.x11.display), POLLIN },
{ _glfw.x11.emptyEventPipe[0], POLLIN }
};
#if defined(__linux__)
if (_glfw.linjs.inotify > fd)
count = _glfw.linjs.inotify + 1;
if (_glfw.joysticksInitialized)
fds[count++] = (struct pollfd) { _glfw.linjs.inotify, POLLIN };
#endif
while (!XPending(_glfw.x11.display))
{
if (!_glfwPollPOSIX(fds, count, timeout))
return GLFW_FALSE;
for (int i = 1; i < count; i++)
{
if (fds[i].revents & POLLIN)
return GLFW_TRUE;
}
}
return GLFW_TRUE;
}
// Writes a byte to the empty event pipe
//
static void writeEmptyEvent(void)
{
for (;;)
{
FD_ZERO(&fds);
FD_SET(fd, &fds);
#if defined(__linux__)
if (_glfw.linjs.inotify > 0)
FD_SET(_glfw.linjs.inotify, &fds);
#endif
const char byte = 0;
const int result = write(_glfw.x11.emptyEventPipe[1], &byte, 1);
if (result == 1 || (result == -1 && errno != EINTR))
break;
}
}
if (timeout)
{
const long seconds = (long) *timeout;
const long microseconds = (long) ((*timeout - seconds) * 1e6);
struct timeval tv = { seconds, microseconds };
const uint64_t base = _glfwPlatformGetTimerValue();
const int result = select(count, &fds, NULL, NULL, &tv);
const int error = errno;
*timeout -= (_glfwPlatformGetTimerValue() - base) /
(double) _glfwPlatformGetTimerFrequency();
if (result > 0)
return GLFW_TRUE;
if ((result == -1 && error == EINTR) || *timeout <= 0.0)
return GLFW_FALSE;
}
else if (select(count, &fds, NULL, NULL, NULL) != -1 || errno != EINTR)
return GLFW_TRUE;
// Drains available data from the empty event pipe
//
static void drainEmptyEvents(void)
{
for (;;)
{
char dummy[64];
const int result = read(_glfw.x11.emptyEventPipe[0], dummy, sizeof(dummy));
if (result == -1 && errno != EINTR)
break;
}
}
@ -116,7 +145,7 @@ static GLFWbool waitForVisibilityNotify(_GLFWwindow* window)
VisibilityNotify,
&dummy))
{
if (!waitForEvent(&timeout))
if (!waitForX11Event(&timeout))
return GLFW_FALSE;
}
@ -958,7 +987,7 @@ static const char* getSelectionString(Atom selection)
SelectionNotify,
&notification))
{
waitForEvent(NULL);
waitForX11Event(NULL);
}
if (notification.xselection.property == None)
@ -994,7 +1023,7 @@ static const char* getSelectionString(Atom selection)
isSelPropNewValueNotify,
(XPointer) &notification))
{
waitForEvent(NULL);
waitForX11Event(NULL);
}
XFree(data);
@ -1238,7 +1267,7 @@ static void processEvent(XEvent *event)
// (the server never sends a timestamp of zero)
// NOTE: Timestamp difference is compared to handle wrap-around
Time diff = event->xkey.time - window->x11.keyPressTimes[keycode];
if (diff == event->xkey.time || (diff > 0 && diff < (1 << 31)))
if (diff == event->xkey.time || (diff > 0 && diff < ((Time)1 << 31)))
{
if (keycode)
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
@ -1896,7 +1925,7 @@ void _glfwPushSelectionToManagerX11(void)
}
}
waitForEvent(NULL);
waitForX11Event(NULL);
}
}
@ -2238,7 +2267,7 @@ void _glfwGetWindowFrameSizeX11(_GLFWwindow* window,
isFrameExtentsEvent,
(XPointer) window))
{
if (!waitForEvent(&timeout))
if (!waitForX11Event(&timeout))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
@ -2744,7 +2773,7 @@ GLFWbool _glfwRawMouseMotionSupportedX11(void)
void _glfwPollEventsX11(void)
{
_GLFWwindow* window;
drainEmptyEvents();
#if defined(__linux__)
if (_glfw.joysticksInitialized)
@ -2759,7 +2788,7 @@ void _glfwPollEventsX11(void)
processEvent(&event);
}
window = _glfw.x11.disabledCursorWindow;
_GLFWwindow* window = _glfw.x11.disabledCursorWindow;
if (window)
{
int width, height;
@ -2779,32 +2808,19 @@ void _glfwPollEventsX11(void)
void _glfwWaitEventsX11(void)
{
while (!XPending(_glfw.x11.display))
waitForEvent(NULL);
waitForAnyEvent(NULL);
_glfwPollEventsX11();
}
void _glfwWaitEventsTimeoutX11(double timeout)
{
while (!XPending(_glfw.x11.display))
{
if (!waitForEvent(&timeout))
break;
}
waitForAnyEvent(&timeout);
_glfwPollEventsX11();
}
void _glfwPostEmptyEventX11(void)
{
XEvent event = { ClientMessage };
event.xclient.window = _glfw.x11.helperWindowHandle;
event.xclient.format = 32; // Data is 32-bit longs
event.xclient.message_type = _glfw.x11.NULL_;
XSendEvent(_glfw.x11.display, _glfw.x11.helperWindowHandle, False, 0, &event);
XFlush(_glfw.x11.display);
writeEmptyEvent();
}
void _glfwGetCursorPosX11(_GLFWwindow* window, double* xpos, double* ypos)