mirror of
https://github.com/glfw/glfw.git
synced 2024-11-26 03:52:01 +00:00
Merge branch '3.3-stable' into new-cursors-on-3.3-stable
This commit is contained in:
commit
830b05ecf9
24
.travis.yml
24
.travis.yml
@ -69,6 +69,28 @@ matrix:
|
||||
- USE_WAYLAND=ON
|
||||
- BUILD_SHARED_LIBS=OFF
|
||||
- CFLAGS=-Werror
|
||||
- os: linux
|
||||
dist: bionic
|
||||
name: "Null shared library"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libosmesa6-dev
|
||||
env:
|
||||
- BUILD_SHARED_LIBS=ON
|
||||
- USE_OSMESA=ON
|
||||
- CFLAGS=-Werror
|
||||
- os: linux
|
||||
dist: bionic
|
||||
name: "Null static library"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libosmesa6-dev
|
||||
env:
|
||||
- BUILD_SHARED_LIBS=OFF
|
||||
- USE_OSMESA=ON
|
||||
- CFLAGS=-Werror
|
||||
- os: osx
|
||||
sudo: false
|
||||
name: "Cocoa shared library"
|
||||
@ -96,7 +118,7 @@ script:
|
||||
git checkout 1.15 && ./autogen.sh --prefix=/usr && make && sudo make install;
|
||||
popd;
|
||||
fi
|
||||
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} -DGLFW_USE_WAYLAND=${USE_WAYLAND} ..
|
||||
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} -DGLFW_USE_WAYLAND=${USE_WAYLAND} -DGLFW_USE_OSMESA=${USE_OSMESA} ..
|
||||
- cmake --build .
|
||||
notifications:
|
||||
email:
|
||||
|
@ -244,7 +244,7 @@ if (_GLFW_WAYLAND)
|
||||
find_package(WaylandScanner REQUIRED)
|
||||
find_package(WaylandProtocols 1.15 REQUIRED)
|
||||
|
||||
list(APPEND glfw_PKG_DEPS "wayland-egl")
|
||||
list(APPEND glfw_PKG_DEPS "wayland-client")
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${Wayland_INCLUDE_DIRS}")
|
||||
list(APPEND glfw_LIBRARIES "${Wayland_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
|
||||
|
11
README.md
11
README.md
@ -123,7 +123,17 @@ information on what to include when reporting a bug.
|
||||
- Added `GLFW_RESIZE_EW_CURSOR` alias for `GLFW_HRESIZE_CURSOR` (#427)
|
||||
- Added `GLFW_RESIZE_NS_CURSOR` alias for `GLFW_VRESIZE_CURSOR` (#427)
|
||||
- Added `GLFW_POINTING_HAND_CURSOR` alias for `GLFW_HAND_CURSOR` (#427)
|
||||
- Bugfix: Some extension loader headers did not prevent default OpenGL header
|
||||
inclusion (#1695)
|
||||
- [Cocoa] Use `CALayer` instead of `NSView` for `EGLNativeWindowType` (#1169)
|
||||
- [X11] Bugfix: IME input of CJK was broken for "C" locale (#1587,#1636)
|
||||
- [X11] Bugfix: Xlib errors caused by other parts of the application could be
|
||||
reported as GLFW errors
|
||||
- [X11] Bugfix: A handle race condition could cause a `BadWindow` error (#1633)
|
||||
- [X11] Bugfix: XKB path used keysyms instead of physical locations for
|
||||
non-printable keys (#1598)
|
||||
- [X11] Bugfix: Function keys were mapped to `GLFW_KEY_UNKNOWN` for some layout
|
||||
combinaitons (#1598)
|
||||
|
||||
|
||||
## Contact
|
||||
@ -295,6 +305,7 @@ skills.
|
||||
- Matt Sealey
|
||||
- Steve Sexton
|
||||
- Arkady Shapkin
|
||||
- Ali Sherief
|
||||
- Yoshiki Shibukawa
|
||||
- Dmitri Shuralyov
|
||||
- Daniel Skorupski
|
||||
|
4
deps/linmath.h
vendored
4
deps/linmath.h
vendored
@ -237,9 +237,9 @@ static inline void mat4x4_rotate_Y(mat4x4 Q, mat4x4 M, float angle)
|
||||
float s = sinf(angle);
|
||||
float c = cosf(angle);
|
||||
mat4x4 R = {
|
||||
{ c, 0.f, s, 0.f},
|
||||
{ c, 0.f, -s, 0.f},
|
||||
{ 0.f, 1.f, 0.f, 0.f},
|
||||
{ -s, 0.f, c, 0.f},
|
||||
{ s, 0.f, c, 0.f},
|
||||
{ 0.f, 0.f, 0.f, 1.f}
|
||||
};
|
||||
mat4x4_mul(Q, M, R);
|
||||
|
@ -25,39 +25,41 @@ GLFW.
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
This header declares the GLFW API and by default also includes the OpenGL header
|
||||
from your development environment. See below for how to control this.
|
||||
This header defines all the constants and declares all the types and function
|
||||
prototypes of the GLFW API. By default it also includes the OpenGL header from
|
||||
your development environment. See [option macros](@ref build_macros) below for
|
||||
how to select OpenGL ES headers and more.
|
||||
|
||||
The GLFW header also defines any platform-specific macros needed by your OpenGL
|
||||
header, so it can be included without needing any window system headers.
|
||||
header, so that it can be included without needing any window system headers.
|
||||
|
||||
For example, under Windows you are normally required to include `windows.h`
|
||||
before the OpenGL header, which would bring in the whole Win32 API. The GLFW
|
||||
header duplicates the small number of macros needed.
|
||||
|
||||
It does this only when needed, so if `windows.h` _is_ included, the GLFW header
|
||||
does not try to redefine those symbols. The reverse is not true, i.e.
|
||||
`windows.h` cannot cope if any of its symbols have already been defined.
|
||||
It does this only when needed, so if window system headers are included, the
|
||||
GLFW header does not try to redefine those symbols. The reverse is not true,
|
||||
i.e. `windows.h` cannot cope if any Win32 symbols have already been defined.
|
||||
|
||||
In other words:
|
||||
|
||||
- Do _not_ include the OpenGL headers yourself, as GLFW does this for you
|
||||
- Do _not_ include `windows.h` or other platform-specific headers unless you
|
||||
plan on using those APIs directly
|
||||
- If you _do_ need to include such headers, do it _before_ including
|
||||
the GLFW header and it will handle this
|
||||
- Use the GLFW header to include OpenGL or OpenGL ES headers portably
|
||||
- Do not include window system headers unless you will use those APIs directly
|
||||
- If you do need such headers, include them before the GLFW header
|
||||
|
||||
If you are using an OpenGL extension loading library such as
|
||||
[glad](https://github.com/Dav1dde/glad), the extension loader header should
|
||||
be included _before_ the GLFW one.
|
||||
be included before the GLFW one. GLFW attempts to detect any OpenGL or OpenGL
|
||||
ES header or extension loader header included before it and will then disable
|
||||
the inclusion of the default OpenGL header. Most extension loaders also define
|
||||
macros that disable similar headers below it.
|
||||
|
||||
@code
|
||||
#include <glad/gl.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
Alternatively the @ref GLFW_INCLUDE_NONE macro (described below) can be used to
|
||||
prevent the GLFW header from including the OpenGL header.
|
||||
Both of these mechanisms depend on the extension loader header defining a known
|
||||
macro. If yours doesn't or you don't know which one your users will pick, the
|
||||
@ref GLFW_INCLUDE_NONE macro will explicitly to prevent the GLFW header from
|
||||
including the OpenGL header. This will also allow you to include the two
|
||||
headers in any order.
|
||||
|
||||
@code
|
||||
#define GLFW_INCLUDE_NONE
|
||||
@ -105,7 +107,7 @@ __GLFW_INCLUDE_ES31__ makes the GLFW header include the OpenGL ES 3.1
|
||||
`GLES3/gl31.h` header instead of the regular OpenGL header.
|
||||
|
||||
@anchor GLFW_INCLUDE_ES32
|
||||
__GLFW_INCLUDE_ES31__ makes the GLFW header include the OpenGL ES 3.2
|
||||
__GLFW_INCLUDE_ES32__ makes the GLFW header include the OpenGL ES 3.2
|
||||
`GLES3/gl32.h` header instead of the regular OpenGL header.
|
||||
|
||||
@anchor GLFW_INCLUDE_NONE
|
||||
@ -113,7 +115,8 @@ __GLFW_INCLUDE_NONE__ makes the GLFW header not include any OpenGL or OpenGL ES
|
||||
API header. This is useful in combination with an extension loading library.
|
||||
|
||||
If none of the above inclusion macros are defined, the standard OpenGL `GL/gl.h`
|
||||
header (`OpenGL/gl.h` on macOS) is included.
|
||||
header (`OpenGL/gl.h` on macOS) is included, unless GLFW detects the inclusion
|
||||
guards of any OpenGL, OpenGL ES or extension loader header it knows about.
|
||||
|
||||
The following macros control the inclusion of additional API headers. Any
|
||||
number of these may be defined simultaneously, and/or together with one of the
|
||||
@ -219,12 +222,15 @@ find_package(OpenGL REQUIRED)
|
||||
@endcode
|
||||
|
||||
If OpenGL is found, the `OpenGL::GL` target is added to your project, containing
|
||||
library and include directory paths. Link against this like above.
|
||||
library and include directory paths. Link against this like any other library.
|
||||
|
||||
@code{.cmake}
|
||||
target_link_libraries(myapp OpenGL::GL)
|
||||
@endcode
|
||||
|
||||
For a minimal example of a program and GLFW sources built with CMake, see the
|
||||
[GLFW CMake Starter](https://github.com/juliettef/GLFW-CMake-starter) on GitHub.
|
||||
|
||||
|
||||
@subsection build_link_cmake_package With CMake and installed GLFW binaries
|
||||
|
||||
@ -258,7 +264,7 @@ find_package(OpenGL REQUIRED)
|
||||
@endcode
|
||||
|
||||
If OpenGL is found, the `OpenGL::GL` target is added to your project, containing
|
||||
library and include directory paths. Link against this like above.
|
||||
library and include directory paths. Link against this like any other library.
|
||||
|
||||
@code{.cmake}
|
||||
target_link_libraries(myapp OpenGL::GL)
|
||||
|
@ -18,43 +18,42 @@ behave differently in GLFW 3.
|
||||
|
||||
@subsection quick_include Including the GLFW header
|
||||
|
||||
In the source files of your application where you use OpenGL or GLFW, you need
|
||||
to include the GLFW 3 header file.
|
||||
In the source files of your application where you use GLFW, you need to include
|
||||
its header file.
|
||||
|
||||
@code
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
This defines all the constants, types and function prototypes of the GLFW API.
|
||||
It also includes the OpenGL header from your development environment and
|
||||
defines all the constants and types necessary for it to work on your platform
|
||||
without including any platform-specific headers.
|
||||
This header provides all the constants, types and function prototypes of the
|
||||
GLFW API.
|
||||
|
||||
In other words:
|
||||
By default it also includes the OpenGL header from your development environment.
|
||||
On some platforms this header only supports older versions of OpenGL. The most
|
||||
extreme case is Windows, where it typically only supports OpenGL 1.2.
|
||||
|
||||
- Do _not_ include the OpenGL header yourself, as GLFW does this for you in
|
||||
a platform-independent way
|
||||
- Do _not_ include `windows.h` or other platform-specific headers unless
|
||||
you plan on using those APIs yourself
|
||||
- If you _do_ need to include such headers, include them _before_ the GLFW
|
||||
header and it will detect this
|
||||
|
||||
On some platforms supported by GLFW the OpenGL header and link library only
|
||||
expose older versions of OpenGL. The most extreme case is Windows, which only
|
||||
exposes OpenGL 1.2. The easiest way to work around this is to use an
|
||||
[extension loader library](@ref context_glext_auto).
|
||||
|
||||
If you are using such a library then you should include its header _before_ the
|
||||
GLFW header. This lets it replace the OpenGL header included by GLFW without
|
||||
conflicts. This example uses
|
||||
[glad2](https://github.com/Dav1dde/glad), but the same rule applies to all such
|
||||
libraries.
|
||||
Most programs will instead use an
|
||||
[extension loader library](@ref context_glext_auto) and include its header.
|
||||
This example uses files generated by [glad](https://gen.glad.sh/). The GLFW
|
||||
header can detect most such headers if they are included first and will then not
|
||||
include the one from your development environment.
|
||||
|
||||
@code
|
||||
#include <glad/gl.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
To make sure there will be no header conflicts, you can define @ref
|
||||
GLFW_INCLUDE_NONE before the GLFW header to explicitly disable inclusion of the
|
||||
development environment header. This also allows the two headers to be included
|
||||
in any order.
|
||||
|
||||
@code
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <glad/gl.h>
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection quick_init_term Initializing and terminating GLFW
|
||||
|
||||
@ -246,12 +245,16 @@ glViewport(0, 0, width, height);
|
||||
You can also set a framebuffer size callback using @ref
|
||||
glfwSetFramebufferSizeCallback and be notified when the size changes.
|
||||
|
||||
Actual rendering with OpenGL is outside the scope of this tutorial, but there
|
||||
are [many](https://open.gl/) [excellent](https://learnopengl.com/)
|
||||
[tutorial](http://openglbook.com/) [sites](http://ogldev.atspace.co.uk/) that
|
||||
teach modern OpenGL. Some of them use GLFW to create the context and window
|
||||
while others use GLUT or SDL, but remember that OpenGL itself always works the
|
||||
same.
|
||||
The details of how to render with OpenGL is outside the scope of this tutorial,
|
||||
but there are many excellent resources for learning modern OpenGL. Here are
|
||||
a few of them:
|
||||
|
||||
- [Anton's OpenGL 4 Tutorials](https://antongerdelan.net/opengl/)
|
||||
- [Learn OpenGL](https://learnopengl.com/)
|
||||
- [Open.GL](https://open.gl/)
|
||||
|
||||
These all happen to use GLFW, but OpenGL itself works the same whatever API you
|
||||
use to create the window and context.
|
||||
|
||||
|
||||
@subsection quick_timer Reading the timer
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
@tableofcontents
|
||||
|
||||
This guide is intended to fill the gaps between the [Vulkan
|
||||
documentation](https://www.khronos.org/vulkan/) and the rest of the GLFW
|
||||
This guide is intended to fill the gaps between the official [Vulkan
|
||||
resources](https://www.khronos.org/vulkan/) and the rest of the GLFW
|
||||
documentation and is not a replacement for either. It assumes some familiarity
|
||||
with Vulkan concepts like loaders, devices, queues and surfaces and leaves it to
|
||||
the Vulkan documentation to explain the details of Vulkan functions.
|
||||
@ -14,7 +14,12 @@ To develop for Vulkan you should download the [LunarG Vulkan
|
||||
SDK](https://vulkan.lunarg.com/) for your platform. Apart from headers and link
|
||||
libraries, they also provide the validation layers necessary for development.
|
||||
|
||||
For details on a specific function in this category, see the @ref vulkan. There
|
||||
The [Vulkan Tutorial](https://vulkan-tutorial.com/) has more information on how
|
||||
to use GLFW and Vulkan. The [Khronos Vulkan
|
||||
Samples](https://github.com/KhronosGroup/Vulkan-Samples) also use GLFW, although
|
||||
with a small framework in between.
|
||||
|
||||
For details on a specific Vulkan support function, see the @ref vulkan. There
|
||||
are also guides for the other areas of the GLFW API.
|
||||
|
||||
- @ref intro_guide
|
||||
|
@ -52,7 +52,7 @@ extern "C" {
|
||||
* This is the reference documentation for OpenGL and OpenGL ES context related
|
||||
* functions. For more task-oriented information, see the @ref context_guide.
|
||||
*/
|
||||
/*! @defgroup vulkan Vulkan reference
|
||||
/*! @defgroup vulkan Vulkan support reference
|
||||
* @brief Functions and types related to Vulkan.
|
||||
*
|
||||
* This is the reference documentation for Vulkan related functions and types.
|
||||
@ -193,7 +193,22 @@ extern "C" {
|
||||
|
||||
#endif /*__APPLE__*/
|
||||
|
||||
#elif !defined(GLFW_INCLUDE_NONE)
|
||||
#elif !defined(GLFW_INCLUDE_NONE) && \
|
||||
!defined(__gl_h_) && \
|
||||
!defined(__gles1_gl_h_) && \
|
||||
!defined(__gles2_gl2_h_) && \
|
||||
!defined(__gles2_gl3_h_) && \
|
||||
!defined(__gles2_gl31_h_) && \
|
||||
!defined(__gles2_gl32_h_) && \
|
||||
!defined(__gl_glcorearb_h_) && \
|
||||
!defined(__gl2_h_) /*legacy*/ && \
|
||||
!defined(__gl3_h_) /*legacy*/ && \
|
||||
!defined(__gl31_h_) /*legacy*/ && \
|
||||
!defined(__gl32_h_) /*legacy*/ && \
|
||||
!defined(__glcorearb_h_) /*legacy*/ && \
|
||||
!defined(__GL_H__) /*non-standard*/ && \
|
||||
!defined(__gltypes_h_) /*non-standard*/ && \
|
||||
!defined(__glee_h_) /*non-standard*/
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
@ -1857,6 +1872,8 @@ GLFWAPI int glfwInit(void);
|
||||
* call this function, as it is called by @ref glfwInit before it returns
|
||||
* failure.
|
||||
*
|
||||
* This function has no effect if GLFW is not initialized.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark This function may be called before @ref glfwInit.
|
||||
|
@ -92,7 +92,7 @@ typedef VkResult (APIENTRY *PFN_vkCreateMetalSurfaceEXT)(VkInstance,const VkMeta
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
|
||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->ns.view)
|
||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->ns.layer)
|
||||
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
|
||||
@ -121,6 +121,7 @@ typedef struct _GLFWwindowNS
|
||||
id layer;
|
||||
|
||||
GLFWbool maximized;
|
||||
GLFWbool occluded;
|
||||
GLFWbool retina;
|
||||
|
||||
// Cached window properties to filter out duplicate events
|
||||
|
@ -322,6 +322,14 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
||||
}
|
||||
|
||||
- (void)windowDidChangeOcclusionState:(NSNotification* )notification
|
||||
{
|
||||
if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)
|
||||
window->ns.occluded = GLFW_FALSE;
|
||||
else
|
||||
window->ns.occluded = GLFW_TRUE;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -901,6 +909,11 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
}
|
||||
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
||||
{
|
||||
// EGL implementation on macOS use CALayer* EGLNativeWindowType so we
|
||||
// need to get the layer for EGL window surface creation.
|
||||
[window->ns.view setWantsLayer:YES];
|
||||
window->ns.layer = [window->ns.view layer];
|
||||
|
||||
if (!_glfwInitEGL())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||
|
@ -588,18 +588,16 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
}
|
||||
|
||||
// Set up attributes for surface creation
|
||||
index = 0;
|
||||
|
||||
if (fbconfig->sRGB)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if (fbconfig->sRGB)
|
||||
{
|
||||
if (_glfw.egl.KHR_gl_colorspace)
|
||||
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||
}
|
||||
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
if (_glfw.egl.KHR_gl_colorspace)
|
||||
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||
}
|
||||
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
|
||||
window->context.egl.surface =
|
||||
eglCreateWindowSurface(_glfw.egl.display,
|
||||
config,
|
||||
|
@ -51,7 +51,7 @@ static void swapBuffersNSGL(_GLFWwindow* window)
|
||||
|
||||
// HACK: Simulate vsync with usleep as NSGL swap interval does not apply to
|
||||
// windows with a non-visible occlusion state
|
||||
if (!([window->ns.object occlusionState] & NSWindowOcclusionStateVisible))
|
||||
if (window->ns.occluded)
|
||||
{
|
||||
int interval = 0;
|
||||
[window->context.nsgl.object getValues:&interval
|
||||
|
@ -356,7 +356,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
{
|
||||
if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||
@ -672,11 +672,11 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
};
|
||||
|
||||
// Screams of horror are appropriate at this point
|
||||
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||
if (state < 0 || state > 8)
|
||||
state = 8;
|
||||
int stateIndex = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||
if (stateIndex < 0 || stateIndex > 8)
|
||||
stateIndex = 8;
|
||||
|
||||
_glfwInputJoystickHat(js, pi, states[state]);
|
||||
_glfwInputJoystickHat(js, pi, states[stateIndex]);
|
||||
pi++;
|
||||
break;
|
||||
}
|
||||
|
@ -208,8 +208,8 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
|
||||
if (fd < 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Creating a buffer file for %d B failed: %m",
|
||||
length);
|
||||
"Wayland: Creating a buffer file for %d B failed: %s",
|
||||
length, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -217,7 +217,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
|
||||
if (data == MAP_FAILED)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: mmap failed: %m");
|
||||
"Wayland: mmap failed: %s", strerror(errno));
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
336
src/x11_init.c
336
src/x11_init.c
@ -38,24 +38,15 @@
|
||||
#include <locale.h>
|
||||
|
||||
|
||||
// Translate an X11 key code to a GLFW key code.
|
||||
// Translate the X11 KeySyms for a key to a GLFW key code
|
||||
// NOTE: This is only used as a fallback, in case the XKB method fails
|
||||
// It is layout-dependent and will fail partially on most non-US layouts
|
||||
//
|
||||
static int translateKeyCode(int scancode)
|
||||
static int translateKeySyms(const KeySym* keysyms, int width)
|
||||
{
|
||||
int keySym;
|
||||
|
||||
// Valid key code range is [8,255], according to the Xlib manual
|
||||
if (scancode < 8 || scancode > 255)
|
||||
return GLFW_KEY_UNKNOWN;
|
||||
|
||||
if (_glfw.x11.xkb.available)
|
||||
if (width > 1)
|
||||
{
|
||||
// Try secondary keysym, for numeric keypad keys
|
||||
// Note: This way we always force "NumLock = ON", which is intentional
|
||||
// since the returned key code should correspond to a physical
|
||||
// location.
|
||||
keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 1);
|
||||
switch (keySym)
|
||||
switch (keysyms[1])
|
||||
{
|
||||
case XK_KP_0: return GLFW_KEY_KP_0;
|
||||
case XK_KP_1: return GLFW_KEY_KP_1;
|
||||
@ -73,22 +64,9 @@ static int translateKeyCode(int scancode)
|
||||
case XK_KP_Enter: return GLFW_KEY_KP_ENTER;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Now try primary keysym for function keys (non-printable keys)
|
||||
// These should not depend on the current keyboard layout
|
||||
keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int dummy;
|
||||
KeySym* keySyms;
|
||||
|
||||
keySyms = XGetKeyboardMapping(_glfw.x11.display, scancode, 1, &dummy);
|
||||
keySym = keySyms[0];
|
||||
XFree(keySyms);
|
||||
}
|
||||
|
||||
switch (keySym)
|
||||
switch (keysyms[0])
|
||||
{
|
||||
case XK_Escape: return GLFW_KEY_ESCAPE;
|
||||
case XK_Tab: return GLFW_KEY_TAB;
|
||||
@ -232,7 +210,7 @@ static int translateKeyCode(int scancode)
|
||||
//
|
||||
static void createKeyTables(void)
|
||||
{
|
||||
int scancode, key;
|
||||
int scancode, scancodeMin, scancodeMax;
|
||||
|
||||
memset(_glfw.x11.keycodes, -1, sizeof(_glfw.x11.keycodes));
|
||||
memset(_glfw.x11.scancodes, -1, sizeof(_glfw.x11.scancodes));
|
||||
@ -242,89 +220,217 @@ static void createKeyTables(void)
|
||||
// Use XKB to determine physical key locations independently of the
|
||||
// current keyboard layout
|
||||
|
||||
char name[XkbKeyNameLength + 1];
|
||||
XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);
|
||||
XkbGetNames(_glfw.x11.display, XkbKeyNamesMask, desc);
|
||||
XkbGetNames(_glfw.x11.display, XkbKeyNamesMask | XkbKeyAliasesMask, desc);
|
||||
|
||||
scancodeMin = desc->min_key_code;
|
||||
scancodeMax = desc->max_key_code;
|
||||
|
||||
const struct
|
||||
{
|
||||
int key;
|
||||
char* name;
|
||||
} keymap[] =
|
||||
{
|
||||
{ GLFW_KEY_GRAVE_ACCENT, "TLDE" },
|
||||
{ GLFW_KEY_1, "AE01" },
|
||||
{ GLFW_KEY_2, "AE02" },
|
||||
{ GLFW_KEY_3, "AE03" },
|
||||
{ GLFW_KEY_4, "AE04" },
|
||||
{ GLFW_KEY_5, "AE05" },
|
||||
{ GLFW_KEY_6, "AE06" },
|
||||
{ GLFW_KEY_7, "AE07" },
|
||||
{ GLFW_KEY_8, "AE08" },
|
||||
{ GLFW_KEY_9, "AE09" },
|
||||
{ GLFW_KEY_0, "AE10" },
|
||||
{ GLFW_KEY_MINUS, "AE11" },
|
||||
{ GLFW_KEY_EQUAL, "AE12" },
|
||||
{ GLFW_KEY_Q, "AD01" },
|
||||
{ GLFW_KEY_W, "AD02" },
|
||||
{ GLFW_KEY_E, "AD03" },
|
||||
{ GLFW_KEY_R, "AD04" },
|
||||
{ GLFW_KEY_T, "AD05" },
|
||||
{ GLFW_KEY_Y, "AD06" },
|
||||
{ GLFW_KEY_U, "AD07" },
|
||||
{ GLFW_KEY_I, "AD08" },
|
||||
{ GLFW_KEY_O, "AD09" },
|
||||
{ GLFW_KEY_P, "AD10" },
|
||||
{ GLFW_KEY_LEFT_BRACKET, "AD11" },
|
||||
{ GLFW_KEY_RIGHT_BRACKET, "AD12" },
|
||||
{ GLFW_KEY_A, "AC01" },
|
||||
{ GLFW_KEY_S, "AC02" },
|
||||
{ GLFW_KEY_D, "AC03" },
|
||||
{ GLFW_KEY_F, "AC04" },
|
||||
{ GLFW_KEY_G, "AC05" },
|
||||
{ GLFW_KEY_H, "AC06" },
|
||||
{ GLFW_KEY_J, "AC07" },
|
||||
{ GLFW_KEY_K, "AC08" },
|
||||
{ GLFW_KEY_L, "AC09" },
|
||||
{ GLFW_KEY_SEMICOLON, "AC10" },
|
||||
{ GLFW_KEY_APOSTROPHE, "AC11" },
|
||||
{ GLFW_KEY_Z, "AB01" },
|
||||
{ GLFW_KEY_X, "AB02" },
|
||||
{ GLFW_KEY_C, "AB03" },
|
||||
{ GLFW_KEY_V, "AB04" },
|
||||
{ GLFW_KEY_B, "AB05" },
|
||||
{ GLFW_KEY_N, "AB06" },
|
||||
{ GLFW_KEY_M, "AB07" },
|
||||
{ GLFW_KEY_COMMA, "AB08" },
|
||||
{ GLFW_KEY_PERIOD, "AB09" },
|
||||
{ GLFW_KEY_SLASH, "AB10" },
|
||||
{ GLFW_KEY_BACKSLASH, "BKSL" },
|
||||
{ GLFW_KEY_WORLD_1, "LSGT" },
|
||||
{ GLFW_KEY_SPACE, "SPCE" },
|
||||
{ GLFW_KEY_ESCAPE, "ESC" },
|
||||
{ GLFW_KEY_ENTER, "RTRN" },
|
||||
{ GLFW_KEY_TAB, "TAB" },
|
||||
{ GLFW_KEY_BACKSPACE, "BKSP" },
|
||||
{ GLFW_KEY_INSERT, "INS" },
|
||||
{ GLFW_KEY_DELETE, "DELE" },
|
||||
{ GLFW_KEY_RIGHT, "RGHT" },
|
||||
{ GLFW_KEY_LEFT, "LEFT" },
|
||||
{ GLFW_KEY_DOWN, "DOWN" },
|
||||
{ GLFW_KEY_UP, "UP" },
|
||||
{ GLFW_KEY_PAGE_UP, "PGUP" },
|
||||
{ GLFW_KEY_PAGE_DOWN, "PGDN" },
|
||||
{ GLFW_KEY_HOME, "HOME" },
|
||||
{ GLFW_KEY_END, "END" },
|
||||
{ GLFW_KEY_CAPS_LOCK, "CAPS" },
|
||||
{ GLFW_KEY_SCROLL_LOCK, "SCLK" },
|
||||
{ GLFW_KEY_NUM_LOCK, "NMLK" },
|
||||
{ GLFW_KEY_PRINT_SCREEN, "PRSC" },
|
||||
{ GLFW_KEY_PAUSE, "PAUS" },
|
||||
{ GLFW_KEY_F1, "FK01" },
|
||||
{ GLFW_KEY_F2, "FK02" },
|
||||
{ GLFW_KEY_F3, "FK03" },
|
||||
{ GLFW_KEY_F4, "FK04" },
|
||||
{ GLFW_KEY_F5, "FK05" },
|
||||
{ GLFW_KEY_F6, "FK06" },
|
||||
{ GLFW_KEY_F7, "FK07" },
|
||||
{ GLFW_KEY_F8, "FK08" },
|
||||
{ GLFW_KEY_F9, "FK09" },
|
||||
{ GLFW_KEY_F10, "FK10" },
|
||||
{ GLFW_KEY_F11, "FK11" },
|
||||
{ GLFW_KEY_F12, "FK12" },
|
||||
{ GLFW_KEY_F13, "FK13" },
|
||||
{ GLFW_KEY_F14, "FK14" },
|
||||
{ GLFW_KEY_F15, "FK15" },
|
||||
{ GLFW_KEY_F16, "FK16" },
|
||||
{ GLFW_KEY_F17, "FK17" },
|
||||
{ GLFW_KEY_F18, "FK18" },
|
||||
{ GLFW_KEY_F19, "FK19" },
|
||||
{ GLFW_KEY_F20, "FK20" },
|
||||
{ GLFW_KEY_F21, "FK21" },
|
||||
{ GLFW_KEY_F22, "FK22" },
|
||||
{ GLFW_KEY_F23, "FK23" },
|
||||
{ GLFW_KEY_F24, "FK24" },
|
||||
{ GLFW_KEY_F25, "FK25" },
|
||||
{ GLFW_KEY_KP_0, "KP0" },
|
||||
{ GLFW_KEY_KP_1, "KP1" },
|
||||
{ GLFW_KEY_KP_2, "KP2" },
|
||||
{ GLFW_KEY_KP_3, "KP3" },
|
||||
{ GLFW_KEY_KP_4, "KP4" },
|
||||
{ GLFW_KEY_KP_5, "KP5" },
|
||||
{ GLFW_KEY_KP_6, "KP6" },
|
||||
{ GLFW_KEY_KP_7, "KP7" },
|
||||
{ GLFW_KEY_KP_8, "KP8" },
|
||||
{ GLFW_KEY_KP_9, "KP9" },
|
||||
{ GLFW_KEY_KP_DECIMAL, "KPDL" },
|
||||
{ GLFW_KEY_KP_DIVIDE, "KPDV" },
|
||||
{ GLFW_KEY_KP_MULTIPLY, "KPMU" },
|
||||
{ GLFW_KEY_KP_SUBTRACT, "KPSU" },
|
||||
{ GLFW_KEY_KP_ADD, "KPAD" },
|
||||
{ GLFW_KEY_KP_ENTER, "KPEN" },
|
||||
{ GLFW_KEY_KP_EQUAL, "KPEQ" },
|
||||
{ GLFW_KEY_LEFT_SHIFT, "LFSH" },
|
||||
{ GLFW_KEY_LEFT_CONTROL, "LCTL" },
|
||||
{ GLFW_KEY_LEFT_ALT, "LALT" },
|
||||
{ GLFW_KEY_LEFT_SUPER, "LWIN" },
|
||||
{ GLFW_KEY_RIGHT_SHIFT, "RTSH" },
|
||||
{ GLFW_KEY_RIGHT_CONTROL, "RCTL" },
|
||||
{ GLFW_KEY_RIGHT_ALT, "RALT" },
|
||||
{ GLFW_KEY_RIGHT_ALT, "LVL3" },
|
||||
{ GLFW_KEY_RIGHT_ALT, "MDSW" },
|
||||
{ GLFW_KEY_RIGHT_SUPER, "RWIN" },
|
||||
{ GLFW_KEY_MENU, "MENU" }
|
||||
};
|
||||
|
||||
// Find the X11 key code -> GLFW key code mapping
|
||||
for (scancode = desc->min_key_code; scancode <= desc->max_key_code; scancode++)
|
||||
for (scancode = scancodeMin; scancode <= scancodeMax; scancode++)
|
||||
{
|
||||
memcpy(name, desc->names->keys[scancode].name, XkbKeyNameLength);
|
||||
name[XkbKeyNameLength] = '\0';
|
||||
int key = GLFW_KEY_UNKNOWN;
|
||||
|
||||
// Map the key name to a GLFW key code. Note: We only map printable
|
||||
// keys here, and we use the US keyboard layout. The rest of the
|
||||
// keys (function keys) are mapped using traditional KeySym
|
||||
// translations.
|
||||
if (strcmp(name, "TLDE") == 0) key = GLFW_KEY_GRAVE_ACCENT;
|
||||
else if (strcmp(name, "AE01") == 0) key = GLFW_KEY_1;
|
||||
else if (strcmp(name, "AE02") == 0) key = GLFW_KEY_2;
|
||||
else if (strcmp(name, "AE03") == 0) key = GLFW_KEY_3;
|
||||
else if (strcmp(name, "AE04") == 0) key = GLFW_KEY_4;
|
||||
else if (strcmp(name, "AE05") == 0) key = GLFW_KEY_5;
|
||||
else if (strcmp(name, "AE06") == 0) key = GLFW_KEY_6;
|
||||
else if (strcmp(name, "AE07") == 0) key = GLFW_KEY_7;
|
||||
else if (strcmp(name, "AE08") == 0) key = GLFW_KEY_8;
|
||||
else if (strcmp(name, "AE09") == 0) key = GLFW_KEY_9;
|
||||
else if (strcmp(name, "AE10") == 0) key = GLFW_KEY_0;
|
||||
else if (strcmp(name, "AE11") == 0) key = GLFW_KEY_MINUS;
|
||||
else if (strcmp(name, "AE12") == 0) key = GLFW_KEY_EQUAL;
|
||||
else if (strcmp(name, "AD01") == 0) key = GLFW_KEY_Q;
|
||||
else if (strcmp(name, "AD02") == 0) key = GLFW_KEY_W;
|
||||
else if (strcmp(name, "AD03") == 0) key = GLFW_KEY_E;
|
||||
else if (strcmp(name, "AD04") == 0) key = GLFW_KEY_R;
|
||||
else if (strcmp(name, "AD05") == 0) key = GLFW_KEY_T;
|
||||
else if (strcmp(name, "AD06") == 0) key = GLFW_KEY_Y;
|
||||
else if (strcmp(name, "AD07") == 0) key = GLFW_KEY_U;
|
||||
else if (strcmp(name, "AD08") == 0) key = GLFW_KEY_I;
|
||||
else if (strcmp(name, "AD09") == 0) key = GLFW_KEY_O;
|
||||
else if (strcmp(name, "AD10") == 0) key = GLFW_KEY_P;
|
||||
else if (strcmp(name, "AD11") == 0) key = GLFW_KEY_LEFT_BRACKET;
|
||||
else if (strcmp(name, "AD12") == 0) key = GLFW_KEY_RIGHT_BRACKET;
|
||||
else if (strcmp(name, "AC01") == 0) key = GLFW_KEY_A;
|
||||
else if (strcmp(name, "AC02") == 0) key = GLFW_KEY_S;
|
||||
else if (strcmp(name, "AC03") == 0) key = GLFW_KEY_D;
|
||||
else if (strcmp(name, "AC04") == 0) key = GLFW_KEY_F;
|
||||
else if (strcmp(name, "AC05") == 0) key = GLFW_KEY_G;
|
||||
else if (strcmp(name, "AC06") == 0) key = GLFW_KEY_H;
|
||||
else if (strcmp(name, "AC07") == 0) key = GLFW_KEY_J;
|
||||
else if (strcmp(name, "AC08") == 0) key = GLFW_KEY_K;
|
||||
else if (strcmp(name, "AC09") == 0) key = GLFW_KEY_L;
|
||||
else if (strcmp(name, "AC10") == 0) key = GLFW_KEY_SEMICOLON;
|
||||
else if (strcmp(name, "AC11") == 0) key = GLFW_KEY_APOSTROPHE;
|
||||
else if (strcmp(name, "AB01") == 0) key = GLFW_KEY_Z;
|
||||
else if (strcmp(name, "AB02") == 0) key = GLFW_KEY_X;
|
||||
else if (strcmp(name, "AB03") == 0) key = GLFW_KEY_C;
|
||||
else if (strcmp(name, "AB04") == 0) key = GLFW_KEY_V;
|
||||
else if (strcmp(name, "AB05") == 0) key = GLFW_KEY_B;
|
||||
else if (strcmp(name, "AB06") == 0) key = GLFW_KEY_N;
|
||||
else if (strcmp(name, "AB07") == 0) key = GLFW_KEY_M;
|
||||
else if (strcmp(name, "AB08") == 0) key = GLFW_KEY_COMMA;
|
||||
else if (strcmp(name, "AB09") == 0) key = GLFW_KEY_PERIOD;
|
||||
else if (strcmp(name, "AB10") == 0) key = GLFW_KEY_SLASH;
|
||||
else if (strcmp(name, "BKSL") == 0) key = GLFW_KEY_BACKSLASH;
|
||||
else if (strcmp(name, "LSGT") == 0) key = GLFW_KEY_WORLD_1;
|
||||
else key = GLFW_KEY_UNKNOWN;
|
||||
// Map the key name to a GLFW key code. Note: We use the US
|
||||
// keyboard layout. Because function keys aren't mapped correctly
|
||||
// when using traditional KeySym translations, they are mapped
|
||||
// here instead.
|
||||
for (int i = 0; i < sizeof(keymap) / sizeof(keymap[0]); i++)
|
||||
{
|
||||
if (strncmp(desc->names->keys[scancode].name,
|
||||
keymap[i].name,
|
||||
XkbKeyNameLength) == 0)
|
||||
{
|
||||
key = keymap[i].key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((scancode >= 0) && (scancode < 256))
|
||||
_glfw.x11.keycodes[scancode] = key;
|
||||
// Fall back to key aliases in case the key name did not match
|
||||
for (int i = 0; i < desc->names->num_key_aliases; i++)
|
||||
{
|
||||
if (key != GLFW_KEY_UNKNOWN)
|
||||
break;
|
||||
|
||||
if (strncmp(desc->names->key_aliases[i].real,
|
||||
desc->names->keys[scancode].name,
|
||||
XkbKeyNameLength) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < sizeof(keymap) / sizeof(keymap[0]); j++)
|
||||
{
|
||||
if (strncmp(desc->names->key_aliases[i].alias,
|
||||
keymap[j].name,
|
||||
XkbKeyNameLength) == 0)
|
||||
{
|
||||
key = keymap[j].key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_glfw.x11.keycodes[scancode] = key;
|
||||
}
|
||||
|
||||
XkbFreeNames(desc, XkbKeyNamesMask, True);
|
||||
XkbFreeKeyboard(desc, 0, True);
|
||||
}
|
||||
else
|
||||
XDisplayKeycodes(_glfw.x11.display, &scancodeMin, &scancodeMax);
|
||||
|
||||
for (scancode = 0; scancode < 256; scancode++)
|
||||
int width;
|
||||
KeySym* keysyms = XGetKeyboardMapping(_glfw.x11.display,
|
||||
scancodeMin,
|
||||
scancodeMax - scancodeMin + 1,
|
||||
&width);
|
||||
|
||||
for (scancode = scancodeMin; scancode <= scancodeMax; scancode++)
|
||||
{
|
||||
// Translate the un-translated key codes using traditional X11 KeySym
|
||||
// lookups
|
||||
if (_glfw.x11.keycodes[scancode] < 0)
|
||||
_glfw.x11.keycodes[scancode] = translateKeyCode(scancode);
|
||||
{
|
||||
const size_t base = (scancode - scancodeMin) * width;
|
||||
_glfw.x11.keycodes[scancode] = translateKeySyms(&keysyms[base], width);
|
||||
}
|
||||
|
||||
// Store the reverse translation for faster key name lookup
|
||||
if (_glfw.x11.keycodes[scancode] > 0)
|
||||
_glfw.x11.scancodes[_glfw.x11.keycodes[scancode]] = scancode;
|
||||
}
|
||||
|
||||
XFree(keysyms);
|
||||
}
|
||||
|
||||
// Check whether the IM has a usable style
|
||||
@ -352,13 +458,13 @@ static GLFWbool hasUsableInputMethodStyle(void)
|
||||
|
||||
// Check whether the specified atom is supported
|
||||
//
|
||||
static Atom getSupportedAtom(Atom* supportedAtoms,
|
||||
unsigned long atomCount,
|
||||
const char* atomName)
|
||||
static Atom getAtomIfSupported(Atom* supportedAtoms,
|
||||
unsigned long atomCount,
|
||||
const char* atomName)
|
||||
{
|
||||
const Atom atom = XInternAtom(_glfw.x11.display, atomName, False);
|
||||
|
||||
for (unsigned int i = 0; i < atomCount; i++)
|
||||
for (unsigned long i = 0; i < atomCount; i++)
|
||||
{
|
||||
if (supportedAtoms[i] == atom)
|
||||
return atom;
|
||||
@ -426,33 +532,33 @@ static void detectEWMH(void)
|
||||
// See which of the atoms we support that are supported by the WM
|
||||
|
||||
_glfw.x11.NET_WM_STATE =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE");
|
||||
_glfw.x11.NET_WM_STATE_ABOVE =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE");
|
||||
_glfw.x11.NET_WM_STATE_FULLSCREEN =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");
|
||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");
|
||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ");
|
||||
_glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION");
|
||||
_glfw.x11.NET_WM_FULLSCREEN_MONITORS =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
|
||||
_glfw.x11.NET_WM_WINDOW_TYPE =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");
|
||||
_glfw.x11.NET_WM_WINDOW_TYPE_NORMAL =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");
|
||||
_glfw.x11.NET_WORKAREA =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WORKAREA");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WORKAREA");
|
||||
_glfw.x11.NET_CURRENT_DESKTOP =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP");
|
||||
_glfw.x11.NET_ACTIVE_WINDOW =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");
|
||||
_glfw.x11.NET_FRAME_EXTENTS =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS");
|
||||
_glfw.x11.NET_REQUEST_FRAME_EXTENTS =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
|
||||
getAtomIfSupported(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
|
||||
|
||||
if (supportedAtoms)
|
||||
XFree(supportedAtoms);
|
||||
@ -666,13 +772,12 @@ static GLFWbool initExtensions(void)
|
||||
_glfw.x11.xkb.detectable = GLFW_TRUE;
|
||||
}
|
||||
|
||||
_glfw.x11.xkb.group = 0;
|
||||
XkbStateRec state;
|
||||
if (XkbGetState(_glfw.x11.display, XkbUseCoreKbd, &state) == Success)
|
||||
{
|
||||
XkbSelectEventDetails(_glfw.x11.display, XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask);
|
||||
_glfw.x11.xkb.group = (unsigned int)state.group;
|
||||
}
|
||||
|
||||
XkbSelectEventDetails(_glfw.x11.display, XkbUseCoreKbd, XkbStateNotify,
|
||||
XkbGroupStateMask, XkbGroupStateMask);
|
||||
}
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
@ -857,6 +962,9 @@ static Window createHelperWindow(void)
|
||||
//
|
||||
static int errorHandler(Display *display, XErrorEvent* event)
|
||||
{
|
||||
if (_glfw.x11.display != display)
|
||||
return 0;
|
||||
|
||||
_glfw.x11.errorCode = event->error_code;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1195,6 +1195,8 @@ static void processEvent(XEvent *event)
|
||||
{
|
||||
_glfw.x11.xkb.group = ((XkbEvent*) event)->state.group;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1557,6 +1559,8 @@ static void processEvent(XEvent *event)
|
||||
// the position into root (screen) coordinates
|
||||
if (!event->xany.send_event && window->x11.parent != _glfw.x11.root)
|
||||
{
|
||||
_glfwGrabErrorHandlerX11();
|
||||
|
||||
Window dummy;
|
||||
XTranslateCoordinates(_glfw.x11.display,
|
||||
window->x11.parent,
|
||||
@ -1564,6 +1568,10 @@ static void processEvent(XEvent *event)
|
||||
xpos, ypos,
|
||||
&xpos, &ypos,
|
||||
&dummy);
|
||||
|
||||
_glfwReleaseErrorHandlerX11();
|
||||
if (_glfw.x11.errorCode == BadWindow)
|
||||
return;
|
||||
}
|
||||
|
||||
if (xpos != window->x11.xpos || ypos != window->x11.ypos)
|
||||
@ -1971,7 +1979,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
Visual* visual;
|
||||
Visual* visual = NULL;
|
||||
int depth;
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
@ -1997,8 +2005,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxconfig->client == GLFW_NO_API ||
|
||||
ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||
if (!visual)
|
||||
{
|
||||
visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen);
|
||||
depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen);
|
||||
|
Loading…
Reference in New Issue
Block a user