Linux,execl(),为什么我丢失了应用程序的键盘输入?

时间:2011-05-11 12:22:56

标签: linux qt keyboard exec

我的Linux程序的名称类似于MyProgram_0001,较新版本的数字更高。启动时,应用程序在同一目录中查找较新版本,如果找到,则通过execl()调用它。这很好用,但是当鼠标继续工作时,即使我事先在其窗口中单击,新版本也不会获得任何键盘输入。调用应用程序已经消失,其他正在运行的程序继续获得键盘输入...任何想法?实际上该程序是用C ++ Qt Designer 4.7应用程序编写的,但这应该不重要,或者可能是:-)?

好的,还有更多信息......这是捕获密钥并调用我的SLOT的代码......

// define my own event handler
// capture all key presses ...
bool Layout10::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::KeyPress)
    {
        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);

        // directly exit on Alt-keys
        if (keyEvent->modifiers()&Qt::AltModifier) return true;

        // normal keyboard
        if ((!(keyEvent->modifiers()&Qt::KeypadModifier))&&(Keyboard_On)) switch (keyEvent->key())
        {
            case Qt::Key_0:         C->Num0ButtonClicked_KP(); return true;
            case Qt::Key_1:         C->Num1ButtonClicked_KP(); return true;
            case Qt::Key_2:         C->Num2ButtonClicked_KP(); return true;
            case Qt::Key_3:         C->Num3ButtonClicked_KP(); return true;
            case Qt::Key_4:         C->Num4ButtonClicked_KP(); return true;
            case Qt::Key_5:         C->Num5ButtonClicked_KP(); return true;
            case Qt::Key_6:         C->Num6ButtonClicked_KP(); return true;
            case Qt::Key_7:         C->Num7ButtonClicked_KP(); return true;
            case Qt::Key_8:         C->Num8ButtonClicked_KP(); return true;
            case Qt::Key_9:         C->Num9ButtonClicked_KP(); return true;
            case Qt::Key_X:         C->XButtonClicked_KP();    return true;
            case Qt::Key_Backspace: C->EButtonClicked_KP();    return true;
            case Qt::Key_F1:        C->F1ButtonClicked_KP();   return true;
            case Qt::Key_F2:        C->F2ButtonClicked_KP();   return true;
            case Qt::Key_F3:        C->F3ButtonClicked_KP();   return true;
        }

        // keypad
        if ((keyEvent->modifiers()&Qt::KeypadModifier)&&(Keypad_On)) switch (keyEvent->key())
        {
            case Qt::Key_0:         C->Num0ButtonClicked_KP(); return true;
            case Qt::Key_Insert:    C->Num0ButtonClicked_KP(); return true;
            case Qt::Key_1:         C->Num1ButtonClicked_KP(); return true;
            case Qt::Key_End:       C->Num1ButtonClicked_KP(); return true;
            case Qt::Key_2:         C->Num2ButtonClicked_KP(); return true;
            case Qt::Key_Down:      C->Num2ButtonClicked_KP(); return true;
            case Qt::Key_3:         C->Num3ButtonClicked_KP(); return true;
            case Qt::Key_PageDown:  C->Num3ButtonClicked_KP(); return true;
            case Qt::Key_4:         C->Num4ButtonClicked_KP(); return true;
            case Qt::Key_Left:      C->Num4ButtonClicked_KP(); return true;
            case Qt::Key_5:         C->Num5ButtonClicked_KP(); return true;
            case Qt::Key_Clear:     C->Num5ButtonClicked_KP(); return true;
            case Qt::Key_6:         C->Num6ButtonClicked_KP(); return true;
            case Qt::Key_Right:     C->Num6ButtonClicked_KP(); return true;
            case Qt::Key_7:         C->Num7ButtonClicked_KP(); return true;
            case Qt::Key_Home:      C->Num7ButtonClicked_KP(); return true;
            case Qt::Key_8:         C->Num8ButtonClicked_KP(); return true;
            case Qt::Key_Up:        C->Num8ButtonClicked_KP(); return true;
            case Qt::Key_9:         C->Num9ButtonClicked_KP(); return true;
            case Qt::Key_PageUp:    C->Num9ButtonClicked_KP(); return true;
            case Qt::Key_Back:      C->XButtonClicked_KP();    return true; // maybe it should have been backslash ?
            case Qt::Key_Delete:    C->EButtonClicked_KP();    return true;
            case Qt::Key_division:  C->F1ButtonClicked_KP();   return true;
            case Qt::Key_multiply:  C->F2ButtonClicked_KP();   return true;
            case Qt::Key_Minus:     C->F3ButtonClicked_KP();   return true;
        }
        return true; // event is NOT given over for further processing
    }
    else
    {
        return false; // other events may be processed further
    }
}

Keyboard_On只是该类的公共布尔成员,如果向用户显示触摸屏,我将用它来禁用键盘。上面的消息处理程序安装如下......

this->installEventFilter(this);

...在widget类的构造函数中...我有一个这样的处理程序用于构成我的对话框的所有窗口小部件......嗯,除非我通过execl或{{从它自己启动应用程序,否则它是有效的1}} ...

有一件事引起了我对startDetached()的描述的注意......他们写道,新进程在自己的环境中运行,行为就像Linux下的守护进程。我想知道这是不是我放松钥匙的原因......

真的这让我很困惑。键盘必须通过一些层链,还有一种方法可以调试,看看我放松了什么级别?谢谢!

更多信息...如果我通过execl调用完全相同的二进制文件,我发现我没有松开键盘。如果我将该二进制文件复制到另一个名称并调用它...键盘就不见了。它归结为execl调用中的单个字母更改,仅在第二个参数中,所有其他相同的错误仍然发生...似乎有一些上下文如果路径+二进制相同,则保持不变,但是否则密钥被发送到旧的上下文,通过execl调用的文件在不同的上下文中启动...

2 个答案:

答案 0 :(得分:0)

许多应用程序通过以运行二进制文件的shell脚本而不是二进制文件本身来处理此类问题。 Firefox就是这么做的。您可以在脚本中执行“最新版本”检查。

答案 1 :(得分:0)

我很好奇:你在致电execl之前是否进行了任何清理工作?你是在Qt事件循环中调用它还是先退出它?

execve(2)函数(execl(3) is a wrapper of)执行了多种interesting stuff,其中包含调用过程的状态,我对此印象深刻,甚至可以在以后工作:

  

execve()在成功时不返回,并且调用进程的text,data,bss和stack将被加载的程序覆盖。调用的程序继承了调用进程的PID,以及未设置为在exec上关闭的任何打开的文件描述符。将清除呼叫进程中待处理的信号。设置为由调用进程捕获的任何信号都将重置为其默认行为。 SIGCHLD信号(设置为SIG_IGN时)可能会也可能不会重置为SIG_DFL。

其中一些可能会破坏Qt或X服务器状态的内部或其他完全。对于Qt来说,一切似乎都是从头开始。对于其他人来说,这是一个相同的过程。

如果在“切换”之前清理所有内容,为什么要重复使用相同的过程?请改用QProcess::startDetached()

编辑。您的上一句话是无条件阻止按键。如果仅当Keyboard_On或Keypad_On为真时才应锁定键盘,则最后一条语句:

 return true; // event is NOT given over for further processing

实际应该是return false。您只会在应用重新启动时注意到这一点,因为可能只有较新版本的应用会丢弃关键事件。