activeFocus not being forwarded to TextInput inside TextField

Bug #1545802 reported by Olivier Tilloy
34
This bug affects 5 people
Affects Status Importance Assigned to Milestone
Canonical System Image
Fix Released
Critical
Zoltan Balogh
ubuntu-ui-toolkit (Ubuntu)
Fix Committed
Critical
Cris Dywan
ubuntu-ui-toolkit (Ubuntu RTM)
New
Undecided
Unassigned
webbrowser-app (Ubuntu)
Fix Released
High
Olivier Tilloy

Bug Description

Haven’t managed to reproduce with a standalone example yet, but I can reliably reproduce the following issue with the browser app on a tablet with a bluetooth keyboard connected (this needs to be on a tablet so that the wide layout of the app is used, for example with a Nexus 7 (flo) in landscape orientation):

 1) launch the browser app with a bluetooth keyboard attached and ensure that the current tab is not a new tab
 2) press Ctrl+T to open a new tab

Expected result: the address bar gets active focus so that the user can start entering a URL right away

Current result: the address bar gets active focus for a fraction of a second, then looses it. When that happens, pressing Ctrl+L (which forces focus on the address bar) doesn’t fix it.

I added some debugging to the browser (printing Window.activeFocusItem whenever it changes), and it appears that when initially forcing active focus on the address bar the QQuickTextInput inside it gets active focus, then looses it. At that point the activeFocusItem is the TextField, but it doesn’t forward it to QQuickTextInput inside itself.

That situation can be remedied by using a bluetooth mouse to click on the address bar, which restores active focus on the QQuickTextInput.

Tags: lt-blocker

Related branches

Revision history for this message
Olivier Tilloy (osomon) wrote :

Here’s the additional debug output from the instrumented browser:

[launching the browser, before pressing Ctrl+T]
qml: AFI: Browser_QMLTYPE_185(0xb7cc5ae0)
qml: AFI: QQuickFocusScope(0xb7d0f8c8)
qml: AFI: QQuickFocusScope_QML_174(0xb80651a8)
qml: AFI: WebViewImpl_QMLTYPE_122_QML_197(0xb80a5398)

[after pressing Ctrl+T]
qml: AFI: QQuickTextInput(0xb7d844a8, "text_input")
qml: AFI: WebViewImpl_QMLTYPE_122_QML_197(0xb80a5398)
qml: AFI: QQuickListView(0xb814e608, "foldersList")
qml: AFI: UrlPreviewGrid_QMLTYPE_134(0xb81266a0, "topSitesList")
qml: AFI: UrlPreviewDelegate_QMLTYPE_132(0xb818f010, "topSiteItem")
qml: AFI: QQuickTextInput(0xb7d844a8, "text_input")
qml: AFI: TextField_QMLTYPE_71(0xb7d7b970, "addressBarTextField")

As can be seen with the last two lines, activeFocus is initially forwarded to the QQuickTextInput inside the TextField, and then for some reason activeFocus switches back to the parent TextField, but is removed from the QQuickTextInput.

summary: - TextInput inside TextField not being forwarded activeFocus
+ activeFocus not being forwarded to TextInput inside TextField
Revision history for this message
Olivier Tilloy (osomon) wrote :

I just tried a very ugly hack to work around the issue:

TextField {
  objectName: "addressBarTextField"
  onActiveFocusChanged: {
    if (activeFocus) {
      var textInput = findChild(textField, "text_input")
      console.log("address bar got active focus, text input =", textInput)
      textInput.forceActiveFocus()
      console.log("after forcing active focus on text input", textInput)
    }
  }
}

Where findChild() is copied from UbuntuTestCase to recursively search for a given descendant by objectName.
Well I’m seeing this output:

qml: AFI: QQuickTextInput(0xb779c760, "text_input")
qml: address bar got active focus, text input = QQuickTextInput(0xb779c760, "text_input")
qml: after forcing active focus on text input QQuickTextInput(0xb779c760, "text_input")
qml: AFI: TextField_QMLTYPE_61_QML_146(0xb7793c28, "addressBarTextField")

So this hack isn’t even working. But it seems to indicate that active focus is removed from the TextInput, but remains on the ancestor TextField. Why that happens remains to be explained.

Revision history for this message
Olivier Tilloy (osomon) wrote :

I added some debugging to TextField13.qml, and I can confirm that when I observe the issue, 'focus' is being set to false on the QQuickTextInput.

Revision history for this message
Olivier Tilloy (osomon) wrote :

I have commented out the definition of the custom primaryItem and secondaryItem in the browser’s AddressBar, and the problem persists. So at least we can rule out those two custom components stealing focus.

Revision history for this message
Olivier Tilloy (osomon) wrote :

I’ve replaced the implementation of the AddressBar component with a simple TextField with no added cruft (only placeholder properties and signals that embedders expect), and the problem persists, so it’s not with the AddressBar implementation.

Revision history for this message
Olivier Tilloy (osomon) wrote :

The problem persists in the latest rc-proposed image.

Revision history for this message
Olivier Tilloy (osomon) wrote :

The same issue affects https://code.launchpad.net/~osomon/webbrowser-app/qquickshortcuts/+merge/290299 (which changes the condition for focusing the address bar on opening a new tab from [wide layout] to [has physical keyboard]).

Revision history for this message
Olivier Tilloy (osomon) wrote :

I’m still unable to reproduce the issue in a standalone example, however there is clearly a problem with the TextField component in the UITK, if it allows active focus to not be forwarded to its child QQuickTextInput under certain circumstances.

In TextField.qml, the TextInput element (with id 'editor') is inside a Flickable (id 'flicker'), which itself is a child of the top-level ActionItem. ActionItem is a focus scope, but Flickable isn’t. I’m not sure how a focus scope is supposed to behave when the item that has 'focus: true' isn’t a direct child.

Revision history for this message
Andrea Bernabei (faenil) wrote :

That should not make a difference, as far as I know.

FocusScope redirects focus to the last child who requested it.

I believe in this case, the problem might be that something is setting focus:false on the QQuickTextInput. When you do that, the FocusScope does not know whom to redirect the focus to anymore, as far I know.

And that would explain why nothing is happening.

So, in the beginning TextInput has focus true, so when TextField is focused it redirects the focus to QQuickTextInput. Then somehow QQuickTextInput focus is set to false. The next time TextField is focused, it doesn't redirect the focus to QQuickTextInput because it is actually *not* asking for focus (i.e. it's focus property is false).

Hope that helps :)

Revision history for this message
Olivier Tilloy (osomon) wrote :

Yep, that analysis is correct, but I still don’t know what sets focus to false on the QQuickTextInput, and why.

Revision history for this message
Olivier Tilloy (osomon) wrote :

I still haven’t gotten to the bottom of things, but I found a workaround in the browser: in Browser.qml at line 70¹, if I comment out the call to contentsContainer.forceActiveFocus(), the issue goes away.

The underlying bug still exists in the UITK.

I’m marking webbrowser-app also affected, and linking a branch that has the workaround.

¹ https://bazaar.launchpad.net/~phablet-team/webbrowser-app/trunk/view/head:/src/app/webbrowser/Browser.qml

Changed in webbrowser-app (Ubuntu):
assignee: nobody → Olivier Tilloy (osomon)
importance: Undecided → High
status: New → In Progress
Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package webbrowser-app - 0.23+16.04.20160408.1-0ubuntu1

---------------
webbrowser-app (0.23+16.04.20160408.1-0ubuntu1) xenial; urgency=medium

  [ CI Train Bot ]
  * Resync trunk.

  [ Loïc Molinari ]
  * Made AddressBar height scalable with regards to the grid units
    system.

  [ Olivier Tilloy ]
  * Add dep8 tests and instructions to run them in qemu or on a phone.
    Original work by Leo Arias and Vincent Ladeuil. added: debian/tests/
    debian/tests/control debian/tests/touch-session-autopilot
  * Catch ESC key event one level up to ensure that it’s not incorrectly
    bubbled up to the outer component. (LP: #1557016)
  * Customize the contents of the media permission dialog to avoid
    truncated text. (LP: #1554220)
  * Do not write the session to a temporary file when no target file is
    defined.
  * Fix a failing unit test with Qt 5.6. (LP: #1565507)
  * Fix broken webapp container autopilot tests. (LP: #1557019)
  * Fix issues with item selection in the downloads page: do not allow
    selecting multiple files when only one is expected do not allow
    entering delete mode (with a long press on an item) while in picker
    mode (LP: #1534112, #1561575)
  * Fix unit tests when run under an sbuild chroot. (LP: #1567294)
  * Import QQuickShortcut from Qt 5.5 to properly handle window-level
    keyboard shortcuts. We cannot bump the dependency on Qt to 5.5 as
    the stable overlay PPA for devices currently has Qt 5.4.1. (LP:
    #1542224, #1545802, #1537782)
  * Make the autopilot tests more reliable when dragging the bottom
    edge. (LP: #1560109)
  * Remove workaround for bug #1526940 that was fixed in the latest
    release of the UITK. (LP: #1526940)
  * Rename debian packages to follow new QML module naming convention.
    (LP: #1342031)
  * Simplify the implementation of HistoryViewWide quite a bit, and as a
    side effect fix a unit test failure when run against the staging
    branch of the UITK. (LP: #1567337)

 -- Olivier Tilloy <email address hidden> Fri, 08 Apr 2016 17:07:04 +0000

Changed in webbrowser-app (Ubuntu):
status: In Progress → Fix Released
Olivier Tilloy (osomon)
Changed in canonical-devices-system-image:
status: New → Fix Committed
Cris Dywan (kalikiana)
Changed in ubuntu-ui-toolkit (Ubuntu):
assignee: nobody → Christian Dywan (kalikiana)
Revision history for this message
Olivier Tilloy (osomon) wrote :

Another (simpler) way of reproducing this issue on a touch device (initially reported as bug #1578304), on the latest rc-proposed image:

  - ensure that the webview has active focus
  - tap once on the address bar

The entire text inside the address bar gets selected, as expected, but the active focus remains on the TextField itself, it is not being passed down to the QQuickTextInput inside it.

Tapping once again on the address bar then correctly focuses the QQuickTextInput.

Changed in ubuntu-ui-toolkit (Ubuntu):
importance: Undecided → Critical
Revision history for this message
Launchpad Janitor (janitor) wrote :

Status changed to 'Confirmed' because the bug affects multiple users.

Changed in ubuntu-ui-toolkit (Ubuntu):
status: New → Confirmed
Olivier Tilloy (osomon)
Changed in canonical-devices-system-image:
status: Fix Committed → New
Revision history for this message
Olivier Tilloy (osomon) wrote :

Another occurrence of the issue just happened when running the QML unit tests for this branch: lp:~osomon/webbrowser-app/browserpage.

That’s with a different TextField (the search field in the history view, not the address bar), but the symptom is similar: at some point the code calls forceActiveFocus() on the field, and the TextField component gets active focus, but it doesn’t forward it to the QQuickTextInput inside it.

Revision history for this message
Olivier Tilloy (osomon) wrote :
tags: added: lt-blocker
Revision history for this message
Olivier Tilloy (osomon) wrote :

I’m looking at the code in InputHandler.qml (https://bazaar.launchpad.net/~ubuntu-sdk-team/ubuntu-ui-toolkit/trunk/view/head:/src/Ubuntu/Components/1.3/InputHandler.qml#L289) and something looks suspicious to me: input.focus is set to false when the main control (in our case the TextField) looses active focus, but I don’t see anywhere where it is restored to true.
The following patch seems to fix the regression, although I’m not sure it’s entirely correct, someone familiar with that code should review it and comment:

=== modified file 'src/Ubuntu/Components/1.3/InputHandler.qml'
--- src/Ubuntu/Components/1.3/InputHandler.qml 2016-04-25 10:45:41 +0000
+++ src/Ubuntu/Components/1.3/InputHandler.qml 2016-05-06 07:55:22 +0000
@@ -291,11 +291,7 @@
     Connections {
         target: main
         ignoreUnknownSignals: true
- onActiveFocusChanged: {
- if (!main.activeFocus) {
- input.focus = false;
- }
- }
+ onActiveFocusChanged: input.focus = main.activeFocus
         onKeyNavigationFocusChanged: {
             if (main.keyNavigationFocus) {
                 input.forceActiveFocus();

Changed in canonical-devices-system-image:
assignee: nobody → Zoltan Balogh (bzoltan)
importance: Undecided → Critical
milestone: none → 11
status: New → In Progress
Cris Dywan (kalikiana)
Changed in ubuntu-ui-toolkit (Ubuntu):
status: Confirmed → In Progress
Changed in canonical-devices-system-image:
status: In Progress → Fix Committed
Cris Dywan (kalikiana)
Changed in ubuntu-ui-toolkit (Ubuntu):
status: In Progress → Fix Committed
Revision history for this message
Oliver Grawert (ogra) wrote :

note that the same seems to happen at the login window (waking up the device has the password field auto-focused, enabling a BT keyboard unsets the focus and you have to tap it first)

Changed in canonical-devices-system-image:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Duplicates of this bug

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.