Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TI-nspire CX CAS: Keypad Input/Mapping Enhancements #347

Open
cgloeckner opened this issue Oct 4, 2024 · 15 comments
Open

TI-nspire CX CAS: Keypad Input/Mapping Enhancements #347

cgloeckner opened this issue Oct 4, 2024 · 15 comments

Comments

@cgloeckner
Copy link

cgloeckner commented Oct 4, 2024

Hi,

there are multiple keypad input enhancements, some important, others optional. Sorted from by importance (most important at the top, imho):

Division Operator
Typing / (using number keys) places \. So no division can be entered using the / on the numbers above the keyboard's letters; using the numpad equivalent works fine.

Del Key
The del key behaves just like backspace: it deletes the character to the left (but is assumed to delete the character to the right of the cursor).

Caps Lock
In CX CAS pressing ctrl followed by shift enteres the CAPS mode. Is there a way to use the native keyboard's caps lock key to control this behavior?

Home/End Mapping
Home maps to the on-Key and End to the Scratchpad, which is tricky: When selecting a part of a calculator line, the user may use Home and End to navigate the current line. Maybe the context menu key could be used here, but it'd make things even less intuitive... Maybe the Pause key could be used for on?... I don't have a good suggestion here, yet.
Btw I like the binding of PageUp/PageDown for doc and menu ❤️

Assignment Operator
I'm used to type function declarations using := by entering : followed by = (instead of using the TI's definition feature via ctrl), since the TI Teachers Software for the CX CAS supported this. The Firebird Emulator ignores the : altogether.

Factorial and Percentage Operator
I'm used to type in ! and % directly, based on my experience with the TI Teacher Software for CX CAS.
Entering ! using my computer keyboard does not lead to factorial, neither leads % to automatic percentage conversion.

Lesser/Greater Operator
Typing < or > does not work as expected. According to the keybinding, < creates E and > does not work (the flag symbol does nothing).

Tested with:

  • firebird-emu v1.6
  • using TI-Nspire CX CAS v4.5.5.79
  • Linux Ubuntu with qwertz Keyboard Layout

glocke

@Vogtinator
Copy link
Member

I think it would be better to have a single issue for keypad input enhancements.

@cgloeckner
Copy link
Author

cgloeckner commented Oct 4, 2024

Sure. I'll point the others to this issue and I'll change the opening post accordingly.

@cgloeckner cgloeckner changed the title TI-nspire CX CAS: ! and % keys TI-nspire CX CAS: Keypad Input Enhancements Oct 4, 2024
@cgloeckner cgloeckner changed the title TI-nspire CX CAS: Keypad Input Enhancements TI-nspire CX CAS: Keypad Input/Mapping Enhancements Oct 5, 2024
@complanar
Copy link

Just realized that the ^-keyb on a physical computer keyboard does not map to ^ at the virtual handheld keyboard. Maybe this could be enhanced together with the above.

@complanar
Copy link

After reading the source in qtkeypadbridge.cpp I found out that many keymappings are not accessible for me, at least not with german keyboard layout on linux (other systems not tested). Additionally the window manager seems to grab the [ALT]-Key so that some of these key combinations trigger different actions related to the window manager instead of doing what qtkeypadbridge.cpp suggests.

@cgloeckner
Copy link
Author

I cannot confirm the [ALT]-Key problem, because I configured my window manager to use the "Windows-Key" instead.

But fun fact on the / vs \: If I press [Shift] + [7] (in German Keyboard Layout this would produce /) I get \ inside the Emulator. Using [Shift] + [Alt] + [7] I get the correct /.

@Vogtinator
Copy link
Member

Vogtinator commented Oct 7, 2024

But fun fact on the / vs : If I press [Shift] + [7] (in German Keyboard Layout this would produce /) I get \ inside the Emulator. Using [Shift] + [Alt] + [7] I get the correct /.

This happens because the calculator sees Shift + /, which produces \.

Maybe for non-alpha keys the modifiers should be ignored.

@cgloeckner
Copy link
Author

cgloeckner commented Oct 7, 2024

This happens because the calculator sees Shift + /, which produces \.

How does the calculator gets notified about the modifier? As far as I understand the keybinding, Qt-Keys are mapped to Keypad-"Actions". Are Qt-Modifiers queried somewhere else, too?

@Vogtinator
Copy link
Member

This happens because the calculator sees Shift + /, which produces .

How does the calculator gets notified about the modifier? As far as I understand the keybinding, Qt-Keys are mapped to Keypad-"Actions". Are Qt-Modifiers queried somewhere else, too?

It's just normal keys, pressing and releasing the shift key on the keyboard presses and releases the shift key on the calculator.

@cgloeckner
Copy link
Author

cgloeckner commented Oct 7, 2024

Makes sense. I'm currently experimenting with the code: sending a release of the shift key before any div operation does not work - or at least my approach isn't suitable

if (translated != QtKeyMap.end())
{
    // here <----
    if (*translated == keymap::div)
    {
        // force release of shift key on any division
        setKeypad(keymap::shift, false);
    }
    // to here <---
            
    pressed_keys.insert(vkey, *translated);
    setKeypad(*translated, true);
}

I also tried

auto mkey = event->key();

// here <----
if (event->modifiers() & Qt::ShiftModifier && mkey == Qt::Key_Slash) {
    setKeypad(keymap::shift, false);
}
// to here <---

if (event->modifiers() & Qt::ShiftModifier && mkey == Qt::Key_Alt)
{
    setKeypad(keymap::shift, false);
    return;
}

Only workaround that helps me: Disabling the keybinding for shift altogether.

@Vogtinator
Copy link
Member

I guess that happens for two reasons:

  1. Shift is sticky by the OS. If there is no key press between pressing and releasing shift, the shift state remains until the next shift press (visible as the up arrow in the status bar).
  2. The keypad isn't a queue, it's just an asynchronous bitfield. To generate events, some time has to pass between changing the state of keys.

@cgloeckner
Copy link
Author

cgloeckner commented Oct 9, 2024

  1. Shift is sticky by the OS. If there is no key press between pressing and releasing shift, the shift state remains until the next shift press (visible as the up arrow in the status bar).

Indeed. Hence I'd recommend to not use the keyboard's [Shift] directly as Calculator's [Shift] but with some variation like [Alt]+[Shift] on the keyboard. I'll provide a fork to review and eventually pull. (I'm aware of this having lots of implications)

  1. The keypad isn't a queue, it's just an asynchronous bitfield. To generate events, some time has to pass between changing the state of keys.

Yeah, that's what I've assumed afterwards.
Is there a way to trigger multiple keypad pushes at once? (e.g. to allow a keypress to Qt::Key_BraceLeft mimic the calculator's [ctrl]+[(] to insert a pair of { }).

@Vogtinator
Copy link
Member

Is there a way to trigger multiple keypad pushes at once? (e.g. to allow a keypress to Qt::Key_BraceLeft mimic the calculator's [ctrl]+[(] to insert a pair of { }).

Not directly, because of the async nature of the keypad again. You'd have to send Ctrl first (or make sure it's pressed already), then set ( as pressed. For press events that's somewhat doable with a queue that just waits a ~50ms or so, but coordinating the release events gets complex.

@cgloeckner
Copy link
Author

I'm working on an input queue implementation (I've got a working prototype atm).
Since the implementation of qtkeypadbridge uses global variables, I'd like to refactor it to be encapsulated inside a class QtKeybadBridge for the reason not to introducing yet another global variable (for the queue itself). The class would do both: event handling (as previous) and queueing keypad actions, while keeping the extern qt_keypad_bridge.

Would you welcome such a contribution, @Vogtinator ?

@Vogtinator
Copy link
Member

Global variables don't really hurt because the keypad state itself is a global variable anyway...

@cgloeckner
Copy link
Author

cgloeckner commented Oct 13, 2024

Yes it is, but anway here's what I've got so far, up for discussion: https://github.com/cgloeckner/firebird-input-queue

Some notes:

  • I disabled mapping Host Shift to Calc Shift because their design is fundamentally different: Host Shift is held but Calc Shift toggles. Instead Host Shift+Alt will toggle Calc Shift (because I rarely use Calc Shift myself).
  • The fork implements a std::list<int> as a (pseudo-)queue of actions. Bindings map Host keys to a List of Calc keys, e.g. Qt::Key_Slash maps to keymap::div. To enter := with a host keyboard, I've mapped Qt::Key_Colon (:) to the Calc's ctrl + ::metrix keys. Keys like Qt::Key_Slash or Qt::Key_Colon seem to be identified by Qt as such (using shift+7 or shift+. on me DE_de layout host keyboard)
  • A keyPressEvent will pick a list of actions based on the Host key. A QTimer steps through those action lists and causes the Calc to receive the corresponding key- or touchpad actions (e.g. ! for factorial requires navigating through a selection menu, which might be specific to CX CAS, idk tbh).

I've tried to mimic your coding style (regarding naming convention and placement of {) but it might not be 100% your style, sorry ^^
Furthermore I've documented many things through comments to highlight the idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants