Kode / Kinc

Modern low level game library and hardware abstraction.
http://kinc.tech
zlib License
509 stars 122 forks source link

callback set with`kinc_keyboard_set_key_up_callback` not being called for `Ctrl` key #720

Open tcdude opened 2 years ago

tcdude commented 2 years ago

Describe the bug Pressing the Ctrl key does not trigger consistently. In fact I only manage to get it to trigger when I press both Ctrl keys on my keyboard. The callback for kinc_keyboard_set_key_down_callback gets triggered as expected.

From a little bit of testing, this only affects the Ctrl key, while it behaves normally with other keys.

To Reproduce Steps to reproduce the behavior:

  1. Set callbacks for kinc_keyboard_set_key_[down/up]_callback
  2. Look for corresponding down and up events
  3. Don't find the appropriate up event for Ctrl

Expected behavior Same as with other keys (maybe differentiating them into Ctrl-Left/Right, because pressing both, releasing one might create a whole other possibility to fail)

Execution Environment:

Using Kinc (a3f97962) from /home/tc/code/kraymarch/krink/Kinc kfile found. Creating Linux project files. Compiling shader 1 of 14 (kr-painter-colored.frag). Compiling shader 2 of 14 (kr-painter-colored.vert). Compiling shader 3 of 14 (kr-painter-image.frag). Compiling shader 4 of 14 (kr-painter-image.vert). Compiling shader 5 of 14 (kr-painter-sdf-circle.frag). Compiling shader 6 of 14 (kr-painter-sdf-circle.vert). Compiling shader 7 of 14 (kr-painter-sdf-line.frag). Compiling shader 8 of 14 (kr-painter-sdf-line.vert). Compiling shader 9 of 14 (kr-painter-sdf-rect.frag). Compiling shader 10 of 14 (kr-painter-sdf-rect.vert). Compiling shader 11 of 14 (kr-painter-text.frag). Compiling shader 12 of 14 (kr-painter-text.vert). Compiling shader 13 of 14 (g1.frag). Compiling shader 14 of 14 (g1.vert). Compiling... gcc -g -I./ -I../../Sources -I../../krink/Sources -I../../krink/Kinc/Sources -I../../krink/Kinc/Backends/System/Linux/Sources -I../../krink/Kinc/Backends/System/POSIX/Sources -I../wayland -I../../krink/Kinc/Backends/Graphics4/OpenGL/Sources -I../../krink/Kinc/Backends/Graphics5/G5onG4/Sources -I../../krafix/glslang -I../../krafix/glslang/glslang -I../../krafix/glslang/glslang/MachineIndependent -I../../krafix/glslang/glslang/Include -I../../krafix/glslang/OGLCompilersDLL -I../../krafix/glslang/glslang/OSDependent/Unix -DKORE_G1 -DKORE_G2 -DKORE_G3 -DKORE_A1 -DKORE_A2 -DKORE_LZ4X -DKORE_OPENGL -DKINC_EGL -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -DKORE_G4 -DKORE_G5 -DKORE_G5ONG4 -DSPIRV_CROSS_KRAFIX -DENABLE_HLSL -DNV_EXTENSIONS -DAMD_EXTENSIONS -DKRAFIX_LIBRARY -c ../../krink/Kinc/Backends/System/Linux/Sources/kinc/backend/linuxunit.c -o linuxunit.o gcc -g -I./ -I../../Sources -I../../krink/Sources -I../../krink/Kinc/Sources -I../../krink/Kinc/Backends/System/Linux/Sources -I../../krink/Kinc/Backends/System/POSIX/Sources -I../wayland -I../../krink/Kinc/Backends/Graphics4/OpenGL/Sources -I../../krink/Kinc/Backends/Graphics5/G5onG4/Sources -I../../krafix/glslang -I../../krafix/glslang/glslang -I../../krafix/glslang/glslang/MachineIndependent -I../../krafix/glslang/glslang/Include -I../../krafix/glslang/OGLCompilersDLL -I../../krafix/glslang/glslang/OSDependent/Unix -DKORE_G1 -DKORE_G2 -DKORE_G3 -DKORE_A1 -DKORE_A2 -DKORE_LZ4X -DKORE_OPENGL -DKINC_EGL -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -DKORE_G4 -DKORE_G5 -DKORE_G5ONG4 -DSPIRV_CROSS_KRAFIX -DENABLE_HLSL -DNV_EXTENSIONS -DAMD_EXTENSIONS -DKRAFIX_LIBRARY -c ../wayland/wayland-generated/waylandunit.c -o waylandunit.o In file included from ../../krink/Kinc/Backends/System/Linux/Sources/kinc/backend/wayland/wayland.h:9, from ../../krink/Kinc/Backends/System/Linux/Sources/kinc/backend/wayland/display.c.h:1, from ../../krink/Kinc/Backends/System/Linux/Sources/kinc/backend/linuxunit.c:8: ../../krink/Kinc/Sources/kinc/system.h:166:18: warning: ‘always_inline’ function might not be inlinable [-Wattributes] 166 | KINC_INLINE void kinc_debug_break(void) { | ^~~~ g++ -o "kraymarch" -g editor.o main.o pipeline.o modeltree.o toolbar.o viewport.o widgets.o graph.o shadergen.o color.o eventhandler.o image.o memory.o system.o flecs.o krink_flecs.o os_api.o animation_comp.o animation_sys.o drag_comp.o drag_sys.o input_comp.o render_comp.o render_sys.o coloredpainter.o graphics.o imagepainter.o sdfpainter.o textpainter.o ttf.o matrix.o vector.o nuklearkrink.o tlsf.o tween.o compute.o openglunit.o g5ong4unit.o linuxunit.o posixunit.o rootunit.o a1unit.o audio.o graphics.o graphics_kore.o graphics_soft.o g4unit.o g5unit.o inputunit.o iounit.o stb_vorbis.o mathunit.o networkunit.o waylandunit.o spirv_cfg.o spirv_cpp.o spirv_cross.o spirv_cross_c.o spirv_cross_parsed_ir.o spirv_cross_util.o spirv_glsl.o spirv_hlsl.o spirv_msl.o spirv_parser.o spirv_reflect.o agaltranslator.o cstyletranslator.o d3d11compiler.o d3d9compiler.o glsltranslator.o glsltranslator2.o hlsltranslator.o hlsltranslator2.o javascripttranslator.o javascripttranslator2.o metalstageintranslator.o metaltranslator.o metaltranslator2.o spirvtranslator.o translator.o varlisttranslator.o krafix.o initializedll.o glslangtospv.o inreadableorder.o logger.o spvremapper.o spvbuilder.o spvpostprocess.o spvtools.o disassemble.o doc.o resourcelimits.o codegen.o link.o constant.o infosink.o initialize.o intermtraverse.o intermediate.o parsecontextbase.o parsehelper.o poolalloc.o removetree.o scan.o shaderlang.o symboltable.o versions.o attribute.o glslangtab.o intermout.o iomapper.o limits.o linkvalidate.o parseconst.o pch.o propagatenocontraction.o reflection.o pp.o ppatom.o ppcontext.o ppscanner.o pptokens.o ossource.o hlslattributes.o hlslgrammar.o hlslopmap.o hlslparsehelper.o hlslparseables.o hlslscancontext.o hlsltokenstream.o pch.o cdecode.o cencode.o json.o document.o map_col.o map_line.o mappings.o pos_idx.o pos_txt.o v3.o -static-libgcc -static-libstdc++ -pthread -lasound -ldl -ludev -lGL -lEGL Build time: 0m 2s Done.


- Application output (if it runs): *Irrelevant*

**Additional context**
None
tcdude commented 2 years ago

I tracked this down to this if statement: https://github.com/Kode/Kinc/blob/8b34e14b6d00afed85958007818cfdba026a0a5e/Backends/System/Linux/Sources/kinc/backend/x11/system.c.h#L514-L516

When I release a key like Shift keysym is identical to ksKey at that point, but upon releasing a Ctrl key I get different values for those variables and the value in keysym at that time is not matched in the following switch statement. The values that I get for Left Ctrl before ksKey is overwritten with keysym are:

Since others who have tested this under similar setups couldn't replicate my problem I suspect that this could be unrelated to Kinc, but I still would like to investigate this odd behavior further to get to the root cause of it.

tcdude commented 2 years ago

Found the problem.. I tried different keyboards on a hunch that it could maybe related to my fancy keyboard and plugged in the other keyboards on different USB ports on my PC and it suddenly worked just fine. Ultimately it isn't even related to my keyboard at all but somehow related to either the specific port I had it plugged in or the USB extension cable I use to reach from the PC to my desk..

Completely Kinc unrelated

tcdude commented 1 year ago

I encountered that problem again using entirely different setups (HW and SW) and have written a little sample with which I can reproduce the issue on several different machines:

#include <kinc/graphics4/graphics.h>
#include <kinc/input/keyboard.h>
#include <kinc/input/mouse.h>
#include <kinc/log.h>
#include <kinc/system.h>

void update(void) { kinc_g4_swap_buffers(); }

void keydowncb(int code) { kinc_log(KINC_LOG_LEVEL_INFO, "Key %d down", code); }

void keyupcb(int code) { kinc_log(KINC_LOG_LEVEL_INFO, "Key %d up", code); }

void mousedowncb(int w, int button, int x, int y) {
  kinc_log(KINC_LOG_LEVEL_INFO, "Mouse button %d down", button);
}

void mouseupcb(int w, int button, int x, int y) {
  kinc_log(KINC_LOG_LEVEL_INFO, "Mouse button %d up", button);
}

int kickstart(int argc, char **argv) {
  kinc_init("ctrlbug", 1280, 720, NULL, NULL);
  kinc_set_update_callback(update);
  kinc_mouse_set_press_callback(mousedowncb);
  kinc_mouse_set_release_callback(mouseupcb);
  kinc_keyboard_set_key_down_callback(keydowncb);
  kinc_keyboard_set_key_up_callback(keyupcb);
  kinc_start();
  return 0;
}

The mouse callback code is only there because I suspected the combination of Ctrl and multiple clicks could potentially be the cause, which wasn't the case

When running this code on Linux and then pressing the Ctrl key, I get a Key 17 down output as expected, but don't get the corresponding Key 17 up output when releasing the Ctrl key.

I can force the release event when I repeatedly press both Ctrl keys at the same time, several times.

Not sure what causes this, but at least on these combinations I can reproduce the issue:

NOTE: I can resolve the wrong behavior by unplugging the keyboard and plugging it back in, but the wrong behavior is restored upon reboot. This is ofc not easily possible with the integrated keyboard of a laptop...

tcdude commented 1 year ago

To update my findings:

Arch based x64 laptop with i3-gaps (X11)

When I change the keyboard layout at least once using setxkbmap ... the expected behavior starts to work

Manjaro based x64 workstation with i3-gaps (X11)

No amount of changing the keyboard layout fixes anything

ManjaroARM based aarch64 laptop with sway (Wayland)

using Wayland

The key going down registers as code 17, there is a release event, but with code 0 instead!!!!

adding KINC_NO_WAYLAND (i.e. using XWayland)

No amount of changing keyboard layout fixes the behavior

tcdude commented 1 year ago

Testing with xev on i3-gaps / X11 yields something that might be interesting:

KeyPress event, serial 35, synthetic NO, window 0x3800001,
    root 0x1ec, subw 0x0, time 9387186, (-1960,611), root:(511,1256),
    state 0x10, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
    XLookupString gives 0 bytes:
    XmbLookupString gives 0 bytes:
    XFilterEvent returns: False

KeyRelease event, serial 35, synthetic NO, window 0x3800001,
    root 0x1ec, subw 0x0, time 9387316, (-1960,611), root:(511,1256),
    state 0x14, keycode 37 (keysym 0xfe0a, ISO_Prev_Group), same_screen YES,
    XLookupString gives 0 bytes:
    XFilterEvent returns: False

The first event is the key press event, the second one the key release. Note how the keycode remains the same, while the keysym changes between the two events.

tcdude commented 1 year ago

Relevant part to make this reproducible is having the option grp:ctrls_toggle set either through e.g. setxkbmap -layout us,ch -option grp:ctrls_toggle or in the case of sway (Wayland) an option like this:

input * {
        xkb_layout "us, gb"
        xkb_options "grp:ctrls_toggle"
}