QApplication::focusChanged does not actually report focus events (Qt 4.8)



  • Hi all,
    Any clues here would be much appreciated. I think this needs the help of someone that actually understands the Qt kernel and focus change event processing.

    The situation is basic: I implemented a virtual keyboard for an embedded application (happy to post the whole source if requested) based on the QInputContext example. And in some contexts it seems to work - but in others it doesn't (sorry to be vague about the contexts - I really can't figure out what is different).

    There are two classes:

    1. VirtualKeyboardContext: public QInputContext
    2. VirtualKeyboard: public QWidget (with a ui)

    In short I do the recommended connect:
    @ connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)), keyboard, SLOT(saveFocusWidget(QWidget*,QWidget*)));
    @
    .. I have tried this both in the ctor for VirtualKeyboard or when creating it in VirtualKeyboardContext - as expected, it makes no difference.

    Here is the best description of the works/fails scenario:

    • Works: from the mainwindow (a top level QWidget) create (using new) an intermediary widget with mainwindow as parent and from there, on a button click create another widget for the actual input (with line edits, etc.) with the intermediary for a parent. Then, VirtualKeyboard receives focusChanged signals.
    • Doesn't work: create the input widget directly from mainwindow (no button clicks, eg. with a timer).

    Furthermore, I know from implementing filterEvent() in the VirtualKeyboard that even when it does receive some focusChange signals it doesn't recieve all of them. In the worst case ("Doesn't work") it recieves no signals at all while filterEvent() shows tons of stuff (much of which doesn't make much sense, nameless QObjects, FocusOut with no FocusIn, etc ..).

    Ideas very welcome - If I ever get this ironed out I might be able to release a very simple OSK.



  • Follow up.
    One work around is this - install an eventFilter in the QInputContext derived class (in this case VirtualKeyboardContext). This is crude but seems to work:
    @bool VirtualKeyboardContext::eventFilter(QObject *o, QEvent *e)
    {
    if(! o->isWidgetType())
    return false;

    if(e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut)
    {
        QWidget *w = (QWidget *) o;
        QString class_name =  w->metaObject()->className();
        qDebug() << "Focus widget class: " << class_name;
        if(class_name.contains("Edit"))
        {
            setFocusWidget(w);
            keyboard->setLastFocusWidget(w);
            w->setFocus();
        }
    }
    return false;
    

    }
    @

    However, I still do not understand why QApplication::focusChanged does not actually report all focus changes .. I did notice in qapplication.cpp that the signal is only emitted if the QFocusEvent::reason != Qt::NoFocusReason. I find no documentation of this "Qt::NoFocusReason" but regardless, many focus change events are observable via the eventFilter and QApplication::focusChanged is not emitted for these (at least my widget doesn't receive them). So there's a workaround but the mystery remains ...



  • More clues:
    If the widget that is to receive input (ie. contains an input widget) is not parented at all it then receives focusChanged signals (although still not all of them). This, BTW, is simpler workaround than the above - but it means you cannot parent a window/widget that expects input ..


Log in to reply
 

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