mirror of
https://github.com/glfw/glfw
synced 2026-09-26 16:18:21 +03:00
Merge 0ec8e46e20 into 92dcf4ce74
This commit is contained in:
commit
f210e8528f
21 changed files with 451 additions and 163 deletions
|
|
@ -313,6 +313,7 @@ video tutorials.
|
|||
- Jonas Ådahl
|
||||
- Lasse Öörni
|
||||
- Leonard König
|
||||
- Yukari Hafner (Shinmera)
|
||||
- All the unmentioned and anonymous contributors in the GLFW community, for bug
|
||||
reports, patches, feedback, testing and encouragement
|
||||
|
||||
|
|
|
|||
|
|
@ -120,8 +120,9 @@ information on what to include when reporting a bug.
|
|||
|
||||
## Changelog since 3.5
|
||||
|
||||
None.
|
||||
|
||||
- Added `glfwGetKeyNameModifiers` to obtain the native key translation including
|
||||
active modifier sets in order to accurately display key state and handle key
|
||||
chords in the presence of shift and other modifiers (#2685)
|
||||
|
||||
## Contact
|
||||
|
||||
|
|
|
|||
|
|
@ -233,14 +233,21 @@ void character_callback(GLFWwindow* window, unsigned int codepoint)
|
|||
### Key names {#input_key_name}
|
||||
|
||||
If you wish to refer to keys by name, you can query the keyboard layout
|
||||
dependent name of printable keys with @ref glfwGetKeyName.
|
||||
dependent name of printable keys with @ref glfwGetKeyName
|
||||
and @ref glfwGetKeyNameModifiers.
|
||||
|
||||
```c
|
||||
const char* key_name = glfwGetKeyName(GLFW_KEY_W, 0);
|
||||
show_tutorial_hint("Press %s to move forward", key_name);
|
||||
```
|
||||
|
||||
This function can handle both [keys and scancodes](@ref input_key). If the
|
||||
```c
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||
printf("You pressed: %s\n", glfwGetKeyNameModifiers(key, scancode, mods));
|
||||
}
|
||||
```
|
||||
|
||||
These functions can handle both [keys and scancodes](@ref input_key). If the
|
||||
specified key is `GLFW_KEY_UNKNOWN` then the scancode is used, otherwise it is
|
||||
ignored. This matches the behavior of the key callback, meaning the callback
|
||||
arguments can always be passed unmodified to this function.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,12 @@
|
|||
|
||||
## New features {#features}
|
||||
|
||||
### Key translations with modifiers {#glfwGetKeyNameModifiers}
|
||||
|
||||
GLFW now provides the @ref glfwGetKeyNameModifiers function to obtain the native
|
||||
key translation including active modifier sets in order to accurately display
|
||||
key state and handle key chords in the presence of shift and other modifiers.
|
||||
|
||||
## Caveats {#caveats}
|
||||
|
||||
## Deprecations {#deprecations}
|
||||
|
|
@ -15,6 +21,8 @@
|
|||
|
||||
### New functions {#new_functions}
|
||||
|
||||
- @ref glfwGetKeyNameModifiers
|
||||
|
||||
### New types {#new_types}
|
||||
|
||||
### New constants {#new_constants}
|
||||
|
|
|
|||
|
|
@ -560,6 +560,11 @@ extern "C" {
|
|||
* GLFW_LOCK_KEY_MODS input mode is set.
|
||||
*/
|
||||
#define GLFW_MOD_NUM_LOCK 0x0020
|
||||
/*! @brief If this bit is set the Alt-Gr or right alt key were held down.
|
||||
*
|
||||
* If this bit is set the Alt-Gr or right alt key were held down.
|
||||
*/
|
||||
#define GLFW_MOD_ALT_GR 0x0040
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
|
@ -4838,6 +4843,82 @@ GLFWAPI int glfwRawMouseMotionSupported(void);
|
|||
*
|
||||
* @remark The contents of the returned string may change when a keyboard
|
||||
* layout change event is received.
|
||||
*
|
||||
* @remark This function is the same as calling @ref glfwGetKeyNameModifiers
|
||||
* with the `modifiers` set to `0`.
|
||||
*
|
||||
* @pointer_lifetime The returned string is allocated and freed by GLFW. You
|
||||
* should not free it yourself. It is valid until the library is terminated.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref input_key_name
|
||||
* @sa @ref glfwGetKeyNameModifiers
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
GLFWAPI const char* glfwGetKeyName(int key, int scancode);
|
||||
|
||||
/*! @brief Returns the layout-specific name of the specified printable key
|
||||
* modifier combination.
|
||||
*
|
||||
* This function returns the name of the specified printable key, when pressed
|
||||
* together with the given set of modifiers, encoded as UTF-8. This is
|
||||
* intended for displaying key bindings and chords to the user.
|
||||
*
|
||||
* __Do not use this function__ for [text input](@ref input_char). You will
|
||||
* break text input for many languages even if it happens to work for yours.
|
||||
* This applies even though the modifiers are respected. Keyboard input
|
||||
* methods often apply transformations that go beyond a single key combination.
|
||||
*
|
||||
* If the key is `GLFW_KEY_UNKNOWN`, the scancode is used to identify the key,
|
||||
* otherwise the scancode is ignored. If you specify a non-printable key, or
|
||||
* `GLFW_KEY_UNKNOWN` and a scancode that maps to a non-printable key, this
|
||||
* function returns `NULL` but does not emit an error.
|
||||
*
|
||||
* This behavior allows you to always pass in the arguments in the
|
||||
* [key callback](@ref input_key) without modification.
|
||||
*
|
||||
* The printable keys are:
|
||||
* - `GLFW_KEY_APOSTROPHE`
|
||||
* - `GLFW_KEY_COMMA`
|
||||
* - `GLFW_KEY_MINUS`
|
||||
* - `GLFW_KEY_PERIOD`
|
||||
* - `GLFW_KEY_SLASH`
|
||||
* - `GLFW_KEY_SEMICOLON`
|
||||
* - `GLFW_KEY_EQUAL`
|
||||
* - `GLFW_KEY_LEFT_BRACKET`
|
||||
* - `GLFW_KEY_RIGHT_BRACKET`
|
||||
* - `GLFW_KEY_BACKSLASH`
|
||||
* - `GLFW_KEY_WORLD_1`
|
||||
* - `GLFW_KEY_WORLD_2`
|
||||
* - `GLFW_KEY_0` to `GLFW_KEY_9`
|
||||
* - `GLFW_KEY_A` to `GLFW_KEY_Z`
|
||||
* - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9`
|
||||
* - `GLFW_KEY_KP_DECIMAL`
|
||||
* - `GLFW_KEY_KP_DIVIDE`
|
||||
* - `GLFW_KEY_KP_MULTIPLY`
|
||||
* - `GLFW_KEY_KP_SUBTRACT`
|
||||
* - `GLFW_KEY_KP_ADD`
|
||||
* - `GLFW_KEY_KP_EQUAL`
|
||||
*
|
||||
* Names for printable keys depend on keyboard layout, while names for
|
||||
* non-printable keys are the same across layouts but depend on the application
|
||||
* language and should be localized along with other user interface text.
|
||||
*
|
||||
* @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`.
|
||||
* @param[in] scancode The scancode of the key to query.
|
||||
* @param[in] modifiers The modifier set of the key combination to query.
|
||||
* @return The UTF-8 encoded, layout-specific name of the key combination, or
|
||||
* `NULL`.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_INVALID_VALUE, @ref GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark The contents of the returned string may change when a keyboard
|
||||
* layout change event is received.
|
||||
*
|
||||
* @pointer_lifetime The returned string is allocated and freed by GLFW. You
|
||||
* should not free it yourself. It is valid until the library is terminated.
|
||||
|
|
@ -4846,11 +4927,11 @@ GLFWAPI int glfwRawMouseMotionSupported(void);
|
|||
*
|
||||
* @sa @ref input_key_name
|
||||
*
|
||||
* @since Added in version 3.2.
|
||||
* @since Added in version 3.5.
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
GLFWAPI const char* glfwGetKeyName(int key, int scancode);
|
||||
GLFWAPI const char* glfwGetKeyNameModifiers(int key, int scancode, int modifiers);
|
||||
|
||||
/*! @brief Returns the platform-specific scancode of the specified key.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ void _glfwPostEmptyEventCocoa(void);
|
|||
void _glfwGetCursorPosCocoa(_GLFWwindow* window, double* xpos, double* ypos);
|
||||
void _glfwSetCursorPosCocoa(_GLFWwindow* window, double xpos, double ypos);
|
||||
void _glfwSetCursorModeCocoa(_GLFWwindow* window, int mode);
|
||||
const char* _glfwGetScancodeNameCocoa(int scancode);
|
||||
const char* _glfwGetScancodeNameCocoa(int scancode, int modifiers);
|
||||
int _glfwGetKeyScancodeCocoa(int key);
|
||||
GLFWbool _glfwCreateCursorCocoa(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
GLFWbool _glfwCreateStandardCursorCocoa(_GLFWcursor* cursor, int shape);
|
||||
|
|
|
|||
|
|
@ -159,6 +159,26 @@ static int translateFlags(NSUInteger flags)
|
|||
return mods;
|
||||
}
|
||||
|
||||
// Translates GLFW key modifiers into macOS ones
|
||||
//
|
||||
static int translateFlagsInverse(int mods)
|
||||
{
|
||||
NSUInteger flags = 0;
|
||||
|
||||
if (mods & GLFW_MOD_SHIFT)
|
||||
flags |= NSEventModifierFlagShift;
|
||||
if (mods & GLFW_MOD_CONTROL)
|
||||
flags |= NSEventModifierFlagControl;
|
||||
if (mods & GLFW_MOD_ALT)
|
||||
flags |= NSEventModifierFlagOption;
|
||||
if (mods & GLFW_MOD_SUPER)
|
||||
flags |= NSEventModifierFlagCommand;
|
||||
if (mods & GLFW_MOD_CAPS_LOCK)
|
||||
flags |= NSEventModifierFlagCapsLock;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
// Translates a macOS keycode to a GLFW keycode
|
||||
//
|
||||
static int translateKey(unsigned int key)
|
||||
|
|
@ -1682,7 +1702,7 @@ void _glfwSetCursorModeCocoa(_GLFWwindow* window, int mode)
|
|||
} // autoreleasepool
|
||||
}
|
||||
|
||||
const char* _glfwGetScancodeNameCocoa(int scancode)
|
||||
const char* _glfwGetScancodeNameCocoa(int scancode, int modifiers)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
|
|
@ -1703,7 +1723,7 @@ const char* _glfwGetScancodeNameCocoa(int scancode)
|
|||
if (UCKeyTranslate([(NSData*) _glfw.ns.unicodeData bytes],
|
||||
scancode,
|
||||
kUCKeyActionDisplay,
|
||||
0,
|
||||
translateFlagsInverse(modifiers),
|
||||
LMGetKbdType(),
|
||||
kUCKeyTranslateNoDeadKeysBit,
|
||||
&deadKeyState,
|
||||
|
|
|
|||
12
src/input.c
12
src/input.c
|
|
@ -47,7 +47,8 @@
|
|||
GLFW_MOD_ALT | \
|
||||
GLFW_MOD_SUPER | \
|
||||
GLFW_MOD_CAPS_LOCK | \
|
||||
GLFW_MOD_NUM_LOCK)
|
||||
GLFW_MOD_NUM_LOCK | \
|
||||
GLFW_MOD_ALT_GR)
|
||||
|
||||
// Initializes the platform joystick API if it has not been already
|
||||
//
|
||||
|
|
@ -701,7 +702,7 @@ GLFWAPI int glfwRawMouseMotionSupported(void)
|
|||
return _glfw.platform.rawMouseMotionSupported();
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetKeyName(int key, int scancode)
|
||||
GLFWAPI const char* glfwGetKeyNameModifiers(int key, int scancode, int modifiers)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
|
|
@ -723,7 +724,12 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode)
|
|||
scancode = _glfw.platform.getKeyScancode(key);
|
||||
}
|
||||
|
||||
return _glfw.platform.getScancodeName(scancode);
|
||||
return _glfw.platform.getScancodeName(scancode, modifiers);
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetKeyName(int key, int scancode)
|
||||
{
|
||||
return glfwGetKeyNameModifiers(key, scancode, 0);
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetKeyScancode(int key)
|
||||
|
|
|
|||
|
|
@ -696,7 +696,7 @@ struct _GLFWplatform
|
|||
GLFWbool (*createStandardCursor)(_GLFWcursor*,int);
|
||||
void (*destroyCursor)(_GLFWcursor*);
|
||||
void (*setCursor)(_GLFWwindow*,_GLFWcursor*);
|
||||
const char* (*getScancodeName)(int);
|
||||
const char* (*getScancodeName)(int, int);
|
||||
int (*getKeyScancode)(int);
|
||||
void (*setClipboardString)(const char*);
|
||||
const char* (*getClipboardString)(void);
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ void _glfwDestroyCursorNull(_GLFWcursor* cursor);
|
|||
void _glfwSetCursorNull(_GLFWwindow* window, _GLFWcursor* cursor);
|
||||
void _glfwSetClipboardStringNull(const char* string);
|
||||
const char* _glfwGetClipboardStringNull(void);
|
||||
const char* _glfwGetScancodeNameNull(int scancode);
|
||||
const char* _glfwGetScancodeNameNull(int scancode, int modifiers);
|
||||
int _glfwGetKeyScancodeNull(int key);
|
||||
|
||||
EGLenum _glfwGetEGLPlatformNull(EGLint** attribs);
|
||||
|
|
|
|||
|
|
@ -569,7 +569,140 @@ EGLNativeWindowType _glfwGetEGLNativeWindowNull(_GLFWwindow* window)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const char* _glfwGetScancodeNameNull(int scancode)
|
||||
// Store the string representations of the scan codes.
|
||||
// This relies on the index in the array corresponding to the
|
||||
// GLFW_NULL_SC_* constant. For each element, it defines the different
|
||||
// names depending on that key's shift level, which can be either 0
|
||||
// (no modifiers), 1 (shift held), 2 (ctrl+alt/altgr held), or 3 (both
|
||||
// shift and altgr held).
|
||||
//
|
||||
// The used key names are from the en-US ANSI keyboard layout.
|
||||
const char* keyNames[GLFW_NULL_SC_LAST+1][4] = {
|
||||
// 0 = neutral, 1 = shift, 2 = altgr, 3 = shift+altgr
|
||||
{/**/ NULL, NULL, NULL, NULL},
|
||||
{/*SPACE*/ " ", " ", " ", " "},
|
||||
{/*APOSTROPHE*/ "'", "\"", NULL, NULL},
|
||||
{/*COMMA*/ ",", "<", NULL, NULL},
|
||||
{/*MINUS*/ "-", "_", NULL, NULL},
|
||||
{/*PERIOD*/ ".", ">", NULL, NULL},
|
||||
{/*SLASH*/ "/", "?", NULL, NULL},
|
||||
{/*0*/ "0", ")", NULL, NULL},
|
||||
{/*1*/ "1", "!", NULL, NULL},
|
||||
{/*2*/ "2", "@", NULL, NULL},
|
||||
{/*3*/ "3", "#", NULL, NULL},
|
||||
{/*4*/ "4", "$", NULL, NULL},
|
||||
{/*5*/ "5", "%", NULL, NULL},
|
||||
{/*6*/ "6", "^", NULL, NULL},
|
||||
{/*7*/ "7", "&", NULL, NULL},
|
||||
{/*8*/ "8", "*", NULL, NULL},
|
||||
{/*9*/ "9", "(", NULL, NULL},
|
||||
{/*SEMICOLON*/ ";", ":", NULL, NULL},
|
||||
{/*EQUAL*/ "=", "+", NULL, NULL},
|
||||
{/*LEFT_BRACKET*/ "[", "{", NULL, NULL},
|
||||
{/*BACKSLASH*/ "\\", "|", NULL, NULL},
|
||||
{/*RIGHT_BRACKET*/ "]", "}", NULL, NULL},
|
||||
{/*GRAVE_ACCENT*/ NULL, NULL, NULL, NULL},
|
||||
{/*WORLD_1*/ "\\", NULL, NULL, NULL},
|
||||
{/*WORLD_2*/ "\\", NULL, NULL, NULL},
|
||||
{/*ESCAPE*/ NULL, NULL, NULL, NULL},
|
||||
{/*ENTER*/ NULL, NULL, NULL, NULL},
|
||||
{/*TAB*/ NULL, NULL, NULL, NULL},
|
||||
{/*BACKSPACE*/ NULL, NULL, NULL, NULL},
|
||||
{/*INSERT*/ NULL, NULL, NULL, NULL},
|
||||
{/*DELETE*/ NULL, NULL, NULL, NULL},
|
||||
{/*RIGHT*/ NULL, NULL, NULL, NULL},
|
||||
{/*LEFT*/ NULL, NULL, NULL, NULL},
|
||||
{/*DOWN*/ NULL, NULL, NULL, NULL},
|
||||
{/*UP*/ NULL, NULL, NULL, NULL},
|
||||
{/*PAGE_UP*/ NULL, NULL, NULL, NULL},
|
||||
{/*PAGE_DOWN*/ NULL, NULL, NULL, NULL},
|
||||
{/*HOME*/ NULL, NULL, NULL, NULL},
|
||||
{/*END*/ NULL, NULL, NULL, NULL},
|
||||
{/*CAPS_LOCK*/ NULL, NULL, NULL, NULL},
|
||||
{/*SCROLL_LOCK*/ NULL, NULL, NULL, NULL},
|
||||
{/*NUM_LOCK*/ NULL, NULL, NULL, NULL},
|
||||
{/*PRINT_SCREEN*/ NULL, NULL, NULL, NULL},
|
||||
{/*PAUSE*/ NULL, NULL, NULL, NULL},
|
||||
{/*A*/ "a", "A", NULL, NULL},
|
||||
{/*B*/ "b", "B", NULL, NULL},
|
||||
{/*C*/ "c", "C", NULL, NULL},
|
||||
{/*D*/ "d", "D", NULL, NULL},
|
||||
{/*E*/ "e", "E", NULL, NULL},
|
||||
{/*F*/ "f", "F", NULL, NULL},
|
||||
{/*G*/ "g", "G", NULL, NULL},
|
||||
{/*H*/ "h", "H", NULL, NULL},
|
||||
{/*I*/ "i", "I", NULL, NULL},
|
||||
{/*J*/ "j", "J", NULL, NULL},
|
||||
{/*K*/ "k", "K", NULL, NULL},
|
||||
{/*L*/ "l", "L", NULL, NULL},
|
||||
{/*M*/ "m", "M", NULL, NULL},
|
||||
{/*N*/ "n", "N", NULL, NULL},
|
||||
{/*O*/ "o", "O", NULL, NULL},
|
||||
{/*P*/ "p", "P", NULL, NULL},
|
||||
{/*Q*/ "q", "Q", NULL, NULL},
|
||||
{/*R*/ "r", "R", NULL, NULL},
|
||||
{/*S*/ "s", "S", NULL, NULL},
|
||||
{/*T*/ "t", "T", NULL, NULL},
|
||||
{/*U*/ "u", "U", NULL, NULL},
|
||||
{/*V*/ "v", "V", NULL, NULL},
|
||||
{/*W*/ "w", "W", NULL, NULL},
|
||||
{/*X*/ "x", "X", NULL, NULL},
|
||||
{/*Y*/ "y", "Y", NULL, NULL},
|
||||
{/*Z*/ "z", "Z", NULL, NULL},
|
||||
{/*F1*/ NULL, NULL, NULL, NULL},
|
||||
{/*F2*/ NULL, NULL, NULL, NULL},
|
||||
{/*F3*/ NULL, NULL, NULL, NULL},
|
||||
{/*F4*/ NULL, NULL, NULL, NULL},
|
||||
{/*F5*/ NULL, NULL, NULL, NULL},
|
||||
{/*F6*/ NULL, NULL, NULL, NULL},
|
||||
{/*F7*/ NULL, NULL, NULL, NULL},
|
||||
{/*F8*/ NULL, NULL, NULL, NULL},
|
||||
{/*F9*/ NULL, NULL, NULL, NULL},
|
||||
{/*F10*/ NULL, NULL, NULL, NULL},
|
||||
{/*F11*/ NULL, NULL, NULL, NULL},
|
||||
{/*F12*/ NULL, NULL, NULL, NULL},
|
||||
{/*F13*/ NULL, NULL, NULL, NULL},
|
||||
{/*F14*/ NULL, NULL, NULL, NULL},
|
||||
{/*F15*/ NULL, NULL, NULL, NULL},
|
||||
{/*F16*/ NULL, NULL, NULL, NULL},
|
||||
{/*F17*/ NULL, NULL, NULL, NULL},
|
||||
{/*F18*/ NULL, NULL, NULL, NULL},
|
||||
{/*F19*/ NULL, NULL, NULL, NULL},
|
||||
{/*F20*/ NULL, NULL, NULL, NULL},
|
||||
{/*F21*/ NULL, NULL, NULL, NULL},
|
||||
{/*F22*/ NULL, NULL, NULL, NULL},
|
||||
{/*F23*/ NULL, NULL, NULL, NULL},
|
||||
{/*F24*/ NULL, NULL, NULL, NULL},
|
||||
{/*F25*/ NULL, NULL, NULL, NULL},
|
||||
{/*KP_0*/ "0", NULL, NULL, NULL},
|
||||
{/*KP_1*/ "1", NULL, NULL, NULL},
|
||||
{/*KP_2*/ "2", NULL, NULL, NULL},
|
||||
{/*KP_3*/ "3", NULL, NULL, NULL},
|
||||
{/*KP_4*/ "4", NULL, NULL, NULL},
|
||||
{/*KP_5*/ "5", NULL, NULL, NULL},
|
||||
{/*KP_6*/ "6", NULL, NULL, NULL},
|
||||
{/*KP_7*/ "7", NULL, NULL, NULL},
|
||||
{/*KP_8*/ "8", NULL, NULL, NULL},
|
||||
{/*KP_9*/ "9", NULL, NULL, NULL},
|
||||
{/*KP_DECIMAL*/ ".", NULL, NULL, NULL},
|
||||
{/*KP_DIVIDE*/ "/", NULL, NULL, NULL},
|
||||
{/*KP_MULTIPLY*/ "*", NULL, NULL, NULL},
|
||||
{/*KP_SUBTRACT*/ "-", NULL, NULL, NULL},
|
||||
{/*KP_ADD*/ "+", NULL, NULL, NULL},
|
||||
{/*KP_ENTER*/ NULL, NULL, NULL, NULL},
|
||||
{/*KP_EQUAL*/ "=", NULL, NULL, NULL},
|
||||
{/*LEFT_SHIFT*/ NULL, NULL, NULL, NULL},
|
||||
{/*LEFT_CONTROL*/ NULL, NULL, NULL, NULL},
|
||||
{/*LEFT_ALT*/ NULL, NULL, NULL, NULL},
|
||||
{/*LEFT_SUPER*/ NULL, NULL, NULL, NULL},
|
||||
{/*RIGHT_SHIFT*/ NULL, NULL, NULL, NULL},
|
||||
{/*RIGHT_CONTROL*/ NULL, NULL, NULL, NULL},
|
||||
{/*RIGHT_ALT*/ NULL, NULL, NULL, NULL},
|
||||
{/*RIGHT_SUPER*/ NULL, NULL, NULL, NULL},
|
||||
{/*MENUP*/ NULL, NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
const char* _glfwGetScancodeNameNull(int scancode, int modifiers)
|
||||
{
|
||||
if (scancode < GLFW_NULL_SC_FIRST || scancode > GLFW_NULL_SC_LAST)
|
||||
{
|
||||
|
|
@ -577,123 +710,12 @@ const char* _glfwGetScancodeNameNull(int scancode)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
switch (scancode)
|
||||
{
|
||||
case GLFW_NULL_SC_APOSTROPHE:
|
||||
return "'";
|
||||
case GLFW_NULL_SC_COMMA:
|
||||
return ",";
|
||||
case GLFW_NULL_SC_MINUS:
|
||||
case GLFW_NULL_SC_KP_SUBTRACT:
|
||||
return "-";
|
||||
case GLFW_NULL_SC_PERIOD:
|
||||
case GLFW_NULL_SC_KP_DECIMAL:
|
||||
return ".";
|
||||
case GLFW_NULL_SC_SLASH:
|
||||
case GLFW_NULL_SC_KP_DIVIDE:
|
||||
return "/";
|
||||
case GLFW_NULL_SC_SEMICOLON:
|
||||
return ";";
|
||||
case GLFW_NULL_SC_EQUAL:
|
||||
case GLFW_NULL_SC_KP_EQUAL:
|
||||
return "=";
|
||||
case GLFW_NULL_SC_LEFT_BRACKET:
|
||||
return "[";
|
||||
case GLFW_NULL_SC_RIGHT_BRACKET:
|
||||
return "]";
|
||||
case GLFW_NULL_SC_KP_MULTIPLY:
|
||||
return "*";
|
||||
case GLFW_NULL_SC_KP_ADD:
|
||||
return "+";
|
||||
case GLFW_NULL_SC_BACKSLASH:
|
||||
case GLFW_NULL_SC_WORLD_1:
|
||||
case GLFW_NULL_SC_WORLD_2:
|
||||
return "\\";
|
||||
case GLFW_NULL_SC_0:
|
||||
case GLFW_NULL_SC_KP_0:
|
||||
return "0";
|
||||
case GLFW_NULL_SC_1:
|
||||
case GLFW_NULL_SC_KP_1:
|
||||
return "1";
|
||||
case GLFW_NULL_SC_2:
|
||||
case GLFW_NULL_SC_KP_2:
|
||||
return "2";
|
||||
case GLFW_NULL_SC_3:
|
||||
case GLFW_NULL_SC_KP_3:
|
||||
return "3";
|
||||
case GLFW_NULL_SC_4:
|
||||
case GLFW_NULL_SC_KP_4:
|
||||
return "4";
|
||||
case GLFW_NULL_SC_5:
|
||||
case GLFW_NULL_SC_KP_5:
|
||||
return "5";
|
||||
case GLFW_NULL_SC_6:
|
||||
case GLFW_NULL_SC_KP_6:
|
||||
return "6";
|
||||
case GLFW_NULL_SC_7:
|
||||
case GLFW_NULL_SC_KP_7:
|
||||
return "7";
|
||||
case GLFW_NULL_SC_8:
|
||||
case GLFW_NULL_SC_KP_8:
|
||||
return "8";
|
||||
case GLFW_NULL_SC_9:
|
||||
case GLFW_NULL_SC_KP_9:
|
||||
return "9";
|
||||
case GLFW_NULL_SC_A:
|
||||
return "a";
|
||||
case GLFW_NULL_SC_B:
|
||||
return "b";
|
||||
case GLFW_NULL_SC_C:
|
||||
return "c";
|
||||
case GLFW_NULL_SC_D:
|
||||
return "d";
|
||||
case GLFW_NULL_SC_E:
|
||||
return "e";
|
||||
case GLFW_NULL_SC_F:
|
||||
return "f";
|
||||
case GLFW_NULL_SC_G:
|
||||
return "g";
|
||||
case GLFW_NULL_SC_H:
|
||||
return "h";
|
||||
case GLFW_NULL_SC_I:
|
||||
return "i";
|
||||
case GLFW_NULL_SC_J:
|
||||
return "j";
|
||||
case GLFW_NULL_SC_K:
|
||||
return "k";
|
||||
case GLFW_NULL_SC_L:
|
||||
return "l";
|
||||
case GLFW_NULL_SC_M:
|
||||
return "m";
|
||||
case GLFW_NULL_SC_N:
|
||||
return "n";
|
||||
case GLFW_NULL_SC_O:
|
||||
return "o";
|
||||
case GLFW_NULL_SC_P:
|
||||
return "p";
|
||||
case GLFW_NULL_SC_Q:
|
||||
return "q";
|
||||
case GLFW_NULL_SC_R:
|
||||
return "r";
|
||||
case GLFW_NULL_SC_S:
|
||||
return "s";
|
||||
case GLFW_NULL_SC_T:
|
||||
return "t";
|
||||
case GLFW_NULL_SC_U:
|
||||
return "u";
|
||||
case GLFW_NULL_SC_V:
|
||||
return "v";
|
||||
case GLFW_NULL_SC_W:
|
||||
return "w";
|
||||
case GLFW_NULL_SC_X:
|
||||
return "x";
|
||||
case GLFW_NULL_SC_Y:
|
||||
return "y";
|
||||
case GLFW_NULL_SC_Z:
|
||||
return "z";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
int level = 0;
|
||||
if (modifiers & GLFW_MOD_SHIFT)
|
||||
level |= 1;
|
||||
if ((modifiers & GLFW_MOD_CONTROL) && (modifiers & GLFW_MOD_ALT))
|
||||
level |= 2;
|
||||
return keyNames[scancode][level];
|
||||
}
|
||||
|
||||
int _glfwGetKeyScancodeNull(int key)
|
||||
|
|
|
|||
|
|
@ -488,7 +488,7 @@ void _glfwInputErrorWin32(int error, const char* description)
|
|||
//
|
||||
void _glfwUpdateKeyNamesWin32(void)
|
||||
{
|
||||
int key;
|
||||
int key, level;
|
||||
BYTE state[256] = {0};
|
||||
|
||||
memset(_glfw.win32.keynames, 0, sizeof(_glfw.win32.keynames));
|
||||
|
|
@ -518,26 +518,36 @@ void _glfwUpdateKeyNamesWin32(void)
|
|||
else
|
||||
vk = MapVirtualKeyW(scancode, MAPVK_VSC_TO_VK);
|
||||
|
||||
length = ToUnicode(vk, scancode, state,
|
||||
chars, sizeof(chars) / sizeof(WCHAR),
|
||||
0);
|
||||
|
||||
if (length == -1)
|
||||
for (level = 0; level < 8; ++level)
|
||||
{
|
||||
// This is a dead key, so we need a second simulated key press
|
||||
// to make it output its own character (usually a diacritic)
|
||||
int mods = _GLFWmodelevels[level];
|
||||
state[(int) VK_SHIFT] = (mods & GLFW_MOD_SHIFT)? 0xff : 0x00;
|
||||
state[(int) VK_CONTROL] = (mods & GLFW_MOD_CONTROL)? 0xff : 0x00;
|
||||
state[(int) VK_MENU] = (mods & GLFW_MOD_ALT)? 0xff : 0x00;
|
||||
state[(int) VK_CAPITAL] = (mods & GLFW_MOD_CAPS_LOCK)? 0xff : 0x00;
|
||||
state[(int) VK_RMENU] = (mods & GLFW_MOD_ALT_GR)? 0xff : 0x00;
|
||||
|
||||
length = ToUnicode(vk, scancode, state,
|
||||
chars, sizeof(chars) / sizeof(WCHAR),
|
||||
0);
|
||||
|
||||
if (length == -1)
|
||||
{
|
||||
// This is a dead key, so we need a second simulated key press
|
||||
// to make it output its own character (usually a diacritic)
|
||||
length = ToUnicode(vk, scancode, state,
|
||||
chars, sizeof(chars) / sizeof(WCHAR),
|
||||
0);
|
||||
}
|
||||
|
||||
if (length < 1)
|
||||
continue;
|
||||
|
||||
WideCharToMultiByte(CP_UTF8, 0, chars, 1,
|
||||
_glfw.win32.keynames[key][level],
|
||||
sizeof(_glfw.win32.keynames[key][level]),
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
if (length < 1)
|
||||
continue;
|
||||
|
||||
WideCharToMultiByte(CP_UTF8, 0, chars, 1,
|
||||
_glfw.win32.keynames[key],
|
||||
sizeof(_glfw.win32.keynames[key]),
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -377,6 +377,17 @@ typedef struct _GLFWwindowWin32
|
|||
WCHAR highSurrogate;
|
||||
} _GLFWwindowWin32;
|
||||
|
||||
const static int _GLFWmodelevels[] = {
|
||||
0,
|
||||
GLFW_MOD_SHIFT,
|
||||
GLFW_MOD_CAPS_LOCK,
|
||||
GLFW_MOD_SHIFT | GLFW_MOD_CAPS_LOCK,
|
||||
GLFW_MOD_CONTROL | GLFW_MOD_ALT,
|
||||
GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SHIFT,
|
||||
GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_CAPS_LOCK,
|
||||
GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SHIFT | GLFW_MOD_CAPS_LOCK
|
||||
};
|
||||
|
||||
// Win32-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryWin32
|
||||
|
|
@ -390,7 +401,7 @@ typedef struct _GLFWlibraryWin32
|
|||
char* clipboardString;
|
||||
short int keycodes[512];
|
||||
short int scancodes[GLFW_KEY_LAST + 1];
|
||||
char keynames[GLFW_KEY_LAST + 1][5];
|
||||
char keynames[GLFW_KEY_LAST + 1][8][5];
|
||||
// Where to place the cursor when re-enabled
|
||||
double restoreCursorPosX, restoreCursorPosY;
|
||||
// The window whose disabled cursor mode is active
|
||||
|
|
@ -527,7 +538,7 @@ void _glfwPostEmptyEventWin32(void);
|
|||
void _glfwGetCursorPosWin32(_GLFWwindow* window, double* xpos, double* ypos);
|
||||
void _glfwSetCursorPosWin32(_GLFWwindow* window, double xpos, double ypos);
|
||||
void _glfwSetCursorModeWin32(_GLFWwindow* window, int mode);
|
||||
const char* _glfwGetScancodeNameWin32(int scancode);
|
||||
const char* _glfwGetScancodeNameWin32(int scancode, int modifiers);
|
||||
int _glfwGetKeyScancodeWin32(int key);
|
||||
GLFWbool _glfwCreateCursorWin32(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
GLFWbool _glfwCreateStandardCursorWin32(_GLFWcursor* cursor, int shape);
|
||||
|
|
|
|||
|
|
@ -419,6 +419,8 @@ static int getKeyMods(void)
|
|||
mods |= GLFW_MOD_CAPS_LOCK;
|
||||
if (GetKeyState(VK_NUMLOCK) & 1)
|
||||
mods |= GLFW_MOD_NUM_LOCK;
|
||||
if (GetKeyState(VK_RMENU) & 1)
|
||||
mods |= GLFW_MOD_ALT_GR;
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
|
@ -2255,7 +2257,7 @@ void _glfwSetCursorModeWin32(_GLFWwindow* window, int mode)
|
|||
updateCursorImage(window);
|
||||
}
|
||||
|
||||
const char* _glfwGetScancodeNameWin32(int scancode)
|
||||
const char* _glfwGetScancodeNameWin32(int scancode, int modifiers)
|
||||
{
|
||||
if (scancode < 0 || scancode > (KF_EXTENDED | 0xff))
|
||||
{
|
||||
|
|
@ -2267,7 +2269,20 @@ const char* _glfwGetScancodeNameWin32(int scancode)
|
|||
if (key == GLFW_KEY_UNKNOWN)
|
||||
return NULL;
|
||||
|
||||
return _glfw.win32.keynames[key];
|
||||
// Determine corresponding modifier level
|
||||
int level = 0;
|
||||
if (modifiers)
|
||||
{
|
||||
for (level = 0; level < 8; ++level)
|
||||
{
|
||||
if ((_GLFWmodelevels[level] & modifiers) == modifiers)
|
||||
break;
|
||||
}
|
||||
if (level == 8)
|
||||
level = 0;
|
||||
}
|
||||
|
||||
return _glfw.win32.keynames[key][level];
|
||||
}
|
||||
|
||||
int _glfwGetKeyScancodeWin32(int key)
|
||||
|
|
|
|||
|
|
@ -691,7 +691,13 @@ int _glfwInitWayland(void)
|
|||
_glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_unref");
|
||||
_glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
|
||||
_glfw.wl.xkb.keymap_mod_get_mask2 = (PFN_xkb_keymap_mod_get_mask2)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_mask2");
|
||||
_glfw.wl.xkb.keymap_key_get_mods_for_level = (PFN_xkb_keymap_key_get_mods_for_level)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_get_mods_for_level");
|
||||
_glfw.wl.xkb.keymap_num_levels_for_key = (PFN_xkb_keymap_num_levels_for_key)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_num_levels_for_key");
|
||||
_glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
|
||||
_glfw.wl.xkb.keymap_key_get_syms_by_level = (PFN_xkb_keymap_key_get_syms_by_level)
|
||||
|
|
|
|||
|
|
@ -185,6 +185,9 @@ typedef void (* PFN_xkb_context_unref)(struct xkb_context*);
|
|||
typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
|
||||
typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
|
||||
typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
|
||||
typedef xkb_mod_mask_t (* PFN_xkb_keymap_mod_get_mask2)(struct xkb_keymap*, const xkb_mod_index_t);
|
||||
typedef xkb_level_index_t (* PFN_xkb_keymap_num_levels_for_key)(struct xkb_keymap*, const xkb_keycode_t, const xkb_layout_index_t);
|
||||
typedef size_t (* PFN_xkb_keymap_key_get_mods_for_level)(struct xkb_keymap*, const xkb_keycode_t, const xkb_layout_index_t, const xkb_level_index_t, xkb_mod_mask_t *, const size_t);
|
||||
typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
|
||||
typedef int (* PFN_xkb_keymap_key_get_syms_by_level)(struct xkb_keymap*,xkb_keycode_t,xkb_layout_index_t,xkb_level_index_t,const xkb_keysym_t**);
|
||||
typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
|
||||
|
|
@ -200,6 +203,9 @@ typedef int (* PFN_xkb_keysym_to_utf8)(xkb_keysym_t, char*, size_t);
|
|||
#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
|
||||
#define xkb_keymap_unref _glfw.wl.xkb.keymap_unref
|
||||
#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index
|
||||
#define xkb_keymap_mod_get_mask2 _glfw.wl.xkb.keymap_mod_get_mask2
|
||||
#define xkb_keymap_num_levels_for_key _glfw.wl.xkb.keymap_num_levels_for_key
|
||||
#define xkb_keymap_key_get_mods_for_level _glfw.wl.xkb.keymap_key_get_mods_for_level
|
||||
#define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats
|
||||
#define xkb_keymap_key_get_syms_by_level _glfw.wl.xkb.keymap_key_get_syms_by_level
|
||||
#define xkb_state_new _glfw.wl.xkb.state_new
|
||||
|
|
@ -517,6 +523,7 @@ typedef struct _GLFWlibraryWayland
|
|||
xkb_mod_index_t superIndex;
|
||||
xkb_mod_index_t capsLockIndex;
|
||||
xkb_mod_index_t numLockIndex;
|
||||
xkb_mod_index_t altGrIndex;
|
||||
unsigned int modifiers;
|
||||
|
||||
PFN_xkb_context_new context_new;
|
||||
|
|
@ -524,8 +531,11 @@ typedef struct _GLFWlibraryWayland
|
|||
PFN_xkb_keymap_new_from_string keymap_new_from_string;
|
||||
PFN_xkb_keymap_unref keymap_unref;
|
||||
PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
|
||||
PFN_xkb_keymap_mod_get_mask2 keymap_mod_get_mask2;
|
||||
PFN_xkb_keymap_key_repeats keymap_key_repeats;
|
||||
PFN_xkb_keymap_key_get_syms_by_level keymap_key_get_syms_by_level;
|
||||
PFN_xkb_keymap_num_levels_for_key keymap_num_levels_for_key;
|
||||
PFN_xkb_keymap_key_get_mods_for_level keymap_key_get_mods_for_level;
|
||||
PFN_xkb_state_new state_new;
|
||||
PFN_xkb_state_unref state_unref;
|
||||
PFN_xkb_state_key_get_syms state_key_get_syms;
|
||||
|
|
@ -700,7 +710,7 @@ void _glfwPostEmptyEventWayland(void);
|
|||
void _glfwGetCursorPosWayland(_GLFWwindow* window, double* xpos, double* ypos);
|
||||
void _glfwSetCursorPosWayland(_GLFWwindow* window, double xpos, double ypos);
|
||||
void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode);
|
||||
const char* _glfwGetScancodeNameWayland(int scancode);
|
||||
const char* _glfwGetScancodeNameWayland(int scancode, int modifiers);
|
||||
int _glfwGetKeyScancodeWayland(int key);
|
||||
GLFWbool _glfwCreateCursorWayland(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
GLFWbool _glfwCreateStandardCursorWayland(_GLFWcursor* cursor, int shape);
|
||||
|
|
|
|||
|
|
@ -1909,6 +1909,7 @@ static void keyboardHandleKeymap(void* userData,
|
|||
_glfw.wl.xkb.superIndex = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
|
||||
_glfw.wl.xkb.capsLockIndex = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock");
|
||||
_glfw.wl.xkb.numLockIndex = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2");
|
||||
_glfw.wl.xkb.altGrIndex = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod3");
|
||||
}
|
||||
|
||||
static void keyboardHandleEnter(void* userData,
|
||||
|
|
@ -2033,7 +2034,8 @@ static void keyboardHandleModifiers(void* userData,
|
|||
{ _glfw.wl.xkb.shiftIndex, GLFW_MOD_SHIFT },
|
||||
{ _glfw.wl.xkb.superIndex, GLFW_MOD_SUPER },
|
||||
{ _glfw.wl.xkb.capsLockIndex, GLFW_MOD_CAPS_LOCK },
|
||||
{ _glfw.wl.xkb.numLockIndex, GLFW_MOD_NUM_LOCK }
|
||||
{ _glfw.wl.xkb.numLockIndex, GLFW_MOD_NUM_LOCK },
|
||||
{ _glfw.wl.xkb.altGrIndex, GLFW_MOD_ALT_GR }
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(modifiers) / sizeof(modifiers[0]); i++)
|
||||
|
|
@ -2978,7 +2980,31 @@ void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode)
|
|||
_glfwSetCursorWayland(window, window->cursor);
|
||||
}
|
||||
|
||||
const char* _glfwGetScancodeNameWayland(int scancode)
|
||||
// Translates an xkb modifier state mask
|
||||
//
|
||||
static xkb_mod_mask_t translateStateInverse(int mods)
|
||||
{
|
||||
xkb_mod_mask_t mask = 0;
|
||||
|
||||
if (mods & GLFW_MOD_SHIFT)
|
||||
mask |= xkb_keymap_mod_get_mask2(_glfw.wl.xkb.keymap, _glfw.wl.xkb.shiftIndex);
|
||||
if (mods & GLFW_MOD_CONTROL)
|
||||
mask |= xkb_keymap_mod_get_mask2(_glfw.wl.xkb.keymap, _glfw.wl.xkb.controlIndex);
|
||||
if (mods & GLFW_MOD_ALT)
|
||||
mask |= xkb_keymap_mod_get_mask2(_glfw.wl.xkb.keymap, _glfw.wl.xkb.altIndex);
|
||||
if (mods & GLFW_MOD_SUPER)
|
||||
mask |= xkb_keymap_mod_get_mask2(_glfw.wl.xkb.keymap, _glfw.wl.xkb.superIndex);
|
||||
if (mods & GLFW_MOD_CAPS_LOCK)
|
||||
mask |= xkb_keymap_mod_get_mask2(_glfw.wl.xkb.keymap, _glfw.wl.xkb.capsLockIndex);
|
||||
if (mods & GLFW_MOD_NUM_LOCK)
|
||||
mask |= xkb_keymap_mod_get_mask2(_glfw.wl.xkb.keymap, _glfw.wl.xkb.numLockIndex);
|
||||
if (mods & GLFW_MOD_ALT_GR)
|
||||
mask |= xkb_keymap_mod_get_mask2(_glfw.wl.xkb.keymap, _glfw.wl.xkb.altGrIndex);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
const char* _glfwGetScancodeNameWayland(int scancode, int modifiers)
|
||||
{
|
||||
if (scancode < 0 || scancode > 255)
|
||||
{
|
||||
|
|
@ -3002,11 +3028,44 @@ const char* _glfwGetScancodeNameWayland(int scancode)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
xkb_level_index_t found_level = 0;
|
||||
if (0 < modifiers)
|
||||
{
|
||||
// Figure out the corresponding level set for the modifier set
|
||||
// that the user requested. This involves a relatively annoying
|
||||
// loop of trying things out. Could cache this information if
|
||||
// lookup speed is of concern.
|
||||
xkb_mod_mask_t mask = translateStateInverse(modifiers);
|
||||
const int num_levels = xkb_keymap_num_levels_for_key(_glfw.wl.xkb.keymap,
|
||||
keycode,
|
||||
layout);
|
||||
xkb_level_index_t level;
|
||||
for (level = 0; level < num_levels && found_level == 0; ++level)
|
||||
{
|
||||
size_t num_masks;
|
||||
xkb_mod_mask_t masks[128];
|
||||
num_masks = xkb_keymap_key_get_mods_for_level(_glfw.wl.xkb.keymap,
|
||||
keycode,
|
||||
layout,
|
||||
level,
|
||||
masks,
|
||||
128);
|
||||
for (int i=0; i < num_masks; ++i)
|
||||
{
|
||||
if ((masks[i] & mask) == mask)
|
||||
{
|
||||
found_level = level;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const xkb_keysym_t* keysyms = NULL;
|
||||
xkb_keymap_key_get_syms_by_level(_glfw.wl.xkb.keymap,
|
||||
keycode,
|
||||
layout,
|
||||
0,
|
||||
found_level,
|
||||
&keysyms);
|
||||
if (keysyms == NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1498,6 +1498,8 @@ int _glfwInitX11(void)
|
|||
_glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbGetState");
|
||||
_glfw.x11.xkb.KeycodeToKeysym = (PFN_XkbKeycodeToKeysym)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbKeycodeToKeysym");
|
||||
_glfw.x11.xkb.LookupKeysym = (PFN_XkbLookupKeysym)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbLookupKeySym");
|
||||
_glfw.x11.xkb.QueryExtension = (PFN_XkbQueryExtension)
|
||||
_glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbQueryExtension");
|
||||
_glfw.x11.xkb.SelectEventDetails = (PFN_XkbSelectEventDetails)
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ typedef XkbDescPtr (* PFN_XkbGetMap)(Display*,unsigned int,unsigned int);
|
|||
typedef Status (* PFN_XkbGetNames)(Display*,unsigned int,XkbDescPtr);
|
||||
typedef Status (* PFN_XkbGetState)(Display*,unsigned int,XkbStatePtr);
|
||||
typedef KeySym (* PFN_XkbKeycodeToKeysym)(Display*,KeyCode,int,int);
|
||||
typedef Bool (* PFN_XkbLookupKeysym)(Display*,KeyCode,unsigned int,unsigned int*,KeySym*);
|
||||
typedef Bool (* PFN_XkbQueryExtension)(Display*,int*,int*,int*,int*,int*);
|
||||
typedef Bool (* PFN_XkbSelectEventDetails)(Display*,unsigned int,unsigned int,unsigned long,unsigned long);
|
||||
typedef Bool (* PFN_XkbSetDetectableAutoRepeat)(Display*,Bool,Bool*);
|
||||
|
|
@ -288,6 +289,7 @@ typedef void (* PFN_Xutf8SetWMProperties)(Display*,Window,const char*,const char
|
|||
#define XkbGetNames _glfw.x11.xkb.GetNames
|
||||
#define XkbGetState _glfw.x11.xkb.GetState
|
||||
#define XkbKeycodeToKeysym _glfw.x11.xkb.KeycodeToKeysym
|
||||
#define XkbLookupKeysym _glfw.x11.xkb.LookupKeysym
|
||||
#define XkbQueryExtension _glfw.x11.xkb.QueryExtension
|
||||
#define XkbSelectEventDetails _glfw.x11.xkb.SelectEventDetails
|
||||
#define XkbSetDetectableAutoRepeat _glfw.x11.xkb.SetDetectableAutoRepeat
|
||||
|
|
@ -782,6 +784,7 @@ typedef struct _GLFWlibraryX11
|
|||
PFN_XkbGetNames GetNames;
|
||||
PFN_XkbGetState GetState;
|
||||
PFN_XkbKeycodeToKeysym KeycodeToKeysym;
|
||||
PFN_XkbLookupKeysym LookupKeysym;
|
||||
PFN_XkbQueryExtension QueryExtension;
|
||||
PFN_XkbSelectEventDetails SelectEventDetails;
|
||||
PFN_XkbSetDetectableAutoRepeat SetDetectableAutoRepeat;
|
||||
|
|
@ -945,7 +948,7 @@ void _glfwPostEmptyEventX11(void);
|
|||
void _glfwGetCursorPosX11(_GLFWwindow* window, double* xpos, double* ypos);
|
||||
void _glfwSetCursorPosX11(_GLFWwindow* window, double xpos, double ypos);
|
||||
void _glfwSetCursorModeX11(_GLFWwindow* window, int mode);
|
||||
const char* _glfwGetScancodeNameX11(int scancode);
|
||||
const char* _glfwGetScancodeNameX11(int scancode, int modifiers);
|
||||
int _glfwGetKeyScancodeX11(int key);
|
||||
GLFWbool _glfwCreateCursorX11(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
GLFWbool _glfwCreateStandardCursorX11(_GLFWcursor* cursor, int shape);
|
||||
|
|
|
|||
|
|
@ -229,10 +229,36 @@ static int translateState(int state)
|
|||
mods |= GLFW_MOD_CAPS_LOCK;
|
||||
if (state & Mod2Mask)
|
||||
mods |= GLFW_MOD_NUM_LOCK;
|
||||
if (state & Mod3Mask)
|
||||
mods |= GLFW_MOD_ALT_GR;
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
// Translates an X event modifier state mask
|
||||
//
|
||||
static int translateStateInverse(int mods)
|
||||
{
|
||||
int state = 0;
|
||||
|
||||
if (mods & GLFW_MOD_SHIFT)
|
||||
state |= ShiftMask;
|
||||
if (mods & GLFW_MOD_CONTROL)
|
||||
state |= ControlMask;
|
||||
if (mods & GLFW_MOD_ALT)
|
||||
state |= Mod1Mask;
|
||||
if (mods & GLFW_MOD_SUPER)
|
||||
state |= Mod4Mask;
|
||||
if (mods & GLFW_MOD_CAPS_LOCK)
|
||||
state |= LockMask;
|
||||
if (mods & GLFW_MOD_NUM_LOCK)
|
||||
state |= Mod2Mask;
|
||||
if (mods & GLFW_MOD_ALT_GR)
|
||||
state |= Mod3Mask;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// Translates an X11 key code to a GLFW key token
|
||||
//
|
||||
static int translateKey(int scancode)
|
||||
|
|
@ -2924,7 +2950,7 @@ void _glfwSetCursorModeX11(_GLFWwindow* window, int mode)
|
|||
XFlush(_glfw.x11.display);
|
||||
}
|
||||
|
||||
const char* _glfwGetScancodeNameX11(int scancode)
|
||||
const char* _glfwGetScancodeNameX11(int scancode, int modifiers)
|
||||
{
|
||||
if (!_glfw.x11.xkb.available)
|
||||
return NULL;
|
||||
|
|
@ -2939,9 +2965,9 @@ const char* _glfwGetScancodeNameX11(int scancode)
|
|||
if (key == GLFW_KEY_UNKNOWN)
|
||||
return NULL;
|
||||
|
||||
const KeySym keysym = XkbKeycodeToKeysym(_glfw.x11.display,
|
||||
scancode, _glfw.x11.xkb.group, 0);
|
||||
if (keysym == NoSymbol)
|
||||
unsigned int state = translateStateInverse(modifiers);
|
||||
KeySym keysym;
|
||||
if (XkbLookupKeysym(_glfw.x11.display, scancode, state, &state, &keysym) != True)
|
||||
return NULL;
|
||||
|
||||
const uint32_t codepoint = _glfwKeySym2UnicodeX11(keysym);
|
||||
|
|
|
|||
|
|
@ -411,7 +411,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
|
|||
}
|
||||
else
|
||||
{
|
||||
const char* name = glfwGetKeyName(key, scancode);
|
||||
const char* name = glfwGetKeyNameModifiers(key, scancode, mods);
|
||||
if (name)
|
||||
{
|
||||
printf("%08x to %i at %0.3f: Key 0x%04x (%s) Scancode 0x%04x Name %s (with%s) was %s\n",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue