[Solved] Sending simulated key events through QX11EmbedContainer



  • Hi everyone! I have a "server"(the qx11embedcontainer) and a client(qx11embedwidget) and using Qt 4.8.1.

    Embedding the client works fine, except for when I try to send programmed key events from the server to the client. When I click my "tab" button on the server side, it changes focus each time until it reaches the _container for xembed. If the container has focus, when I now post a tab key event this event will be sent to the client.

    When the client receives a key event from this post and print the key value, it will always be the last key value I pressed on my keyboard when the client had focus. The KeyPress and KeyRelease on my keyevents are ignored as well and seems be the the last one from the keyboard.

    That is the programmed key event from my "tab" button will be received, but it's value will be something it shouldn't.

    Have anyone got an idea what is wrong with this code?

    // Server
    @class Test : public QWidget
    {
    Q_OBJECT
    public:
    Test() : QWidget( 0 )
    {
    QVBoxLayout *l = new QVBoxLayout( this );

    _container = new QX11EmbedContainer();
    _container->setFocusPolicy(Qt::StrongFocus);
    _winId = new QLineEdit();
    _winId->setFocusPolicy(Qt::StrongFocus);

    QPushButton *b = new QPushButton( "Embed" );
    b->setFocusPolicy(Qt::StrongFocus);

    QPushButton *tab = new QPushButton( "Tab" );
    tab->setFocusPolicy(Qt::NoFocus);

    l->addWidget( _container );
    l->addWidget( _winId );
    l->addWidget( b );
    l->addWidget(tab);

    setLayout( l );

    connect( tab, SIGNAL( pressed() ),
    this, SLOT( slotPressedTab() ) );
    connect( tab, SIGNAL( released() ),
    this, SLOT( slotReleasedTab() ) );

    connect( b, SIGNAL( clicked() ),
    this, SLOT( embed() ) );

    connect( _container, SIGNAL( error( QX11EmbedContainer::Error ) ),
    this, SLOT( error( QX11EmbedContainer::Error ) ) );
    }

    private slots:
    void slotPressedTab() {
    QCoreApplication::postEvent(this->focusWidget(), new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Tab, 0, 0));
    }
    void slotReleasedTab() {
    QCoreApplication::postEvent(this->focusWidget(), new QKeyEvent(QKeyEvent::KeyRelease, Qt::Key_Tab, 0, 0));
    }

    void embed() {
    WId id = _winId->text().toInt(0,10);//.toUInt( 0, 16 ); // note: base 16!
    std::cout << "THE ID IS:" << id << std::endl;
    _container->embedClient( id );
    }

    void error( QX11EmbedContainer::Error err ) {
    QMessageBox::warning( this, "Error", QString::number( err ) );
    }

    private:
    QX11EmbedContainer *_container;
    QLineEdit *_winId;
    };@

    // Client
    @class MyWindow : public QX11EmbedWidget {
    Q_OBJECT
    public:
    MyWindow(QWidget* parent=0) : QX11EmbedWidget(parent) {
    isEmbedded = false;
    setFixedSize(QSize(200,200));

    label = new QLabel();
    label->setText(QString("test test test"));

    lineEdit = new QLineEdit();

    QPushButton* button = new QPushButton();

    QHBoxLayout *layout = new QHBoxLayout(this);

    layout->addWidget(label);
    layout->addWidget(lineEdit);
    layout->addWidget(button);

    qDebug("window id:%lu", winId());
    };
    QLabel *label;
    QLineEdit *lineEdit;

    bool eventFilter(QObject *object, QEvent *event) {
    if (event->type() == QEvent::KeyPress) {
    QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
    qDebug("another key in event pressed filter: %i", keyEvent->key());
    }
    } else if (event->type() == QEvent::KeyRelease) {
    QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
    qDebug("another key in event release filter: %i", keyEvent->key());
    }

    return QX11EmbedWidget::eventFilter(object, event);
    }@

    Note I haven't added the error signal slots and such here for convenience but they are not printing any errors.



  • Okay I found that the QX11EmbedContainer don't really handle simulated key presses well. At least not Qt simulated key presses. In the x11EventFilter used for the widget it stores X11 key presses in a variable called lastkeyevent.

    Then it calls the event function of the widget which will reach the eventFilter first and there it uses the lastkeyevent variable that was stored earlier and transfer it there. So If I simulate a Qt key press it will reach the eventFilter but there it will use the lastkeyevent which is only X11 key presses so it will not send my simulated qt key.

    I now simply simulate x11 key presses to the main program and then it handle everything as it should after that.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Glad you found a solution and thanks for sharing.

    Can you also update the thread title prepending [solved] ? So other forum users may know a solution has been found :)



  • Ah of course I didn't think about that! Changed it to solved now.


Log in to reply
 

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