Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Detecting IF a key is being pressed

Detecting IF a key is being pressed

Scheduled Pinned Locked Moved Solved General and Desktop
19 Posts 4 Posters 6.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Kent-Dorfman
    6 Jun 2023, 01:49

    @NightShadeI
    I got nothing, because I have never encountered the need to handle key events while moving windows.

    N Offline
    N Offline
    NightShadeI
    wrote on 6 Jun 2023, 02:00 last edited by NightShadeI 6 Jun 2023, 02:01
    #7

    @Kent-Dorfman

    That's fine, can leave for someone else to answer.

    Just to be clear to anyone reading, the aim isn't necessarily to handle key events while the window is moving (although it is still a win if I can)

    The aim is just to detect that i'm in some state where events cannot be handled, so it might be better to wipe my map of "keys currently being pressed" , to maintain some invariant , and not be left in a bad state

    Or even provide a solution that will allow me to forego the use of this stateful map, (example querying the keyboard state during painting instead of relying on my own map)

    N 1 Reply Last reply 6 Jun 2023, 03:41
    0
    • N NightShadeI
      6 Jun 2023, 02:00

      @Kent-Dorfman

      That's fine, can leave for someone else to answer.

      Just to be clear to anyone reading, the aim isn't necessarily to handle key events while the window is moving (although it is still a win if I can)

      The aim is just to detect that i'm in some state where events cannot be handled, so it might be better to wipe my map of "keys currently being pressed" , to maintain some invariant , and not be left in a bad state

      Or even provide a solution that will allow me to forego the use of this stateful map, (example querying the keyboard state during painting instead of relying on my own map)

      N Offline
      N Offline
      NightShadeI
      wrote on 6 Jun 2023, 03:41 last edited by NightShadeI 6 Jun 2023, 05:46
      #8

      @NightShadeI

      Another update: I think this problem is even worse and there seems to be some bug in QT looking more deeply into it

      After you stop dragging the window, if you press the same key again, it won't register as a key press, but it will register as a key release once you raise the key... (and everything is then consistent again) so this means QT's internal state must be wrong since it seems its also waiting for the key release, which already happened while it was blocked

      Update 2: Tried on OSX , and it also doesn't work there , so thinking this might be some QT specific bug

      Update 3:

      Here is the most minimal code example I could make to reproduce the issue, if you try to move or resize the widget while pressing any keyboard button , the event will never be called:

      class KeyPressFilter : public QObject {
      public:
          bool eventFilter(QObject* aObject, QEvent* aEvent) final {
              if (aEvent->type() != QEvent::KeyRelease) return QObject::eventFilter(aObject, aEvent);
              if (!static_cast<QKeyEvent*>(aEvent)->isAutoRepeat()) {
                  std::cout << "Will it be called? Who knows!" << std::endl;
              }
              return true;
          }
      };
      
      int main(int aArgc, char *aArgv[]) {
          QApplication myApplication{aArgc, aArgv};
      
          KeyPressFilter myKeyFilter;
          myApplication.installEventFilter(&myKeyFilter);
      
          QWidget myWidget;
          myWidget.show();
      
          return myApplication.exec();
      }
      
      N 1 Reply Last reply 7 Jun 2023, 04:49
      2
      • N NightShadeI
        6 Jun 2023, 03:41

        @NightShadeI

        Another update: I think this problem is even worse and there seems to be some bug in QT looking more deeply into it

        After you stop dragging the window, if you press the same key again, it won't register as a key press, but it will register as a key release once you raise the key... (and everything is then consistent again) so this means QT's internal state must be wrong since it seems its also waiting for the key release, which already happened while it was blocked

        Update 2: Tried on OSX , and it also doesn't work there , so thinking this might be some QT specific bug

        Update 3:

        Here is the most minimal code example I could make to reproduce the issue, if you try to move or resize the widget while pressing any keyboard button , the event will never be called:

        class KeyPressFilter : public QObject {
        public:
            bool eventFilter(QObject* aObject, QEvent* aEvent) final {
                if (aEvent->type() != QEvent::KeyRelease) return QObject::eventFilter(aObject, aEvent);
                if (!static_cast<QKeyEvent*>(aEvent)->isAutoRepeat()) {
                    std::cout << "Will it be called? Who knows!" << std::endl;
                }
                return true;
            }
        };
        
        int main(int aArgc, char *aArgv[]) {
            QApplication myApplication{aArgc, aArgv};
        
            KeyPressFilter myKeyFilter;
            myApplication.installEventFilter(&myKeyFilter);
        
            QWidget myWidget;
            myWidget.show();
        
            return myApplication.exec();
        }
        
        N Offline
        N Offline
        NightShadeI
        wrote on 7 Jun 2023, 04:49 last edited by NightShadeI 6 Jul 2023, 04:51
        #9

        Could one of the QT pros give some insight on this? Even if it's just answering I should make a QT bug ticket (if it is one?)

        Or even if the issue can be reproduced

        1 Reply Last reply
        0
        • N NightShadeI
          6 Jun 2023, 01:30

          @Kent-Dorfman

          This is while it still has focus, and infact I mark all keys as not pressed when QEvent::WindowDeactivate is received

          To reproduce on Windows 10 for example you would:

          1. Hold 'W' key (for example), observe keyPressedEvent is called
          2. Start dragging the window while still holding W key, with your mouse. By dragging the window I mean clicking and holding on the window title bar and moving the mouse
          3. Release the 'W' key while still dragging. Observe the keyReleaseEvent is not called while this occurs.
          4. You will therefore get into some state with the window focused, and the application thinks the 'W' is still pressed, but it is not
          C Offline
          C Offline
          CPPUIX
          wrote on 7 Jun 2023, 13:40 last edited by
          #10

          Hi,

          First, here's my exact environment:

          • System :
            • Operating System: KDE neon 5.27
            • KDE Plasma Version: 5.27.5
            • KDE Frameworks Version: 5.106.0
            • Qt Version: 5.15.9
            • Kernel Version: 5.19.0-41-generic (64-bit)
            • Graphics Platform: X11

          • Developing tools :
            • Qt 6.5.0
            • CMake 3.22.1
            • Qt Creator 10.0.1
            • Kit: Desktop Qt 6.5.0 GCC 64bit

          @NightShadeI said in Detecting IF a key is being pressed:

          1. Hold 'W' key (for example), observe keyPressedEvent is called
          2. Start dragging the window while still holding W key, with your mouse. By dragging the window I mean clicking and holding on the window title bar and moving the mouse
          3. Release the 'W' key while still dragging. Observe the keyReleaseEvent is not called while this occurs.
          4. You will therefore get into some state with the window focused, and the application thinks the 'W' is still pressed, but it is not

          I couldn't reproduce that, key release event gets called while still moving the window or resizing it. I tried different combinations of pressing, releasing, dragging, resizing, all resulted the same.

          @NightShadeI said in Detecting IF a key is being pressed:

          After you stop dragging the window, if you press the same key again, it won't register as a key press, but it will register as a key release once you raise the key

          @NightShadeI said in Detecting IF a key is being pressed:

          if you try to move or resize the widget while pressing any keyboard button , the event will never be called

          Wouldn't that be because your MRE only detects key release events.

          From what I understand, I made my own event filter, here it is:

          bool eventFilter(QObject* aObject, QEvent* aEvent) final
              {
                  //detect key release
                  //the current time is just my way of preventing same output of debug messages
                  if (aEvent->type() == QEvent::KeyRelease)
                  {
                      if (!static_cast<QKeyEvent*>(aEvent)->isAutoRepeat())
                      {
                          qDebug() << "Key Released"  << QTime::currentTime();
                      }
                  }
                  //detect key press
                  if (aEvent->type() == QEvent::KeyPress)
                  {
                      if (!static_cast<QKeyEvent*>(aEvent)->isAutoRepeat())
                      {
                          qDebug() << "Key Pressed"  << QTime::currentTime() << "\n";
                      }
                  }
          
                  return QObject::eventFilter(aObject, aEvent);
              }
          

          I tried multiple ways of pressing and releasing again, and everything seems to be normal.

          I am no expert, just thought I'd share this in case it might be of some help. You can also correct me if I got it wrong (I feel like I'm missing something), to clarify it for others.

          Good luck!

          N 1 Reply Last reply 7 Jun 2023, 14:01
          2
          • C CPPUIX
            7 Jun 2023, 13:40

            Hi,

            First, here's my exact environment:

            • System :
              • Operating System: KDE neon 5.27
              • KDE Plasma Version: 5.27.5
              • KDE Frameworks Version: 5.106.0
              • Qt Version: 5.15.9
              • Kernel Version: 5.19.0-41-generic (64-bit)
              • Graphics Platform: X11

            • Developing tools :
              • Qt 6.5.0
              • CMake 3.22.1
              • Qt Creator 10.0.1
              • Kit: Desktop Qt 6.5.0 GCC 64bit

            @NightShadeI said in Detecting IF a key is being pressed:

            1. Hold 'W' key (for example), observe keyPressedEvent is called
            2. Start dragging the window while still holding W key, with your mouse. By dragging the window I mean clicking and holding on the window title bar and moving the mouse
            3. Release the 'W' key while still dragging. Observe the keyReleaseEvent is not called while this occurs.
            4. You will therefore get into some state with the window focused, and the application thinks the 'W' is still pressed, but it is not

            I couldn't reproduce that, key release event gets called while still moving the window or resizing it. I tried different combinations of pressing, releasing, dragging, resizing, all resulted the same.

            @NightShadeI said in Detecting IF a key is being pressed:

            After you stop dragging the window, if you press the same key again, it won't register as a key press, but it will register as a key release once you raise the key

            @NightShadeI said in Detecting IF a key is being pressed:

            if you try to move or resize the widget while pressing any keyboard button , the event will never be called

            Wouldn't that be because your MRE only detects key release events.

            From what I understand, I made my own event filter, here it is:

            bool eventFilter(QObject* aObject, QEvent* aEvent) final
                {
                    //detect key release
                    //the current time is just my way of preventing same output of debug messages
                    if (aEvent->type() == QEvent::KeyRelease)
                    {
                        if (!static_cast<QKeyEvent*>(aEvent)->isAutoRepeat())
                        {
                            qDebug() << "Key Released"  << QTime::currentTime();
                        }
                    }
                    //detect key press
                    if (aEvent->type() == QEvent::KeyPress)
                    {
                        if (!static_cast<QKeyEvent*>(aEvent)->isAutoRepeat())
                        {
                            qDebug() << "Key Pressed"  << QTime::currentTime() << "\n";
                        }
                    }
            
                    return QObject::eventFilter(aObject, aEvent);
                }
            

            I tried multiple ways of pressing and releasing again, and everything seems to be normal.

            I am no expert, just thought I'd share this in case it might be of some help. You can also correct me if I got it wrong (I feel like I'm missing something), to clarify it for others.

            Good luck!

            N Offline
            N Offline
            NightShadeI
            wrote on 7 Jun 2023, 14:01 last edited by NightShadeI 6 Jul 2023, 14:05
            #11

            @Abderrahmene_Rayene

            Very much appreicate the attempt to reproduce! I don't have some sort of linux OS I can work with , so maybe it is only specific to OSX and Windows? Either way appreciate you helping with the investigation on this issue :)

            I believe you have understood perfectly

            Wouldn't that be because your MRE only detects key release events.

            Just to clarify, I use keyPress and keyRelease in my actual code, just used keyRelease only in MRE to give the shorest possible code , as to try not to detour people , since both highlight the issue

            C 1 Reply Last reply 7 Jun 2023, 14:06
            0
            • N NightShadeI
              7 Jun 2023, 14:01

              @Abderrahmene_Rayene

              Very much appreicate the attempt to reproduce! I don't have some sort of linux OS I can work with , so maybe it is only specific to OSX and Windows? Either way appreciate you helping with the investigation on this issue :)

              I believe you have understood perfectly

              Wouldn't that be because your MRE only detects key release events.

              Just to clarify, I use keyPress and keyRelease in my actual code, just used keyRelease only in MRE to give the shorest possible code , as to try not to detour people , since both highlight the issue

              C Offline
              C Offline
              CPPUIX
              wrote on 7 Jun 2023, 14:06 last edited by CPPUIX 6 Jul 2023, 14:11
              #12

              @NightShadeI said in Detecting IF a key is being pressed:

              just used keyRelease only in MRE to give the shorest possible code , as to try not to detour people , since both highlight the issue

              I think you should include the key press event as well in your MRE, I thought you missed it.

              And you're welcome, thanks for providing details, I always appreciate an MRE.

              1 Reply Last reply
              0
              • N Offline
                N Offline
                NightShadeI
                wrote on 9 Jun 2023, 08:50 last edited by NightShadeI 6 Sept 2023, 08:51
                #13

                Can one of QT members please clarify if I should be raising a bug for this? Getting pretty desperate and it's still not solved

                Or is there anything else I should provide?

                K 1 Reply Last reply 10 Jun 2023, 03:22
                0
                • N NightShadeI
                  9 Jun 2023, 08:50

                  Can one of QT members please clarify if I should be raising a bug for this? Getting pretty desperate and it's still not solved

                  Or is there anything else I should provide?

                  K Offline
                  K Offline
                  Kent-Dorfman
                  wrote on 10 Jun 2023, 03:22 last edited by
                  #14

                  @NightShadeI

                  I wouldn't file a bug report unless you are sure they will be able to reproduce the behaviour. That's the key to having it addressed.

                  N 1 Reply Last reply 10 Jun 2023, 14:18
                  0
                  • K Kent-Dorfman
                    10 Jun 2023, 03:22

                    @NightShadeI

                    I wouldn't file a bug report unless you are sure they will be able to reproduce the behaviour. That's the key to having it addressed.

                    N Offline
                    N Offline
                    NightShadeI
                    wrote on 10 Jun 2023, 14:18 last edited by
                    #15

                    @Kent-Dorfman

                    Is there anything else you think I should provide for this? I think I really just need someone else to try this on windows or OSX now, I've given steps and code

                    1 Reply Last reply
                    0
                    • N Offline
                      N Offline
                      NightShadeI
                      wrote on 14 Jun 2023, 09:24 last edited by
                      #16

                      @JonB , @SGaist , @Christian-Ehrlicher , @Chris-Kawa or @jsulm

                      Are any of you able to provide any light on this issue? Thanks :)

                      C 1 Reply Last reply 14 Jun 2023, 21:38
                      0
                      • N NightShadeI
                        14 Jun 2023, 09:24

                        @JonB , @SGaist , @Christian-Ehrlicher , @Chris-Kawa or @jsulm

                        Are any of you able to provide any light on this issue? Thanks :)

                        C Offline
                        C Offline
                        Chris Kawa
                        Lifetime Qt Champion
                        wrote on 14 Jun 2023, 21:38 last edited by Chris Kawa
                        #17

                        @NightShadeI Well, welcome to the world of pain input handling :) This is not a Qt bug and you're not missing any events. You're just not getting any. There is no state that gets lost in Qt because it holds no state (apart from modifiers). It directly translates the OS messages to you e.g. on Windows the WM_[whatever] native messages. You can install the native event filter on the app object and monitor all the raw messages OS sends to your windows if you want to see for yourself. It's the same if you use MFC or low level WinAPI. They all just work with what the system sends.

                        A drag is denoted by QEvent::NonClientAreaMouseButtonPress and QEvent::NonClientAreaMouseButtonRelease. I don't know about other OSes and I suspect this could vary on different window managers, but on Windows a window that is being dragged does not receive key press or release events. This means that:

                        If you press before and release after a drag you will get both events.
                        If you press before and release during drag you will only get the press event.
                        If you press during and release after you will only get release.
                        If you press during, hold long enough to get autorepeat after drag and then release then it gets weird, because the first autorepeat after drag is converted to normal press, so you get normal press, then auto-repeat release without matching press, then a bunch of auto-repeat presses/releases pairs and a finishing normal release.

                        I'd say it's a very niche corner case that may vary across platforms and there's no point in obsessing over it. The easiest way to handle this not to end up in an inconsistent state is to clear your key map when you get a non-client mouse press. You won't get any key presses until the drag is over and at worst you'll get an unmatched release after, but that's fine, since the map is cleared anyway.

                        If you want to loose some hair and actually handle this (I would advise against) you'd need to use the platform specific low level input APIs e.g. Direct Input or a keyboard hook with the SetWindowsHookEx API on Windows. I don't know about other OSes, but I suspect they have something similar.

                        N 2 Replies Last reply 14 Jun 2023, 22:55
                        7
                        • C Chris Kawa
                          14 Jun 2023, 21:38

                          @NightShadeI Well, welcome to the world of pain input handling :) This is not a Qt bug and you're not missing any events. You're just not getting any. There is no state that gets lost in Qt because it holds no state (apart from modifiers). It directly translates the OS messages to you e.g. on Windows the WM_[whatever] native messages. You can install the native event filter on the app object and monitor all the raw messages OS sends to your windows if you want to see for yourself. It's the same if you use MFC or low level WinAPI. They all just work with what the system sends.

                          A drag is denoted by QEvent::NonClientAreaMouseButtonPress and QEvent::NonClientAreaMouseButtonRelease. I don't know about other OSes and I suspect this could vary on different window managers, but on Windows a window that is being dragged does not receive key press or release events. This means that:

                          If you press before and release after a drag you will get both events.
                          If you press before and release during drag you will only get the press event.
                          If you press during and release after you will only get release.
                          If you press during, hold long enough to get autorepeat after drag and then release then it gets weird, because the first autorepeat after drag is converted to normal press, so you get normal press, then auto-repeat release without matching press, then a bunch of auto-repeat presses/releases pairs and a finishing normal release.

                          I'd say it's a very niche corner case that may vary across platforms and there's no point in obsessing over it. The easiest way to handle this not to end up in an inconsistent state is to clear your key map when you get a non-client mouse press. You won't get any key presses until the drag is over and at worst you'll get an unmatched release after, but that's fine, since the map is cleared anyway.

                          If you want to loose some hair and actually handle this (I would advise against) you'd need to use the platform specific low level input APIs e.g. Direct Input or a keyboard hook with the SetWindowsHookEx API on Windows. I don't know about other OSes, but I suspect they have something similar.

                          N Offline
                          N Offline
                          NightShadeI
                          wrote on 14 Jun 2023, 22:55 last edited by
                          #18

                          @Chris-Kawa

                          Thanks for the reply, I can't thank you for it enough. This is super useful and I believe I'll do the former of your approaches, sounds like a lot less of a headache :)

                          I'll test tonight and mark as solved if all is good! Hope this serves to help many others in future

                          1 Reply Last reply
                          0
                          • C Chris Kawa
                            14 Jun 2023, 21:38

                            @NightShadeI Well, welcome to the world of pain input handling :) This is not a Qt bug and you're not missing any events. You're just not getting any. There is no state that gets lost in Qt because it holds no state (apart from modifiers). It directly translates the OS messages to you e.g. on Windows the WM_[whatever] native messages. You can install the native event filter on the app object and monitor all the raw messages OS sends to your windows if you want to see for yourself. It's the same if you use MFC or low level WinAPI. They all just work with what the system sends.

                            A drag is denoted by QEvent::NonClientAreaMouseButtonPress and QEvent::NonClientAreaMouseButtonRelease. I don't know about other OSes and I suspect this could vary on different window managers, but on Windows a window that is being dragged does not receive key press or release events. This means that:

                            If you press before and release after a drag you will get both events.
                            If you press before and release during drag you will only get the press event.
                            If you press during and release after you will only get release.
                            If you press during, hold long enough to get autorepeat after drag and then release then it gets weird, because the first autorepeat after drag is converted to normal press, so you get normal press, then auto-repeat release without matching press, then a bunch of auto-repeat presses/releases pairs and a finishing normal release.

                            I'd say it's a very niche corner case that may vary across platforms and there's no point in obsessing over it. The easiest way to handle this not to end up in an inconsistent state is to clear your key map when you get a non-client mouse press. You won't get any key presses until the drag is over and at worst you'll get an unmatched release after, but that's fine, since the map is cleared anyway.

                            If you want to loose some hair and actually handle this (I would advise against) you'd need to use the platform specific low level input APIs e.g. Direct Input or a keyboard hook with the SetWindowsHookEx API on Windows. I don't know about other OSes, but I suspect they have something similar.

                            N Offline
                            N Offline
                            NightShadeI
                            wrote on 15 Jun 2023, 09:57 last edited by
                            #19

                            @Chris-Kawa

                            Works perfectly on both Windows and OSX!

                            I'll leave a footnote for anyone in future, that it seems that on OSX you have to actually install a event filter into the QApplication to handle the event, the QWidget does not seem to receive this event, where as it seems to on Windows.

                            Thanks Chris again for the response, will mark as solved

                            1 Reply Last reply
                            2
                            • N NightShadeI has marked this topic as solved on 15 Jun 2023, 09:57

                            16/19

                            14 Jun 2023, 09:24

                            • Login

                            • Login or register to search.
                            16 out of 19
                            • First post
                              16/19
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • Users
                            • Groups
                            • Search
                            • Get Qt Extensions
                            • Unsolved