Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-96235

Disabling Qt::WheelFocus on a QSpinBox, then scrolling it, creates a permanent selection

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P3: Somewhat important
    • None
    • 5.15.2, 6.2.0 Beta3
    • None
    • Windows 10 x64, Qt 5.15.2 and 6.2.0 Beta 3
      Reproduced on default Vista theme, and "fusion" and "windows" application styles.
      Didn't test on other OSes.
    • Windows

    Description

      On Qt 5 and 6, if you call QSpinBox::setFocusPolicy(Qt::StrongFocus) (or any weaker focus policy other than Qt::WheelFocus), then scrolling on the QSpinBox causes the text to remain selected and blue, even if you focus another widget. (The intent was to add spinboxes into a keyboard-driven music composing app, but ensure that adjusting numeric settings using the mouse wheel doesn't take focus away from the main canvas.)

      Test program at https://github.com/nyanpasu64/qt6-dpi-fail/tree/qspinbox-blue (note, non-default branch).

      I believe Qt clears widget selections when the widget loses focus. This is intended to ensure there's only one selection at a time, and works as long as you can only create selections in the focused widget. But if you use QWidget::setFocusPolicy() so widgets don't gain focus like usual (like QLineEdit not gaining focus on click, or QAbstractSpinBox not gaining focus on scroll), then you can create a "permanent" selection in one or more widgets, which never goes away when you click on other widgets. A widget's permanent selection is only cleared when you focus and unfocus the widget.

      I think the best fix for QAbstractSpinBox is to change stepBy() to only call selectAll() when the widget is focused. I haven't rebuilt Qt to test this, but I don't think this could break any use cases which aren't already broken.

      An application-specific workaround is to subclass QSpinBox/etc., and override stepBy to call:

              QSpinBox::stepBy(steps);
              if (!hasFocus()) {
                  lineEdit()->deselect();
              }
      

      I have tested that this works. Instances of the QSpinBox subclass with a focus policy set do not gain text selections when scrolled, unless the widget is already focused. With the default focus policy of WheelFocus, instances gain focus and selection upon mouse wheel scrolling.

      A more invasive global fix (which also fixes text-based widgets with Qt::ClickFocus disabled) is to ensure that text-based widgets can't gain selections when not focused (making selectAll() on an unfocused QSpinBox a no-op). However I'm afraid this might cause widespread breakage of Qt or apps.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            qt.team.quick.subscriptions Qt Quick and Widgets Team
            nyanpasu64 Nyan Pasu
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes