lc-soft / LCUI

C library for building user interfaces
https://lcui-dev.github.io
MIT License
4.12k stars 356 forks source link

Text input not working for keys, which are symbol on Shift hold (such as $ or £) #268

Closed WhoAteDaCake closed 2 years ago

WhoAteDaCake commented 2 years ago

Describe the bug

Using the symbol keys like £ or % without holding a shift would not enter the keys correctly

To Reproduce Steps to reproduce the behavior:

  1. Create textedit widget and try to press £ key on the top of the keyboard
  2. Item won't be entered

Expected behavior Would expect number 3 to appear on the screen

Environment (please complete the following information): It's a LINUX x11 problem

Additional context

I think it can be resolved like the following:

static void OnKeyboardMessage(LCUI_Event ev, void *arg)
{
    KeySym keysym;
    XEvent *x_ev = arg;
    LCUI_X11AppDriver x11;
    LCUI_SysEventRec sys_ev;
    switch (x_ev->type) {
    case KeyPress:
        sys_ev.type = LCUI_KEYDOWN;
        break;
    case KeyRelease:
        sys_ev.type = LCUI_KEYUP;
        break;
    default:
        return;
    }
    x11 = LCUI_GetAppData();
    XAutoRepeatOn(x11->display);
    int min;
    int max;
        // Can probably be done once, when a display is created ?
    XDisplayKeycodes(x11->display, &min, &max);
    keysym = XkbKeycodeToKeysym(x11->display, x_ev->xkey.keycode, 0, 0);
    sys_ev.key.code = ConvertKeyCode(keysym);
    sys_ev.key.shift_key = x_ev->xkey.state & ShiftMask ? TRUE : FALSE;
    sys_ev.key.ctrl_key = x_ev->xkey.state & ControlMask ? TRUE : FALSE;

    _DEBUG_MSG("keyname: %s\n", XKeysymToString(keysym));
    _DEBUG_MSG("keycode: %d, keyscancode: %u, keysym: %lu\n", keysym,
           x_ev->xkey.keycode, keysym);
    _DEBUG_MSG("shift: %d, ctrl: %d\n", sys_ev.key.shift_key,
           sys_ev.key.ctrl_key);
    LCUI_TriggerEvent(&sys_ev, NULL);

    if (keysym >= min && keysym <= max && sys_ev.type == LCUI_KEYDOWN) {
        sys_ev.type = LCUI_KEYPRESS;
        sys_ev.key.code = ConvertKeyCodeToChar(x11, x_ev);
        _DEBUG_MSG("char: %c\n", sys_ev.key.code);
        LCUI_TriggerEvent(&sys_ev, NULL);
    }
}
lc-soft commented 2 years ago
        // Can probably be done once, when a display is created ?
    XDisplayKeycodes(x11->display, &min, &max);

I think your current solution is OK,, because it is not necessary to reduce the number of calls to XDisplayKeycodes().

WhoAteDaCake commented 2 years ago

Fixed with https://github.com/lc-soft/LCUI/commit/b3a0a94a9594c5c9451a2a5b0c2a8b13e5146840