juce-framework / JUCE

JUCE is an open-source cross-platform C++ application framework for desktop and mobile applications, including VST, VST3, AU, AUv3, LV2 and AAX audio plug-ins.
https://juce.com
Other
6.54k stars 1.73k forks source link

KeyPress::isKeyCurrentlyDown doesn't read '=' and '\\' keystate in Windows [Bug]: #1309

Closed astriiddev closed 6 months ago

astriiddev commented 10 months ago

Detailed steps on how to reproduce the bug

A 'false' boolean is returned when using KeyPress::isKeyCurrentlyDown('=') or KeyPress::isKeyCurrentlyDown('\\') in Windows regardless of those keys' states. This is due to those two characters not being accounted for in the function in juce_Windowing_windows.cpp

Using '+' instead of '=' or '|' instead of '\\' is an easy workaround, however I'm using the char value from getKeyCode() for a separate function and using those substitution characters instead wouldn't yield the results I need in my program

A proposed addition to the KeyPress::isKeyCurrentlyDown function in juce_Windowing_windows.cpp :

bool KeyPress::isKeyCurrentlyDown (const int keyCode)
{
    auto k = (SHORT) keyCode;

    if ((keyCode & extendedKeyModifier) == 0)
    {
        if (k >= (SHORT) 'a' && k <= (SHORT) 'z')
            k += (SHORT) 'A' - (SHORT) 'a';

        // Only translate if extendedKeyModifier flag is not set
        const SHORT translatedValues[] = { (SHORT) ',', VK_OEM_COMMA,
                                           (SHORT) '+', VK_OEM_PLUS,
                                           (SHORT) '=', VK_OEM_PLUS,
                                           (SHORT) '-', VK_OEM_MINUS,
                                           (SHORT) '.', VK_OEM_PERIOD,
                                           (SHORT) ';', VK_OEM_1,
                                           (SHORT) ':', VK_OEM_1,
                                           (SHORT) '/', VK_OEM_2,
                                           (SHORT) '?', VK_OEM_2,
                                           (SHORT) '[', VK_OEM_4,
                                           (SHORT) ']', VK_OEM_6 };

        for (int i = 0; i < numElementsInArray (translatedValues); i += 2)
            if (k == translatedValues[i])
                k = translatedValues[i + 1];

        /* US keyboards use VK_OEM_5, non-US 102-key keyboards use VK_OEM_102 */
        if (k == (SHORT) '\\') k = VkKeyScanA(k);
    }

    return HWNDComponentPeer::isKeyDown (k);
}

What is the expected behaviour?

KeyPress::isKeyCurrentlyDown returns true when '=' or '\' are pressed down, false when they are released

Operating systems

Windows

What versions of the operating systems?

Windows 11 10.0.22621 Build 22621

Architectures

x86_64, 64-bit

Stacktrace

No response

Plug-in formats (if applicable)

No response

Plug-in host applications (DAWs) (if applicable)

No response

Testing on the develop branch

The bug is present on the develop branch

Code of Conduct

astriiddev commented 10 months ago

'\' should read as '\\' in "What is the expected behaviour?" (forgot to account for Github's own formatting in that spot)

NetworkRock commented 7 months ago

Hello, would like to contribute here (first time). Looks like the above code builds. Cloned the repo, put your code suggestion into it and it has built. Is there also a way to test that somehow 😅 ?

reuk commented 6 months ago

Have you checked whether this behaviour is still present on the develop branch after this commit? https://github.com/juce-framework/juce/commit/8aa9b012643265bba95ad25923af3d8da9edb614

NetworkRock commented 6 months ago

Sorry for confusion I realized later that this issue targeting Windows. Still I had time to write some code for testing that in (OSX). So if anyone else could test that in Windows feel free to ran and adjust the below code for testing it. Also in my case the 47 was a backslash, so you might need to adjust that key code.

Declare methods PluginEditor.h

    bool keyPressed(const juce::KeyPress& key, juce::Component* originatingComponent) override;

    // Declare keyStateChanged method
    bool keyStateChanged(bool isKeyDown, juce::Component* originatingComponent) override;

Implementation PluginEditor.cpp

NewProjectAudioProcessorEditor::NewProjectAudioProcessorEditor (NewProjectAudioProcessor& p)
    : AudioProcessorEditor (&p), audioProcessor (p)
{
    setSize (400, 300);
    setWantsKeyboardFocus(true); // Ensure the editor can receive keyboard events
    addKeyListener(this); // Add the editor as a KeyListener
}
bool NewProjectAudioProcessorEditor::keyPressed(const juce::KeyPress& key, juce::Component* originatingComponent)
{
    if (key.getKeyCode() == 61)
    {
        if (juce::KeyPress::isKeyCurrentlyDown(61))
            DBG("Equal key is currently down.");
        else
            DBG("Equal key is not currently down.");
    }

    if (key.getKeyCode() == 47)
    {
        if (juce::KeyPress::isKeyCurrentlyDown(47))
            DBG("Backslash key is currently down.");
        else
            DBG("Backslash key is not currently down.");
    }
    return true; // Return true to indicate that the key press was handled
}

bool NewProjectAudioProcessorEditor::keyStateChanged(bool isKeyDown, juce::Component* originatingComponent)
{
    if (isKeyDown)
        DBG("A key is currently down.");
    else
        DBG("No keys are currently down.");

    return true; // Return true to indicate that the key state change was handled
}
astriiddev commented 6 months ago

Just now seeing these replies, sorry! Finally got around to updating my Windows version to the current JUCE version (JUCE 7.0.10) and the bug has been fixed. Their version is much more elegant and, from what I can tell, much more accurate than my modification to their old code:

bool KeyPress::isKeyCurrentlyDown (const int keyCode)
{
    const auto k = [&]
    {
        if ((keyCode & extendedKeyModifier) != 0)
            return keyCode;

        const auto vk = BYTE (VkKeyScan ((WCHAR) keyCode) & 0xff);
        return vk != (BYTE) -1 ? vk : keyCode;
    }();

    return HWNDComponentPeer::isKeyDown (k);
}

Looks like I was at least on the right track with that VkKeyScanA that I had in my modification tho 😉 Thanks JUCE devs for fixing this! Closing this issue