2
votes

I'm trying to display a Google login dialog in a QWebView, and as I recall, Google likes to set your keyboard focus to the first input field on the page (in this case, the e-mail field).

Unfortunately, the QWebView widget doesn't actually respect this behaviour, and therefore loads the page with keyboard focus on nothing at all:

Login dialog with no focus

So I decided dig about a little, and inserted this code snippet into my class logic:

void GoogleAuthDialog::pageLoaded(bool ok) {
    if (ok) {
        ui->webView->setFocus();
        ui->webView->page()->mainFrame()->setFocus();
        QWebElement el = ui->webView->page()->mainFrame()->findFirstElement("input:not([type=hidden])");
        if (!el.isNull()) {
            el.setFocus();
            el.evaluateJavaScript("this.focus()");
            el.evaluateJavaScript("this.click()");
        }
    }
}

And the following declaration in my header file:

...
private slots:
    void pageLoaded(bool);

Back in the class code, I connected the appropriate signal from the QWebView to my slot:

connect(ui->webView, SIGNAL(loadFinished(bool)), this, SLOT(pageLoaded(bool)));

Yes, I am throwing every possible thing I can think of at it to redirect keyboard focus to the first input box.

Unfortunately, the code did not seem to work, as while it did focus the right input box, I could not type anything inside of it until I clicked it myself, or pressed Tab:

Focus with no keyboard

Next I bound the function to my Control key, and proceeded to produce strange results.

If I placed focus into the password field manually, and pressed the Control key, I noticed that I would continue to have keyboard focus in the password field, but have 'visual' focus in the e-mail field:

Keyboard caret in the wrong field

Also, when I typed something in this 'state', occasionally a letter might 'leak' into the e-mail field before the visual and keyboard focus would 'reset' to the password field:

Character leaking

Is there a proper way of redirecting keyboard focus to an input field of my choosing?

2
@duDE Thank you for the link, but I don't believe listening for focus events would actually help me focus the keyboard input directly.TheFuzzy

2 Answers

3
votes

I managed to redirect the keyboard input focus by simulating tab focusing via QKeyEvent:

void GoogleAuthDialog::pageLoaded(bool ok) {
if (ok) {
    //Gets the first input element
    QWebElement el = ui->webView->page()->currentFrame()->findFirstElement("input:not([type=hidden])");
    if (!el.isNull()) {
        el.setFocus();
    }
    // Simulate a forward tab, then back.
    QKeyEvent *forwardTab = new QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier);
    QKeyEvent *backwardTab = new QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier);
    QCoreApplication::postEvent(ui->webView, forwardTab);
    QCoreApplication::postEvent(ui->webView, backwardTab);
    }
}

In my opinion, this does seem like a 'hack-ish' solution, so if there is a 'right' way to do this, I'm all ears.

0
votes

pgh is right. Just set focus on the QWebView object during your app's initialization.

m_webView->setFocus();