Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

WebView focus on the WebPage



  • Is it possible to give a WebView focus that enables JavaScript on the website to accept onClick events without having to click on the WebView?

    We do not have a mouse, and need to get focus on the webpage.

    Ex: I'm on a List with KeyNavigation.right = webView. When I navigate to the right the webView gains focus. I want the next keypress to be sent to the WebPage and NOT to the webView.

    Edit: Found someone else that has the same problem and was never answered: http://developer.qt.nokia.com/forums/viewthread/1917

    Edit: A challenge for you! When the following QML loads up, make it focus the google search bar like most browser. So when I start typing with the keyboard, it immediately starts typing in the search bar. You can not use your mouse! ;)

    @import Qt 4.7
    import QtWebKit 1.0

    WebView {
    id: webView
    width: 1280
    height: 600
    url: "http://www.google.com"
    }
    @

    Edit: Trying to derive from QDeclarativeWebView and extend the functionality myself. However, the registerTypes(const char *uri) is not getting called. If I remove QDeclarativeWebView from the equation, and substitute it with QDeclarativeItem, the plugin now works. /boggle

    GtTools.cpp (Plugin Entry)

    @#include "GtTools.h"
    #include "QDebug"
    #include "InteractiveWebKit.h"

    void GtTools::registerTypes(const char *uri)
    {
    qDebug() << endl << "Registering GtTools" << endl;

    Q_UNUSED(uri);
    
    qmlRegisterType<InteractiveWebKit>("GtTools", 1, 0, "InteractiveWebKit");
    

    }

    Q_EXPORT_PLUGIN(GtTools);@

    GtTools.h

    @#include "GtTools.h"
    #include "QDebug"
    #include "InteractiveWebKit.h"

    void GtTools::registerTypes(const char *uri)
    {
    qDebug() << endl << "Registering GtTools" << endl;

    Q_UNUSED(uri);
    
    qmlRegisterType<InteractiveWebKit>("GtTools", 1, 0, "InteractiveWebKit");
    

    }

    Q_EXPORT_PLUGIN(GtTools);@

    InteractiveWebKit (The class I am extending from QDeclarativeWebView)

    @#include <QtCore/QTime>
    #include <QtDeclarative/qdeclarative.h>

    #include "InteractiveWebKit.h"

    InteractiveWebKit::InteractiveWebKit(QDeclarativeItem *parent):
    QDeclarativeWebView(parent)
    {
    }

    InteractiveWebKit::~InteractiveWebKit() {

    }

    QML_DECLARE_TYPE(InteractiveWebKit);
    @

    InteractiveWebKit.h

    @#ifndef EXAMPLEITEM_H
    #define EXAMPLEITEM_H

    #include <QtCore/QObject>
    #include <QtCore/QString>
    #include <QtCore/QTimer>
    #include <QDeclarativeItem>
    #include <qdeclarativewebview_p.h>

    class InteractiveWebKit : public QDeclarativeWebView
    {
    Q_OBJECT

    public:
    InteractiveWebKit(QDeclarativeItem *parent = 0);
    virtual ~InteractiveWebKit();

    Q_INVOKABLE void focusView() { page()->view()->setFocus(); }
    

    private:
    Q_DISABLE_COPY(InteractiveWebKit)
    };

    #endif // EXAMPLEITEM_H
    @



  • Hi,

    This sounds like a bug -- when WebView gains focus it should assign correct "subfocus", regardless of whether focus was obtained via mouse or keyboard. I'd suggest logging a bug at http://webkit.org/new-qtwebkit-bug with a small example to reproduce the issue.

    Regards,
    Michael



  • Thanks for the reply. It does seem like a bug. I do need a work-around for now as I have a demo to prove this functionality by the end of this week. I think the best approach is to extend the QDeclarativeWebView class and add a simple function to put the focus on the GraphicsView.

    The code I am using is posted above.

    I do get this error when executing:

    plugin cannot be loaded for module "GtTools": Cannot load library /home/townsendg/projects/GtTools-build-desktop/libGtTools.so: (/home/townsendg/projects/GtTools-build-desktop/libGtTools.so: undefined symbol: _ZN19QDeclarativeWebView17componentCompleteEv)

    I am using the 4.7.1 release SDK for Linux 32bit. I did not build from source, but used the SDK binary which came with QtCreator.

    Here is my project file:

    @TEMPLATE = lib
    TARGET = GtTools
    QT += declarative webkit
    CONFIG += debug warn_on qt plugin shared

    TARGET = $$qtLibraryTarget($$TARGET)

    INCLUDEPATH = /home/townsendg/sdk/qtsdk-2010.05/qt/src/3rdparty/webkit/WebKit/qt/declarative

    Input

    SOURCES +=
    GtTools.cpp
    InteractiveWebKit.cpp

    OTHER_FILES=qmldir

    HEADERS +=
    GtTools.h
    InteractiveWebKit.h
    @

    and LDD

    @townsendg@firefly:~/projects/WebKit$ ldd imports/GtTools/libGtTools.so
    linux-gate.so.1 => (0xb78e2000)
    libQtDeclarative.so.4 => /home/townsendg/sdk/qtsdk-2010.05/qt/lib/libQtDeclarative.so.4 (0xb7575000)
    libQtScript.so.4 => /home/townsendg/sdk/qtsdk-2010.05/qt/lib/libQtScript.so.4 (0xb72bd000)
    libQtSvg.so.4 => /home/townsendg/sdk/qtsdk-2010.05/qt/lib/libQtSvg.so.4 (0xb7261000)
    libQtSql.so.4 => /home/townsendg/sdk/qtsdk-2010.05/qt/lib/libQtSql.so.4 (0xb721f000)
    libQtXmlPatterns.so.4 => /home/townsendg/sdk/qtsdk-2010.05/qt/lib/libQtXmlPatterns.so.4 (0xb6d6d000)
    libQtOpenGL.so.4 => /home/townsendg/sdk/qtsdk-2010.05/qt/lib/libQtOpenGL.so.4 (0xb6c7e000)
    libQtNetwork.so.4 => /home/townsendg/sdk/qtsdk-2010.05/qt/lib/libQtNetwork.so.4 (0xb6b41000)
    libQtWebKit.so.4 => /home/townsendg/sdk/qtsdk-2010.05/qt/lib/libQtWebKit.so.4 (0xb57e0000)
    libQtGui.so.4 => /home/townsendg/sdk/qtsdk-2010.05/qt/lib/libQtGui.so.4 (0xb4c71000)
    libQtCore.so.4 => /home/townsendg/sdk/qtsdk-2010.05/qt/lib/libQtCore.so.4 (0xb4993000)
    libpthread.so.0 => /lib/libpthread.so.0 (0xb4962000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb4877000)
    libm.so.6 => /lib/libm.so.6 (0xb4850000)
    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb4834000)
    libc.so.6 => /lib/libc.so.6 (0xb46d6000)
    libGL.so.1 => /usr/lib/nvidia-current/libGL.so.1 (0xb460d000)
    libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0xb4596000)
    libdl.so.2 => /lib/libdl.so.2 (0xb4591000)
    libXrender.so.1 => /usr/lib/libXrender.so.1 (0xb4587000)
    libfontconfig.so.1 => /usr/lib/libfontconfig.so.1 (0xb4557000)
    libz.so.1 => /lib/libz.so.1 (0xb4542000)
    libXext.so.6 => /usr/lib/libXext.so.6 (0xb4532000)
    libX11.so.6 => /usr/lib/libX11.so.6 (0xb4415000)
    libphonon.so.4 => /home/townsendg/sdk/qtsdk-2010.05/qt/lib/libphonon.so.4 (0xb43b7000)
    libQtDBus.so.4 => /home/townsendg/sdk/qtsdk-2010.05/qt/lib/libQtDBus.so.4 (0xb432e000)
    libQtXml.so.4 => /home/townsendg/sdk/qtsdk-2010.05/qt/lib/libQtXml.so.4 (0xb42e3000)
    libgthread-2.0.so.0 => /usr/lib/libgthread-2.0.so.0 (0xb42de000)
    librt.so.1 => /lib/librt.so.1 (0xb42d5000)
    libglib-2.0.so.0 => /lib/libglib-2.0.so.0 (0xb4205000)
    libgobject-2.0.so.0 => /usr/lib/libgobject-2.0.so.0 (0xb41c3000)
    libSM.so.6 => /usr/lib/libSM.so.6 (0xb41ba000)
    libICE.so.6 => /usr/lib/libICE.so.6 (0xb41a1000)
    /lib/ld-linux.so.2 (0xb78e3000)
    libnvidia-tls.so.260.19.06 => /usr/lib/nvidia-current/tls/libnvidia-tls.so.260.19.06 (0xb419f000)
    libnvidia-glcore.so.260.19.06 => /usr/lib/nvidia-current/libnvidia-glcore.so.260.19.06 (0xb2b01000)
    libexpat.so.1 => /lib/libexpat.so.1 (0xb2ada000)
    libxcb.so.1 => /usr/lib/libxcb.so.1 (0xb2ac0000)
    libpcre.so.3 => /lib/libpcre.so.3 (0xb2a8b000)
    libuuid.so.1 => /lib/libuuid.so.1 (0xb2a85000)
    libXau.so.6 => /usr/lib/libXau.so.6 (0xb2a81000)
    libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0xb2a7b000)
    @

    Execution:

    @townsendg@firefly:~/projects/WebKit$ QML_IMPORT_TRACE=1 /home/townsendg/sdk/qtsdk-2010.05/qt/bin/qmlviewer WebKit.qml -I imports
    QDeclarativeImportDatabase::addImportPath "/home/townsendg/sdk/qtsdk-2010.05/qt/imports"
    QDeclarativeImportDatabase::addImportPath "/home/townsendg/sdk/qtsdk-2010.05/qt/bin"
    QDeclarativeImportDatabase::addImportPath "imports"
    QDeclarativeImportDatabase::addToImport 0x99048c4 "." -1.-1 File as ""
    QDeclarativeImportDatabase::addToImport 0x99048c4 "Qt" 4.7 Library as ""
    QDeclarativeImportDatabase::addToImport 0x99048c4 "QtWebKit" 1.0 Library as ""
    QDeclarativeImportDatabase::add: loaded "/home/townsendg/sdk/qtsdk-2010.05/qt/imports/QtWebKit/qmldir"
    QDeclarativeImportDatabase::importPlugin "QtWebKit" from "/home/townsendg/sdk/qtsdk-2010.05/qt/imports/QtWebKit/libqmlwebkitplugin.so"
    QDeclarativeImportDatabase::addToImport 0x99048c4 "GtTools" 1.0 Library as ""
    QDeclarativeImportDatabase::add: loaded "/home/townsendg/projects/WebKit/imports/GtTools/qmldir"
    QDeclarativeImportDatabase::importPlugin "GtTools" from "/home/townsendg/projects/WebKit/imports/GtTools/libGtTools.so"
    file:///home/townsendg/projects/WebKit/WebKit.qml:3:1: plugin cannot be loaded for module "GtTools": Cannot load library /home/townsendg/projects/GtTools-build-desktop/libGtTools.so: (/home/townsendg/projects/GtTools-build-desktop/libGtTools.so: undefined symbol: _ZN19QDeclarativeWebView17componentCompleteEv)
    import GtTools 1.0
    ^ @



  • It looks like the shared library and the source are not the same. I copied the qdeclarativewebview_p.h and qdeclarativewebview.cpp into my own plugin projected and made the following changes:

    In qdeclarativewebview_p.h I added the following to QDeclarativeWebView class:

    @
    Q_INVOKABLE void viewFocus();
    @

    In qdeclarativewebview.cpp I added the following to QDeclarativeWebView class:

    @
    void QDeclarativeWebView::viewFocus() {
    if (d && d->view) {
    d->view->setFocus();
    }
    }
    @

    I called this component WebView2 in my Plugin registerTypes

    @ qmlRegisterType<QDeclarativeWebView>(uri, 1, 0, "WebView2");@

    In my qml I added:

    @ onActiveFocusChanged: {
    if (activeFocus) {
    web.viewFocus();
    }
    }@

    Now it works as expected. I really had adding a work around, especially in the private headers protecting me from working on different platforms.

    Is there a better way to do this?



  • I found a better way:

    In qdeclarativewebview.cpp I added setFocusProxy(d->view) in the init method:

    @void QDeclarativeWebView::init()
    {
    d = new QDeclarativeWebViewPrivate(this);

    QWebSettings::enablePersistentStorage();
    
    setAcceptedMouseButtons(Qt::LeftButton);
    setFlag(QGraphicsItem::ItemHasNoContents, true);
    setClip(true);
    
    d->view = new GraphicsWebView(this);
    d->view->setResizesToContents(true);
    QWebPage* wp = new QDeclarativeWebPage(this);
    setPage(wp);
    setFocusProxy(d->view);
    connect(d->view, SIGNAL(geometryChanged()), this, SLOT(updateDeclarativeWebViewSize()));
    connect(d->view, SIGNAL(doubleClick(int, int)), this, SIGNAL(doubleClick(int, int)));
    connect(d->view, SIGNAL(scaleChanged()), this, SIGNAL(contentsScaleChanged()));
    

    }@

    Still looking for the best way to have the view be the focus without changing the SDK and being at the mercy of future releases.



  • [quote author="mbrasser" date="1292308495"]Hi,

    This sounds like a bug -- when WebView gains focus it should assign correct "subfocus", regardless of whether focus was obtained via mouse or keyboard. I'd suggest logging a bug at http://webkit.org/new-qtwebkit-bug with a small example to reproduce the issue.

    Regards,
    Michael[/quote]

    Thanks! I added the bug here: https://bugs.webkit.org/show_bug.cgi?id=51094

    Do you have a suggested work around until the feature is added or bug is fixed?



  • [quote author="Gary_" date="1292390734"]Do you have a suggested work around until the feature is added or bug is fixed?[/quote]

    I can't see any easy workarounds (though I'm definitely not a WebView expert) -- from what I can see an approach like yours above (relying on or modifying private classes) is unfortunately needed for now.

    Regards,
    Michael


Log in to reply