Merge branch '3.3-stable' into new-cursors-on-3.3-stable

This commit is contained in:
Camilla Löwy 2020-06-02 19:47:53 +02:00
commit 830b05ecf9
16 changed files with 388 additions and 197 deletions

View File

@ -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:

View File

@ -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}")

View File

@ -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
View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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))

View File

@ -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,

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);