Shift + tab? KeyPressed()

I’m not sure if this is a problem with my laptop, my OS(Linux), or what, but Shift+Tab key presses are not calling Component::KeyPressed()? So while I can traverse forward through widgets, I can’t go backwards. Can anyone confirm that this is just a local problem?

I was going to ask about this exact thing tonight. I can use TAB to move from one editable Label to the next, but SHIFT+TAB doesn’t work as expected. (I’m on Ubuntu Linux; haven’t tried any other platform.)

This is a problem for me since I’m working on a data-entry application. If someone knows what I need to change to make SHIFT+TAB work, I’d appreciate it.

I asked the exact same question march this year, (

No one ever provided an answer. I do belive though it must be possible somehow. It is a very common behaviour of almost any program. I find it a bit strange that it isn’t working out of the box so to speak

Presumably some quirk of the linux keyboard handling stuff… I’m busy this week and won’t have time to debug it, but the place to look for clues would be in LinuxComponentPeer::handleKeyPressEvent

Hi Jules, can you add the following cases to juce_Linux_Windowing, circa lines 1402(switch (keyCode) function)

case XK_Shift_L:
case XK_Shift_R:

Shift presses weren't being passed. Not sure if they need to be added ot the translate stuff above?

No... can't really see why that would make sense. That would trigger a key press event when the shift key is pressed, but that's not supposed to happen for modifier, only for "real" keys.

Ok, that was a rather rash suggestion. My problem is that if I press the shift key on Linux my keyPressed() method never gets called. I thought my above suggestion would fix it, but after some experimentation I agree, it is not a good solution :).  Any other suggestions? I'm try to catch tab+shift, but like I said, pressing shift seems to prevent my keypress method from being called.  

Of course I meant that pressing a combo of Shift+Tab does not invoke KeyPressed()! Other combos work fine.

Hmm, not sure. Maybe there's a special key-code for that combination?

Found it. So one needs to check for "case XK_ISO_Left_Tab:", but it doesn't get caught with your:

if ((sym & 0xff00) == 0xff00)


My rather crude hack(avert your eyes!) is to do:

        if ((sym & 0xff00) == 0xff00 || sym==XK_ISO_Left_Tab)

This gets me into the the body of that if statement so I can check for XK_ISO_Left_Tab. No doubt nees some JUCEing up.

[EXTRA BONUS QUESTION!] In the top of that method you have a pair of { }'s preceeded and followed by nothing. What does this mean. I'm having a hard time finding anything about it online?

That's actually not such a bad hack! When you're in the horrible under-the-hood platform-specific code, a bit of hackery like that is often the only way to get the required result.

Bonus question: It's just a scoped block - it restricts the scope of the local variables inside it, to separate them from the code that follows the block. It's a handy trick when using RAII types like scoped locks.


Hi Jules

Just got back to my old JUCE app, brought it up to juce 3.0.8 and thought I'd had a look at this old shift-tab issue again. Seems like Rory suggested the right thing but he didn't reveal everything needed. (See his comment: This gets me into the the body of that if statement so I can check for XK_ISO_Left_Tab. )

Don't know how he actually made the check within the body, but this patch solves my problems:


git show a434b235c566e0f7fdafc0fe4caccc485ae52d24

commit a434b235c566e0f7fdafc0fe4caccc485ae52d24
Author: Kim Bøndergaard <>
Date:   Sat Oct 18 23:54:54 2014 +0200

    Fixed problem with shift-tab not working

diff --git a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp b/modules/j
index b9bd76b..f312876 100644
--- a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp
+++ b/modules/juce_gui_basics/native/juce_linux_Windowing.cpp
@@ -1433,6 +1433,11 @@ public:
                     keyCode &= 0xff;
+                case XK_ISO_Left_Tab:^M
+                    keyPressed = true;^M
+                    keyCode = XK_Tab & 0xff;^M
+                    break;^M
                     if (sym >= XK_F1 && sym <= XK_F16)


Cool, thanks for the heads-up, I'll take a look at that!

..actually, just looking at the code that was originally there, there's a comparison at line 1375 where it says "sym == XK_ISO_Left_Tab".

Assuming that your fix does work, then it's the keyCode and not the sym that should be getting tested, right? So presumably the test for "sym == XK_ISO_Left_Tab" is actually redundant and could be removed?

The comparison in line 1375 is necessary to get into the if - statement in which the switch on XK_ISO_Left_Tab is inserted.

Problem is that XK_ISO_Left_Tab has a value of 0xFE20 and thus not falling into the sym & 0xFF00 filter.

But I must admit that I can't really see the difference between sym and keyCode values.


While inserting the following debug just above the if statement in line 1375

DBG("sym: " + String(static_cast<unsigned int>(sym)));
DBG("keycode" + String(keyCode));

I get this by pressing "Tab", "Right Shift", "Left Shift", "Right Shift + Tab"

JUCE v3.0.8
sym: 65289           <- Tab
sym: 65506           <- Right shift
sym: 65505           <- Left shift
sym: 65506           <- Right shift (keep pressed)
sym: 65056          <- + Tab

Another approach would be to do something like this:

        if (keyCode == XK_ISO_Left_Tab) 
            keyPressed = true;
            keyCode = XK_Tab & 0xff;
        else if ((sym & 0xff00) == 0xff00)


keeping XK_ISO_Left_Tab handling separate from the other key handling


Ok, thanks, I'll sort something out for that!