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
Forum Updated to NodeBB v4.3 + New Features

Detecting IF a key is being pressed

Scheduled Pinned Locked Moved Solved General and Desktop
19 Posts 4 Posters 6.9k Views 4 Watching
  • 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.
  • N NightShadeI

    @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 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
    2
    • C CPPUIX

      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 last edited by NightShadeI
      #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
      0
      • N NightShadeI

        @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 last edited by CPPUIX
        #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 last edited by NightShadeI
          #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?

          Kent-DorfmanK 1 Reply Last reply
          0
          • N NightShadeI

            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?

            Kent-DorfmanK Offline
            Kent-DorfmanK Offline
            Kent-Dorfman
            wrote on 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
            0
            • Kent-DorfmanK Kent-Dorfman

              @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 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 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 :)

                Chris KawaC 1 Reply Last reply
                0
                • N NightShadeI

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

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

                  Chris KawaC Offline
                  Chris KawaC Offline
                  Chris Kawa
                  Lifetime Qt Champion
                  wrote on 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
                  7
                  • Chris KawaC Chris Kawa

                    @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 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
                    • Chris KawaC Chris Kawa

                      @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 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

                      • Login

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