Get confirmation that a key has reached JS



  • Hi

    I have a strange issue that on every second use of key used to navigate in a webView with JS, it simply does not react on it.
    I've added an event viewer to the webView to filter and debug key events received and it shows the key press as well as the release event coming in.
    So far, everything seems OK as far as I can reach it 'code-wise'.
    How can I be sure the key reaches the JS code to tell where to look for this issue (my code, behavior of webKit, PHP, JS on server ....)?

    Thanks for any input to track this down.
    McL



  • @McLion You can set up handler for keydown or keypress in your JS code and send messages to console



  • Thanks.
    Sounds like a plan ... going to try and post back.



  • @Konstantin-Tokarev

    Should something like the 2 console.log lines below give me some output on the console?
    Excerpt from JS code:

    case(event.keyCode >= 65 && event.keyCode <= 73): /* a..i */
                        var index = 0;
                        var rowNum = event.keyCode - 65;
                        var jBottommenuRows = $(this).children('.row');
                        console.log("JS");
                        console.log(event.keyCode);
    


  • @McLion Yes



  • @Konstantin-Tokarev

    OK, fine. What if there is nothing ... on the very same console all qDebug() perfectly appear?



  • @McLion No, they go to JS console. You can see it in Inspector, or handle QWebPage::javaScriptConsoleMessage signal



  • @Konstantin-Tokarev

    Ahhh ... OK ... Thanks a lot.
    Never saw the 'Inspector' and will try to read it up ... is it also part of webKit in Qt?
    I know the inspector on desktop browser but it won't help because it unfortunately does not show the issue there.
    I'll try (tomorrow) to connect the signal to a slot and use qDebug() in there.



  • @McLion
    Activated the inspector with the following line:
    QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
    Basically works. However, as soon as I have the inspector turned on my webView's do behave very strange, like they do not get all inputs anymore, and I can not debug the situation.

    Looks like I need to implement QWebPage::javaScriptConsoleMessage and send the messages back to C++ and debug from there.
    According docs this is not a signal so I can not simply connect to it.



  • @McLion Right, I've mixed it up with new consoleMessageReceived() signal that is present in revived QtWebKit only (since TP3)



  • @Konstantin-Tokarev
    Need some help ...
    I have the following:
    in h:

    #include <QWebPage>
    class DBGWebPage : public QWebPage
    {
    Q_OBJECT
      public:
        explicit DBGWebPage(QObject *parent = 0);
      protected:
        void javaScriptConsoleMessage( const QString & message, int lineNumber, const QString & sourceID );
    };
    

    in cpp:

    void DBGWebPage::javaScriptConsoleMessage( const QString & message, int lineNumber, const QString & sourceID )
    {
      qDebug() << message << lineNumber << sourceID;
    }
    

    and my webGUI's are derived from qWebView:

    QWebView *webGUI = new QWebView(QTGUI_MainWindow::centralWidget());
    

    How do I make it use the reimplementation of javaScriptConsoleMessage()?



  • @McLion QWebView::setPage



  • @Konstantin-Tokarev
    Thanks .. seems to be too late for today ... I don't get it to build ... dam...



  • @Konstantin-Tokarev
    There's something I don't get ... probably soemthing with these C++ classes I'm always stumbling over:

    #include <QWebPage>
    class DBGWebPage : public QWebPage
    {
    Q_OBJECT
      public:
        explicit DBGWebPage(QObject *parent = 0);
        QWebPage *DebugWebPage;
      protected:
        void javaScriptConsoleMessage( const QString & message, int lineNumber, const QString & sourceID );
    };
    
    DBGWebPage::DBGWebPage(QObject *parent) :
      QWebPage(parent)
    {
      //QWebPage* DebugWebPage = new QWebPage;
      DebugWebPage = new QWebPage(this);
    }
    
    QWebView * QTGUI_MainWindow::CreateNewWebGUI(int iID)
    {
      // check if already existing
      if(webGUIMap.value(iID) != 0) { qDebug("GUI %d existing", iID); return false; }
    
      // check for max GUI count here
      if(iID > GUI_COUNT_MAX) { qDebug("GUI %d failed - Max GUI ID is %d", iID, GUI_COUNT_MAX); return false; }
    
      // create new webGUI and add it to the list
      QWebView *webGUI = new QWebView(QTGUI_MainWindow::centralWidget());
      webGUIMap.insert(iID, webGUI);
    
      // make some basic settings to the new GUI
      webGUI->setPage(DBGWebPage::DebugWebPage);
      webGUI->setObjectName(QString::fromUtf8("webGUI%1").arg(iID));
    ......
    

    Fehler:object missing in reference to 'DBGWebPage::DebugWebPage'



  • This post is deleted!

  • Qt Champions 2016

    Hi
    webGUI->setPage(DBGWebPage::DebugWebPage);
    I would expect be something like
    DBGWebPage *page=new DBGWebPage();
    webGUI->setPage(page->DebugWebPage);

    The other syntax seems odd ?



  • @McLion You derive DBGWebPage from QWebPage and add QWebPage* field to it, then try to use that QWebPage* field (which is vanilla QWebPage, not DBGWebPage) as it was static filed of DBGWebPage.



  • @mrjj
    Thanks.
    In fact, the other syntax seemed wrong.
    You code builds without error, however, crashes with SIGSEGV.



  • @McLion Because it should be

    DBGWebPage *page=new DBGWebPage();
    webGUI->setPage(page);



  • I somehow understand all you're saying, but I so far am not able to modify my code to not crash.
    Currently ended up with (modified to it while Konstantin was writing it too):

    DBGWebPage *page=new DBGWebPage();
    webGUI->setPage(page);
    

    and an empty constructor.
    Still crashing .... I'm stumped.



  • remove DebugWebPage and all code messing with it



  • Found something.
    It actually works if comment 2 signal connects for the page, but I need these two.

    • networkAccessManager for SSL errors
    • and the JS bridge
      If the page has been set, do I need to connect these in a different way or do these now go to the wrong object?
    QWebView * QTGUI_MainWindow::CreateNewWebGUI(int iID)
    {
      // check if already existing
      if(webGUIMap.value(iID) != 0) { qDebug("GUI %d existing", iID); return false; }
    
      // check for max GUI count here
      if(iID > GUI_COUNT_MAX) { qDebug("GUI %d failed - Max GUI ID is %d", iID, GUI_COUNT_MAX); return false; }
    
      // create new webGUI and add it to the list
      QWebView *webGUI = new QWebView(QTGUI_MainWindow::centralWidget());
      webGUIMap.insert(iID, webGUI);
    
      // make some basic settings to the new GUI
    DBGWebPage *page=new DBGWebPage();
    webGUI->setPage(page);
    
      webGUI->setObjectName(QString::fromUtf8("webGUI%1").arg(iID));
    //qDebug() << "New webGUI:" << webGUI;
    //qDebug() << "Map:" << iID << webGUIMap.value(iID);
      webGUI->setStyleSheet(QString::fromUtf8("background-color: rgba(0, 0, 0, 0);"));
      webGUI->setUrl(QUrl("about:blank"));
      webGUI->setRenderHints(QPainter::SmoothPixmapTransform|QPainter::TextAntialiasing);
      webGUI->page()->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
      webGUI->page()->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
      webGUI->setGeometry(0, 0, SCREEN_SIZE_X, SCREEN_SIZE_Y);
      webGUI->setFocusPolicy(Qt::StrongFocus);
      webGUI->setMouseTracking(true);
      webGUI->setAcceptDrops(true);
      webGUIeventFilter *webGUIEvFil = new webGUIeventFilter;
      webGUI->installEventFilter(webGUIEvFil);
      webGUI->hide();
    
      // connect load progress and finished signals
      connect(webGUI, SIGNAL(loadProgress(int)), ui->webGUIChangeProgressBar, SLOT(setValue(int)));
      connect(webGUI, SIGNAL(loadFinished(bool)), this, SLOT(webGUI_loadFinished(bool)));
    
      // prepare adding objects to JavaScript (bridge from JS to native code)
    //  connect(webGUI->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(populateJavaScriptWindowObject()));
    
      // setup SSL error handling
    //  connect(webGUI->page()->networkAccessManager(), SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError> & )),
    //  this, SLOT(HandleGUIsslErrors(QNetworkReply*, const QList<QSslError> & )));
    
      return webGUI;
    }
    


  • @Konstantin-Tokarev
    Did so - all removed.



  • I can not find what I'm doing wrong. The console debug works, as long as I have deactivated the JS bridge.

    DBGWebPage *page=new DBGWebPage();
    webGUI->setPage(page);
    // the following lines that use the new page seem to work
    webGUI->page()->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
    webGUI->page()->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
    // and the following line - that I need - let it crash upon boot:
    connect(webGUI->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(populateJavaScriptWindowObject()));
    

    If I don't use setPage() to change the page that the webView generates by default, the JS bridge works perfectly.
    What am I doing wrong to use the page of my own class with the debug added AND use the JS bridge?



  • Anyone an idea what I'm doing wrong here?
    The code does not crash while connecting. It seems to crashes when the first web page is loaded and the loadProgress or loadFinished signal is sent from the webView.
    Edit/Add:
    On second thought, it probably crashes when the javaScriptWindowObjectCleared() is called the first time.



  • @McLion Throw it in gdb or your debugger of choice and give us a backtrace and we can probably tell ya what the issue is.



  • @ambershark
    Unfortunately, I don't have any debugger running on this eLinux target.



  • @McLion said in Get confirmation that a key has reached JS:

    I can not find what I'm doing wrong. The console debug works, as long as I have deactivated the JS bridge.

    DBGWebPage *page=new DBGWebPage();
    webGUI->setPage(page);
    // the following lines that use the new page seem to work
    webGUI->page()->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
    webGUI->page()->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
    // and the following line - that I need - let it crash upon boot:
    connect(webGUI->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(populateJavaScriptWindowObject()));
    

    If I don't use setPage() to change the page that the webView generates by default, the JS bridge works perfectly.
    What am I doing wrong to use the page of my own class with the debug added AND use the JS bridge?

    @McLion Ok if that's the case you'll need to move to using qDebug() or some sort of cout/logfile debugging to figure out what's going on. If you need a logger for linux you're welcome to use mine at https://github.com/ambershark-mike/sharklog. It's not feature complete yet but is definitely more than usable. I use it in a number of projects.

    Anyway, my guess with your crash is that webGUI or page() or mainFrame() is invalid. One of those is causing the issue almost guaranteed. Assuming the crash is actually on that line. So for instance if you were using my logger you could check it with code like:

    // sorry for the casts to (int) on the pointers, I don't have hex address/pointer support in the logger yet.
    // it's a side project I don't have a ton of time for. :)
    LoggerStream() << "webGUI: " << (int)webGUI << SHARKLOG_END;
    LoggerStream() << "page: " << (int)webGUI->page() << SHARKLOG_END;
    LoggerStream() << "mainFrame: " << (int)webGUI->page()->mainFrame() << SHARKLOG_END;
    

    The reason we do all those logs on a separate line is if any of them are bad they will crash. Put these in before your connect and check which object is bad. Probably a null (0), but potentially it has been deleted. If that is the case and it is a dangling pointer it is going to be harder to find without a debugger.



  • @ambershark
    Oh, I'm using qDebug() a lot since I have a serial console connected to the embedded target that allows me to see everything from Linux and interact with it as well.

    The problem is that from within a JS in webKit there is no qDebug().
    By subclassing webView and reimplementing javaScriptConsoleMessage() every console message in a JS (i.e. console.log("JS keyCode: " + event.keyCode);) can be catched in C++ code and forwarded to the console by using qDebug().
    Actually, this works ... as long as I don't connect the bridge and comment the following:

    // prepare adding objects to JavaScript (bridge from JS to native code)
    connect(webGUI->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(populateJavaScriptWindowObject()));
    

    So, I assume that the object in the connect is the issue because page() is not automatically derived from the webView as it was before and has been changed to page() from my subclass DBGWebPage.

    I just can't see what is wrong with the stuff I'm doing.
    Thanks a lot anyway.



  • @McLion Could you post self-contained project that can be built?



  • @Konstantin-Tokarev
    I'm not sure ... I think that should work if I share all Qt sources in my 'src' folder, does it?

    I am working and developing on Windows with Creator to have the output from the compiler and everything Creator offers. If it builds ok, I switch to my Linux Debian VM and build the ARM code from within the Linux console. The traget gets the code over the LAN directly from my Linux VM by NFS.
    The application can not really be run on windows because there are some hardware components and other stuff that is available on the target only. I mean it runs, but you can't do anything with it on windows.



  • @McLion Run your program with valgrind (e.g. as "valgrind --leak-check=no--track-origins=yes <your_program> <your_program_args...>") and look for memory errors (e.g., invalid reads, writes)



  • Finally coming back to this ... and found the issue :-)

    DBGWebPage *NewPage = new DBGWebPage(webGUI);
    

    The new Page was not a child of the correct object.
    I checked pointers as suggested.
    The connect of the JS bridge showed no issues.
    However, the first call from JS (signal javaScriptWindowObjectCleared() calling my populateJavaScriptWindowObject())
    crashed on

    QWebFrame * webGUIframe = qobject_cast<QWebFrame *>(sender());
    QWebView * webGUI = (QWebView*)(webGUIframe->parent())->parent();
    

    obviously because it was pointing to 'nothing' instead of a QWebView.
    Thank you guys for all the hints.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.