退出分叉窗口管理器后,无法在GtkEntry中键入内容

时间:2015-02-02 21:55:19

标签: c linux gtk gtk3 display-manager

更新:我认为这不是GtkEntry特有的,但更多的是键盘输入本身没有被发送到程序(不再触发键事件)。

我正在做一名显示经理。我在Arch Linux上进行测试。这个想法是当用户输入他们的凭证并按Enter键时,显示管理器会分叉并启动他们~/.xinitrc中指定的窗口管理器。我使用Awesome WM作为窗口管理器进行测试。当用户退出窗口管理器时,显示管理器应该返回控制权,以便用户可以再次登录。

问题是,在用户退出窗口管理器后,显示了显示管理器,但我无法再键入GtkEntry框。我可以突出显示文本甚至右键单击并剪切和粘贴,但我无法输入。我在下面做了一个简化的例子。请注意,如果不是启动窗口管理器而是启动类似sleep命令的操作,那么一切正常。

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

#include <gtk/gtk.h>

#define ENTER_KEY    65293

static pthread_t login_thread;

static void* login_func(void *data) {
    pid_t child_pid = fork();
    if (child_pid == 0) {
        execl("/bin/bash", "/bin/bash", "--login", "/home/gulshan/.xinitrc", NULL); // This doesn't work
        // execl("/usr/bin/awesome", "/usr/bin/awesome", NULL); // This doesn't work
        // execl("/usr/bin/sleep", "/usr/bin/sleep", "5", NULL); // This works
        printf("exec error");
        exit(1);
    }

    // Wait for child process to finish
    int status;
    waitpid(child_pid, &status, 0);

    printf("Returning from login_func\n");
    return NULL;
}

static gboolean key_event(GtkWidget *widget, GdkEventKey *event) {
    if (event->keyval == ENTER_KEY) {
        pthread_create(&login_thread, NULL, login_func, (void*) widget);
    }
    return FALSE;
}

int main(int argc, char *argv[]) {
    gtk_init(&argc, &argv);

    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    gtk_container_add(GTK_CONTAINER(window), gtk_entry_new());
    gtk_widget_show_all(window);

    g_signal_connect(window, "key-release-event", G_CALLBACK(key_event), NULL);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_main();

    return 0;
}

以下是我编译代码的方法:

gcc `pkg-config --cflags --libs gtk+-3.0` -Wall -o test test.c

要测试此代码,我首先运行:

Xephyr -ac -br -noreset -screen 800x600 :1

这会在我可用于测试的窗口中启动X服务器。然后我用

启动代码
DISPLAY=:1 ./test

在Xephyr窗口中启动它。如果您退出显示管理器(在Awesome中,您可以右键单击并单击&#34;退出&#34;),您将看到您无法再在文本框中输入内容。

1 个答案:

答案 0 :(得分:0)

我认为你不应该混合线程和叉子,请参阅threads-and-fork-think-twice-before-using-them

我修改了你的代码:

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

#include <gtk/gtk.h>

#define ENTER_KEY    65293

static pthread_t login_thread;

static void* login_func(void *data) {
    pid_t child_pid = fork();
    if (child_pid == 0) {
        execl("/usr/bin/awesome", "/usr/bin/awesome", NULL); // This doesn't work
        printf("exec error");
        exit(1);
    }

    // Wait for child process to finish
    int status;
    waitpid(child_pid, &status, 0);

    printf("Returning from login_func\n");
    return NULL;
}

static gboolean key_event(GtkWidget *widget, GdkEventKey *event) {
    if (event->keyval == ENTER_KEY) {
      login_func((void *) widget);
    }
    return FALSE;
}

int main(int argc, char *argv[]) {
    gtk_init(&argc, &argv);

    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    gtk_container_add(GTK_CONTAINER(window), gtk_entry_new());
    gtk_widget_show_all(window);

    g_signal_connect(window, "key-release-event", G_CALLBACK(key_event), NULL);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_main();

    return 0;
}

正如您所看到的,我刚刚删除了该主题。现在当我从Awesome注销时,我可以输入gtk条目。