Extract key event data to struct

This commit is contained in:
Benoit de Chezelles 2019-09-24 04:27:49 +02:00
parent fb1c318a09
commit 53275c9137
14 changed files with 215 additions and 124 deletions

View File

@ -185,6 +185,12 @@ def generate_wrappers(glfw_header):
p = src.find('*/', p)
preamble = src[p + 2:first]
header = '''\
//
// THIS FILE IS GENERATED BY glfw.py
//
// SAVE YOURSELF SOME TIME, DO NOT MANUALLY EDIT
//
#pragma once
#include <stddef.h>
#include <stdint.h>

35
glfw/glfw3.h vendored
View File

@ -1177,6 +1177,29 @@ typedef struct GLFWwindow GLFWwindow;
*/
typedef struct GLFWcursor GLFWcursor;
typedef struct GLFWkeyevent
{
// The [keyboard key](@ref keys) that was pressed or released.
int key;
// The system-specific scancode of the key.
int scancode;
// The event action. Either `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`.
int action;
// Bit field describing which [modifier keys](@ref mods) were held down.
int mods;
// UTF-8 encoded text generated by this key event or empty string.
const char *text;
// Used for Input Method events. Zero for normal key events.
// A value of 1 means the pre-edit text for the input event has been changed.
// A value of 2 means the text should be committed.
int ime_state;
} GLFWkeyevent;
/*! @brief The function signature for error callbacks.
*
* This is the function signature for error callback functions.
@ -1462,15 +1485,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int);
* the "s" key will generate text "o" and GLFW_KEY_O.
*
* @param[in] window The window that received the event.
* @param[in] key The [keyboard key](@ref keys) that was pressed or released.
* @param[in] scancode The system-specific scancode of the key.
* @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`.
* @param[in] mods Bit field describing which [modifier keys](@ref mods) were
* held down.
* @param[in] text UTF-8 encoded text generated by this key event or empty string.
* @param[in] status Used for Input Method events. Zero for normal key events.
* A value of 1 means the pre-edit text for the input event has been changed.
* A value of 2 means the text should be committed.
* @param[in] ev TODO: blablabla
*
* @note On X11/Wayland if a modifier other than the modifiers GLFW reports
* (ctrl/shift/alt/super) is used, GLFW will report the shifted key rather
@ -1484,7 +1499,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int);
*
* @ingroup input
*/
typedef void (* GLFWkeyboardfun)(GLFWwindow*, int, int, int, int, const char*, int);
typedef void (* GLFWkeyboardfun)(GLFWwindow*, GLFWkeyevent*);
/*! @brief The function signature for file drop callbacks.
*

29
glfw/ibus_glfw.c vendored
View File

@ -107,10 +107,14 @@ get_ibus_text_from_message(DBusMessage *msg) {
}
static inline void
send_text(const char *text, int state) {
send_text(const char *text, int ime_state) {
_GLFWwindow *w = _glfwFocusedWindow();
if (w && w->callbacks.keyboard) {
w->callbacks.keyboard((GLFWwindow*) w, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0, text, state);
GLFWkeyevent fake_ev;
_glfwInitializeKeyEvent(&fake_ev, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0);
fake_ev.text = text;
fake_ev.ime_state = ime_state;
w->callbacks.keyboard((GLFWwindow*) w, &fake_ev);
}
}
@ -393,31 +397,36 @@ ibus_key_state(unsigned int glfw_modifiers, int action) {
void
key_event_processed(DBusMessage *msg, const char* errmsg, void *data) {
uint32_t handled = 0;
KeyEvent *ev = (KeyEvent*)data;
bool is_release = ev->action == GLFW_RELEASE;
_GLFWIBUSKeyEvent *ev = (_GLFWIBUSKeyEvent*)data;
// Restore key's text from the text embedded in the structure.
ev->glfw_ev.text = ev->__embedded_text;
bool is_release = ev->glfw_ev.action == GLFW_RELEASE;
bool failed = false;
if (errmsg) {
_glfwInputError(GLFW_PLATFORM_ERROR, "IBUS: Failed to process key with error: %s", errmsg);
failed = true;
} else {
glfw_dbus_get_args(msg, "Failed to get IBUS handled key from reply", DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID);
debug("IBUS processed scancode: 0x%x release: %d handled: %u\n", ev->keycode, is_release, handled);
debug("IBUS processed scancode: 0x%x release: %d handled: %u\n", ev->glfw_ev.scancode, is_release, handled);
}
glfw_xkb_key_from_ime(ev, handled ? true : false, failed);
free(ev);
}
bool
ibus_process_key(const KeyEvent *ev_, _GLFWIBUSData *ibus) {
ibus_process_key(const _GLFWIBUSKeyEvent *ev_, _GLFWIBUSData *ibus) {
if (!check_connection(ibus)) return false;
KeyEvent *ev = malloc(sizeof(KeyEvent));
_GLFWIBUSKeyEvent *ev = malloc(sizeof(_GLFWIBUSKeyEvent));
if (!ev) return false;
memcpy(ev, ev_, sizeof(KeyEvent));
uint32_t state = ibus_key_state(ev->glfw_modifiers, ev->action);
memcpy(ev, ev_, sizeof(_GLFWIBUSKeyEvent));
// Put the key's text in a field IN the structure, for proper serialization.
memcpy(ev->__embedded_text, ev->glfw_ev.text, sizeof(ev->__embedded_text));
ev->glfw_ev.text = NULL;
uint32_t state = ibus_key_state(ev->glfw_ev.mods, ev->glfw_ev.action);
if (!glfw_dbus_call_method_with_reply(
ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "ProcessKeyEvent",
3000, key_event_processed, ev,
DBUS_TYPE_UINT32, &ev->ibus_sym, DBUS_TYPE_UINT32, &ev->ibus_keycode, DBUS_TYPE_UINT32,
DBUS_TYPE_UINT32, &ev->ibus_keysym, DBUS_TYPE_UINT32, &ev->ibus_keycode, DBUS_TYPE_UINT32,
&state, DBUS_TYPE_INVALID)) {
free(ev);
return false;

15
glfw/ibus_glfw.h vendored
View File

@ -27,6 +27,7 @@
#pragma once
#include "internal.h"
#include "dbus_glfw.h"
#include <xkbcommon/xkbcommon.h>
@ -38,18 +39,16 @@ typedef struct {
} _GLFWIBUSData;
typedef struct {
xkb_keycode_t keycode, ibus_keycode;
xkb_keysym_t keysym, ibus_sym;
unsigned int glfw_modifiers;
int action;
xkb_keycode_t ibus_keycode;
xkb_keysym_t ibus_keysym;
GLFWid window_id;
int glfw_keycode;
char text[64];
} KeyEvent;
GLFWkeyevent glfw_ev;
char __embedded_text[64];
} _GLFWIBUSKeyEvent;
void glfw_connect_to_ibus(_GLFWIBUSData *ibus);
void glfw_ibus_terminate(_GLFWIBUSData *ibus);
void glfw_ibus_set_focused(_GLFWIBUSData *ibus, bool focused);
void glfw_ibus_dispatch(_GLFWIBUSData *ibus);
bool ibus_process_key(const KeyEvent *ev_, _GLFWIBUSData *ibus);
bool ibus_process_key(const _GLFWIBUSKeyEvent *ev_, _GLFWIBUSData *ibus);
void glfw_ibus_set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h);

31
glfw/input.c vendored
View File

@ -256,33 +256,44 @@ static bool parseMapping(_GLFWmapping* mapping, const char* string)
////// GLFW event API //////
//////////////////////////////////////////////////////////////////////////
void _glfwInitializeKeyEvent(GLFWkeyevent *ev, int key, int scancode, int action, int mods)
{
ev->key = key;
ev->scancode = scancode;
ev->action = action;
ev->mods = mods;
ev->text = "";
ev->ime_state = 0;
}
// Notifies shared code of a physical key event
//
void _glfwInputKeyboard(_GLFWwindow* window, int key, int scancode, int action, int mods, const char* text, int state)
void _glfwInputKeyboard(_GLFWwindow* window, GLFWkeyevent* ev)
{
if (key >= 0 && key <= GLFW_KEY_LAST)
if (ev->key >= 0 && ev->key <= GLFW_KEY_LAST)
{
bool repeated = false;
if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE)
if (ev->action == GLFW_RELEASE && window->keys[ev->key] == GLFW_RELEASE)
return;
if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)
if (ev->action == GLFW_PRESS && window->keys[ev->key] == GLFW_PRESS)
repeated = true;
if (action == GLFW_RELEASE && window->stickyKeys)
window->keys[key] = _GLFW_STICK;
if (ev->action == GLFW_RELEASE && window->stickyKeys)
window->keys[ev->key] = _GLFW_STICK;
else
window->keys[key] = (char) action;
window->keys[ev->key] = (char) ev->action;
if (repeated)
action = GLFW_REPEAT;
ev->action = GLFW_REPEAT;
}
// FIXME: will need to update ev->virtual_mods here too?
if (window->callbacks.keyboard) {
if (!window->lockKeyMods) mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
window->callbacks.keyboard((GLFWwindow*) window, key, scancode, action, mods, text, state);
if (!window->lockKeyMods) ev->mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
window->callbacks.keyboard((GLFWwindow*) window, ev);
}
}

3
glfw/internal.h vendored
View File

@ -756,7 +756,8 @@ void _glfwInputWindowDamage(_GLFWwindow* window);
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
void _glfwInputKeyboard(_GLFWwindow* window, int key, int scancode, int action, int mods, const char* text, int state);
void _glfwInitializeKeyEvent(GLFWkeyevent *ev, int key, int scancode, int action, int mods);
void _glfwInputKeyboard(_GLFWwindow *window, GLFWkeyevent *ev);
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int flags);
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);

4
glfw/window.c vendored
View File

@ -57,7 +57,9 @@ void _glfwInputWindowFocus(_GLFWwindow* window, bool focused)
if (window->keys[key] == GLFW_PRESS)
{
const int scancode = _glfwPlatformGetKeyScancode(key);
_glfwInputKeyboard(window, key, scancode, GLFW_RELEASE, 0, "", 0);
GLFWkeyevent ev;
_glfwInitializeKeyEvent(&ev, key, scancode, GLFW_RELEASE, 0);
_glfwInputKeyboard(window, &ev);
}
}

100
glfw/xkb_glfw.c vendored
View File

@ -445,16 +445,14 @@ glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t scancode) {
}
static KeyEvent key_event = {0};
static inline xkb_keysym_t
compose_symbol(struct xkb_compose_state *composeState, xkb_keysym_t sym, int *compose_completed) {
compose_symbol(struct xkb_compose_state *composeState, xkb_keysym_t sym, int *compose_completed, char *key_text, int n) {
*compose_completed = 0;
if (sym == XKB_KEY_NoSymbol || !composeState) return sym;
if (xkb_compose_state_feed(composeState, sym) != XKB_COMPOSE_FEED_ACCEPTED) return sym;
switch (xkb_compose_state_get_status(composeState)) {
case XKB_COMPOSE_COMPOSED:
xkb_compose_state_get_utf8(composeState, key_event.text, sizeof(key_event.text));
xkb_compose_state_get_utf8(composeState, key_text, n);
*compose_completed = 1;
return xkb_compose_state_get_one_sym(composeState);
case XKB_COMPOSE_COMPOSING:
@ -534,11 +532,14 @@ glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, i
}
void
glfw_xkb_key_from_ime(KeyEvent *ev, bool handled_by_ime, bool failed) {
glfw_xkb_key_from_ime(_GLFWIBUSKeyEvent *ev, bool handled_by_ime, bool failed) {
_GLFWwindow *window = _glfwWindowForId(ev->window_id);
if (failed && window && window->callbacks.keyboard) {
// notify application to remove any existing pre-edit text
window->callbacks.keyboard((GLFWwindow*) window, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0, "", 1);
GLFWkeyevent fake_ev;
_glfwInitializeKeyEvent(&fake_ev, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0);
fake_ev.ime_state = 1;
window->callbacks.keyboard((GLFWwindow*) window, &fake_ev);
}
static xkb_keycode_t last_handled_press_keycode = 0;
// We filter out release events that correspond to the last press event
@ -547,53 +548,58 @@ glfw_xkb_key_from_ime(KeyEvent *ev, bool handled_by_ime, bool failed) {
// you'd need to implement a ring buffer to store pending key presses.
xkb_keycode_t prev_handled_press = last_handled_press_keycode;
last_handled_press_keycode = 0;
bool is_release = ev->action == GLFW_RELEASE;
debug("From IBUS: scancode: 0x%x name: %s is_release: %d\n", ev->keycode, glfw_xkb_keysym_name(ev->keysym), is_release);
if (window && !handled_by_ime && !(is_release && ev->keycode == prev_handled_press)) {
bool is_release = ev->glfw_ev.action == GLFW_RELEASE;
debug("From IBUS: scancode: 0x%x name: %s is_release: %d\n", ev->glfw_ev.scancode, glfw_xkb_keysym_name(ev->glfw_ev.key), is_release);
if (window && !handled_by_ime && !(is_release && ev->glfw_ev.scancode == (int) prev_handled_press)) {
debug("↳ to application: glfw_keycode: 0x%x (%s) keysym: 0x%x (%s) action: %s %s text: %s\n",
ev->glfw_keycode, _glfwGetKeyName(ev->glfw_keycode), ev->keysym, glfw_xkb_keysym_name(ev->keysym),
(ev->action == GLFW_RELEASE ? "RELEASE" : (ev->action == GLFW_PRESS ? "PRESS" : "REPEAT")),
format_mods(ev->glfw_modifiers), ev->text
ev->glfw_ev.scancode, _glfwGetKeyName(ev->glfw_ev.scancode), ev->glfw_ev.key, glfw_xkb_keysym_name(ev->glfw_ev.key),
(ev->glfw_ev.action == GLFW_RELEASE ? "RELEASE" : (ev->glfw_ev.action == GLFW_PRESS ? "PRESS" : "REPEAT")),
format_mods(ev->glfw_ev.mods), ev->glfw_ev.text
);
_glfwInputKeyboard(window, ev->glfw_keycode, ev->keysym, ev->action, ev->glfw_modifiers, ev->text, 0);
ev->glfw_ev.ime_state = 0;
_glfwInputKeyboard(window, &ev->glfw_ev);
} else debug("↳ discarded\n");
if (!is_release && handled_by_ime) last_handled_press_keycode = ev->keycode;
if (!is_release && handled_by_ime) last_handled_press_keycode = ev->glfw_ev.scancode;
}
static char key_text[64] = {0};
void
glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t scancode, int action) {
const xkb_keysym_t *syms, *clean_syms, *default_syms;
xkb_keysym_t glfw_sym;
xkb_keycode_t code_for_sym = scancode;
key_event.ibus_keycode = scancode;
xkb_keysym_t xkb_sym;
xkb_keycode_t code_for_sym = scancode, ibus_keycode = scancode;
GLFWkeyevent glfw_ev;
_glfwInitializeKeyEvent(&glfw_ev, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0); // init with default values
#ifdef _GLFW_WAYLAND
code_for_sym += 8;
#else
key_event.ibus_keycode -= 8;
ibus_keycode -= 8;
#endif
debug("%s scancode: 0x%x ", action == GLFW_RELEASE ? "Release" : "Press", scancode);
XKBStateGroup *sg = &xkb->states;
int num_syms = xkb_state_key_get_syms(sg->state, code_for_sym, &syms);
int num_clean_syms = xkb_state_key_get_syms(sg->clean_state, code_for_sym, &clean_syms);
key_event.text[0] = 0;
key_text[0] = 0;
// According to the documentation of xkb_compose_state_feed it does not
// support multi-sym events, so we ignore them
if (num_syms != 1 || num_clean_syms != 1) {
debug("num_syms: %d num_clean_syms: %d ignoring event\n", num_syms, num_clean_syms);
return;
}
glfw_sym = clean_syms[0];
xkb_sym = clean_syms[0];
debug("clean_sym: %s ", glfw_xkb_keysym_name(clean_syms[0]));
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
const char *text_type = "composed_text";
int compose_completed;
glfw_sym = compose_symbol(sg->composeState, syms[0], &compose_completed);
if (glfw_sym == XKB_KEY_NoSymbol && !compose_completed) {
xkb_sym = compose_symbol(sg->composeState, syms[0], &compose_completed, key_text, sizeof(key_text));
if (xkb_sym == XKB_KEY_NoSymbol && !compose_completed) {
debug("compose not complete, ignoring.\n");
return;
}
debug("composed_sym: %s ", glfw_xkb_keysym_name(glfw_sym));
if (glfw_sym == syms[0]) { // composed sym is the same as non-composed sym
debug("composed_sym: %s ", glfw_xkb_keysym_name(xkb_sym));
if (xkb_sym == syms[0]) { // composed sym is the same as non-composed sym
// Only use the clean_sym if no mods other than the mods we report
// are active (for example if ISO_Shift_Level_* mods are active
// they are not reported by GLFW so the key should be the shifted
@ -601,37 +607,49 @@ glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t
xkb_mod_mask_t consumed_unknown_mods = xkb_state_key_get_consumed_mods(sg->state, code_for_sym) & sg->activeUnknownModifiers;
if (sg->activeUnknownModifiers) debug("%s", format_xkb_mods(xkb, "active_unknown_mods", sg->activeUnknownModifiers));
if (consumed_unknown_mods) { debug("%s", format_xkb_mods(xkb, "consumed_unknown_mods", consumed_unknown_mods)); }
else glfw_sym = clean_syms[0];
else xkb_sym = clean_syms[0];
// xkb returns text even if alt and/or super are pressed
if ( ((GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER) & sg->modifiers) == 0) xkb_state_key_get_utf8(sg->state, code_for_sym, key_event.text, sizeof(key_event.text));
if ( ((GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER) & sg->modifiers) == 0) {
xkb_state_key_get_utf8(sg->state, code_for_sym, key_text, sizeof(key_text));
}
text_type = "text";
}
if ((1 <= key_event.text[0] && key_event.text[0] <= 31) || key_event.text[0] == 127) key_event.text[0] = 0; // don't send text for ascii control codes
if (key_event.text[0]) { debug("%s: %s ", text_type, key_event.text); }
if ((1 <= key_text[0] && key_text[0] <= 31) || key_text[0] == 127) {
key_text[0] = 0; // don't send text for ascii control codes
}
if (key_text[0]) { debug("%s: %s ", text_type, key_text); }
}
int glfw_keycode = glfw_key_for_sym(glfw_sym);
int glfw_sym = glfw_key_for_sym(xkb_sym);
bool is_fallback = false;
if (glfw_keycode == GLFW_KEY_UNKNOWN && !key_event.text[0]) {
if (glfw_sym == GLFW_KEY_UNKNOWN && !key_text[0]) {
int num_default_syms = xkb_state_key_get_syms(sg->default_state, code_for_sym, &default_syms);
if (num_default_syms > 0) {
glfw_sym = default_syms[0];
glfw_keycode = glfw_key_for_sym(glfw_sym);
xkb_sym = default_syms[0];
glfw_sym = glfw_key_for_sym(xkb_sym);
is_fallback = true;
}
}
debug(
"%s%s: %d (%s) xkb_key: %d (%s)\n",
format_mods(sg->modifiers),
is_fallback ? "glfw_fallback_key" : "glfw_key", glfw_keycode, _glfwGetKeyName(glfw_keycode),
glfw_sym, glfw_xkb_keysym_name(glfw_sym)
is_fallback ? "glfw_fallback_key" : "glfw_key", glfw_sym, _glfwGetKeyName(glfw_sym),
xkb_sym, glfw_xkb_keysym_name(xkb_sym)
);
key_event.action = action; key_event.glfw_modifiers = sg->modifiers;
key_event.keycode = scancode; key_event.keysym = glfw_sym;
key_event.window_id = window->id; key_event.glfw_keycode = glfw_keycode;
key_event.ibus_sym = syms[0];
if (ibus_process_key(&key_event, &xkb->ibus)) {
debug("↳ to IBUS: keycode: 0x%x keysym: 0x%x (%s) %s\n", key_event.ibus_keycode, key_event.ibus_sym, glfw_xkb_keysym_name(key_event.ibus_sym), format_mods(key_event.glfw_modifiers));
glfw_ev.action = action;
glfw_ev.scancode = xkb_sym;
glfw_ev.key = glfw_sym;
glfw_ev.mods = sg->modifiers;
glfw_ev.text = key_text;
_GLFWIBUSKeyEvent ibus_ev;
ibus_ev.glfw_ev = glfw_ev;
ibus_ev.ibus_keycode = ibus_keycode;
ibus_ev.window_id = window->id;
ibus_ev.ibus_keysym = syms[0];
if (ibus_process_key(&ibus_ev, &xkb->ibus)) {
debug("↳ to IBUS: scancode: 0x%x keysym: 0x%x (%s) %s\n", ibus_ev.ibus_keycode, ibus_ev.ibus_keysym, glfw_xkb_keysym_name(ibus_ev.ibus_keysym), format_mods(ibus_ev.glfw_ev.mods));
} else {
_glfwInputKeyboard(window, glfw_keycode, glfw_sym, action, sg->modifiers, key_event.text, 0);
_glfwInputKeyboard(window, &glfw_ev);
}
}

2
glfw/xkb_glfw.h vendored
View File

@ -93,4 +93,4 @@ xkb_keysym_t glfw_xkb_sym_for_key(int key);
void glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t scancode, int action);
int glfw_xkb_keysym_from_name(const char *name, bool case_sensitive);
void glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, int b, int c, int d);
void glfw_xkb_key_from_ime(KeyEvent *ev, bool handled_by_ime, bool failed);
void glfw_xkb_key_from_ime(_GLFWIBUSKeyEvent *ev, bool handled_by_ime, bool failed);

View File

@ -13,6 +13,7 @@
#include <stdbool.h>
#include <poll.h>
#include <pthread.h>
#include "glfw-wrapper.h"
// Required minimum OpenGL version
#define OPENGL_REQUIRED_VERSION_MAJOR 3
#define OPENGL_REQUIRED_VERSION_MINOR 3
@ -309,7 +310,7 @@ void focus_in_event(void);
void scroll_event(double, double, int);
void fake_scroll(int, bool);
void set_special_key_combo(int glfw_key, int mods, bool is_native);
void on_key_input(int key, int scancode, int action, int mods, const char*, int);
void on_key_input(GLFWkeyevent *ev);
void request_window_attention(id_type, bool);
#ifndef __APPLE__
void play_canberra_sound(const char *which_sound, const char *event_id);

83
kitty/glfw-wrapper.h generated
View File

@ -1,3 +1,9 @@
//
// THIS FILE IS GENERATED BY glfw.py
//
// SAVE YOURSELF SOME TIME, DO NOT MANUALLY EDIT
//
#pragma once
#include <stddef.h>
#include <stdint.h>
@ -18,7 +24,7 @@
* backward-compatible.
* @ingroup init
*/
#define GLFW_VERSION_MINOR 3
#define GLFW_VERSION_MINOR 4
/*! @brief The revision number of the GLFW library.
*
* This is incremented when a bug fix release is made that does not contain any
@ -725,62 +731,62 @@
#define GLFW_CLIENT_API 0x00022001
/*! @brief Context client API major version hint and attribute.
*
* Context client API major version [hint](@ref GLFW_CLIENT_API_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib).
* Context client API major version [hint](@ref GLFW_CONTEXT_VERSION_MAJOR_hint)
* and [attribute](@ref GLFW_CONTEXT_VERSION_MAJOR_attrib).
*/
#define GLFW_CONTEXT_VERSION_MAJOR 0x00022002
/*! @brief Context client API minor version hint and attribute.
*
* Context client API minor version [hint](@ref GLFW_CLIENT_API_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib).
* Context client API minor version [hint](@ref GLFW_CONTEXT_VERSION_MINOR_hint)
* and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib).
*/
#define GLFW_CONTEXT_VERSION_MINOR 0x00022003
/*! @brief Context client API revision number hint and attribute.
*
* Context client API revision number [hint](@ref GLFW_CLIENT_API_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib).
* Context client API revision number
* [attribute](@ref GLFW_CONTEXT_REVISION_attrib).
*/
#define GLFW_CONTEXT_REVISION 0x00022004
/*! @brief Context robustness hint and attribute.
*
* Context client API revision number [hint](@ref GLFW_CLIENT_API_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib).
* Context client API revision number [hint](@ref GLFW_CONTEXT_ROBUSTNESS_hint)
* and [attribute](@ref GLFW_CONTEXT_ROBUSTNESS_attrib).
*/
#define GLFW_CONTEXT_ROBUSTNESS 0x00022005
/*! @brief OpenGL forward-compatibility hint and attribute.
*
* OpenGL forward-compatibility [hint](@ref GLFW_CLIENT_API_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib).
* OpenGL forward-compatibility [hint](@ref GLFW_OPENGL_FORWARD_COMPAT_hint)
* and [attribute](@ref GLFW_OPENGL_FORWARD_COMPAT_attrib).
*/
#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006
/*! @brief OpenGL debug context hint and attribute.
*
* OpenGL debug context [hint](@ref GLFW_CLIENT_API_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib).
* OpenGL debug context [hint](@ref GLFW_OPENGL_DEBUG_CONTEXT_hint) and
* [attribute](@ref GLFW_OPENGL_DEBUG_CONTEXT_attrib).
*/
#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007
/*! @brief OpenGL profile hint and attribute.
*
* OpenGL profile [hint](@ref GLFW_CLIENT_API_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib).
* OpenGL profile [hint](@ref GLFW_OPENGL_PROFILE_hint) and
* [attribute](@ref GLFW_OPENGL_PROFILE_attrib).
*/
#define GLFW_OPENGL_PROFILE 0x00022008
/*! @brief Context flush-on-release hint and attribute.
*
* Context flush-on-release [hint](@ref GLFW_CLIENT_API_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib).
* Context flush-on-release [hint](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint) and
* [attribute](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_attrib).
*/
#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009
/*! @brief Context error suppression hint and attribute.
*
* Context error suppression [hint](@ref GLFW_CLIENT_API_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib).
* Context error suppression [hint](@ref GLFW_CONTEXT_NO_ERROR_hint) and
* [attribute](@ref GLFW_CONTEXT_NO_ERROR_attrib).
*/
#define GLFW_CONTEXT_NO_ERROR 0x0002200A
/*! @brief Context creation API hint and attribute.
*
* Context creation API [hint](@ref GLFW_CLIENT_API_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib).
* Context creation API [hint](@ref GLFW_CONTEXT_CREATION_API_hint) and
* [attribute](@ref GLFW_CONTEXT_CREATION_API_attrib).
*/
#define GLFW_CONTEXT_CREATION_API 0x0002200B
/*! @brief Window content area scaling window
@ -934,6 +940,29 @@ typedef struct GLFWwindow GLFWwindow;
*/
typedef struct GLFWcursor GLFWcursor;
typedef struct GLFWkeyevent
{
// The [keyboard key](@ref keys) that was pressed or released.
int key;
// The system-specific scancode of the key.
int scancode;
// The event action. Either `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`.
int action;
// Bit field describing which [modifier keys](@ref mods) were held down.
int mods;
// UTF-8 encoded text generated by this key event or empty string.
const char *text;
// Used for Input Method events. Zero for normal key events.
// A value of 1 means the pre-edit text for the input event has been changed.
// A value of 2 means the text should be committed.
int ime_state;
} GLFWkeyevent;
/*! @brief The function signature for error callbacks.
*
* This is the function signature for error callback functions.
@ -1219,15 +1248,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int);
* the "s" key will generate text "o" and GLFW_KEY_O.
*
* @param[in] window The window that received the event.
* @param[in] key The [keyboard key](@ref keys) that was pressed or released.
* @param[in] scancode The system-specific scancode of the key.
* @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`.
* @param[in] mods Bit field describing which [modifier keys](@ref mods) were
* held down.
* @param[in] text UTF-8 encoded text generated by this key event or empty string.
* @param[in] Used for Input Method events. Zero for normal key events.
* A value of 1 means the pre-edit text for the input event has been changed.
* A value of 2 means the text should be committed.
* @param[in] ev TODO: blablabla
*
* @note On X11/Wayland if a modifier other than the modifiers GLFW reports
* (ctrl/shift/alt/super) is used, GLFW will report the shifted key rather
@ -1241,7 +1262,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int);
*
* @ingroup input
*/
typedef void (* GLFWkeyboardfun)(GLFWwindow*, int, int, int, int, const char*, int);
typedef void (* GLFWkeyboardfun)(GLFWwindow*, GLFWkeyevent*);
/*! @brief The function signature for file drop callbacks.
*

View File

@ -230,14 +230,14 @@ refresh_callback(GLFWwindow *w) {
static int mods_at_last_key_or_button_event = 0;
static void
key_callback(GLFWwindow *w, int key, int scancode, int action, int mods, const char* text, int state) {
key_callback(GLFWwindow *w, GLFWkeyevent *ev) {
if (!set_callback_window(w)) return;
mods_at_last_key_or_button_event = mods;
mods_at_last_key_or_button_event = ev->mods;
global_state.callback_os_window->cursor_blink_zero_time = monotonic();
if (key >= 0 && key <= GLFW_KEY_LAST) {
global_state.callback_os_window->is_key_pressed[key] = action == GLFW_RELEASE ? false : true;
if (ev->key >= 0 && ev->key <= GLFW_KEY_LAST) {
global_state.callback_os_window->is_key_pressed[ev->key] = ev->action == GLFW_RELEASE ? false : true;
}
if (is_window_ready_for_callbacks()) on_key_input(key, scancode, action, mods, text, state);
if (is_window_ready_for_callbacks()) on_key_input(ev);
global_state.callback_os_window = NULL;
request_tick_callback();
}

View File

@ -31,9 +31,9 @@ static void* empty_thread_main(void* data UNUSED)
return 0;
}
static void key_callback(GLFWwindow *w UNUSED, int key, int scancode UNUSED, int action, int mods UNUSED, const char* text UNUSED, int state UNUSED)
static void key_callback(GLFWwindow *w UNUSED, GLFWkeyevent *ev)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
if (ev->key == GLFW_KEY_ESCAPE && ev->action == GLFW_PRESS) {
glfwSetWindowShouldClose(w, true);
wakeup_main_loop();
}

View File

@ -121,16 +121,24 @@ update_ime_position(OSWindow *os_window, Window* w, Screen *screen) {
#define debug(...) if (OPT(debug_keyboard)) printf(__VA_ARGS__);
void
on_key_input(int key, int scancode, int action, int mods, const char* text, int state) {
on_key_input(GLFWkeyevent *ev) {
Window *w = active_window();
int action, scancode, key, mods;
const char *text;
action = ev->action;
scancode = ev->scancode;
key = ev->key;
mods = ev->mods;
text = ev->text;
debug("on_key_input: glfw key: %d native_code: 0x%x action: %s mods: 0x%x text: '%s' state: %d ",
key, scancode,
(action == GLFW_RELEASE ? "RELEASE" : (action == GLFW_PRESS ? "PRESS" : "REPEAT")),
mods, text, state);
mods, text, ev->ime_state);
if (!w) { debug("no active window, ignoring\n"); return; }
if (OPT(mouse_hide_wait) < 0 && !is_modifier_key(key)) hide_mouse(global_state.callback_os_window);
Screen *screen = w->render_data.screen;
switch(state) {
switch(ev->ime_state) {
case 1: // update pre-edit text
update_ime_position(global_state.callback_os_window, w, screen);
screen_draw_overlay_text(screen, text);