在MS Windows上重新使用GTK +中不同父级的模态对话框 - 损坏的焦点

时间:2011-06-22 11:11:33

标签: c windows gtk

我正在重用GTK +中的模态对话框 - 我使用gtk_window_set_transient_for设置它的父对话框,运行它,然后将其父级重置为另一个对话框并再次运行它。

在Linux上一切都很好但是在MS Windows上第二次显示此对话框时,所有GTK窗口都混淆了哪一个是活动的。

这是一个测试程序:

#include <gtk/gtk.h>

GtkWidget* main_window;

void run_reused_dialog(
    GtkWidget* reused_dialog,
    const gchar *parent_title,
    const gchar *reused_dialog_title
) {
    GtkWidget* parent_dialog = gtk_dialog_new_with_buttons(
        parent_title,
        GTK_WINDOW(main_window),
        GTK_DIALOG_MODAL,
        GTK_STOCK_OK,
        GTK_RESPONSE_ACCEPT,
        NULL
    );
    gtk_container_add(
        GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(parent_dialog))),
        gtk_label_new(parent_title)
    );
    gtk_widget_show_all(parent_dialog);
    gtk_dialog_run(GTK_DIALOG(parent_dialog));

    gtk_window_set_transient_for(GTK_WINDOW(reused_dialog),GTK_WINDOW(parent_dialog));
    gtk_window_set_title(GTK_WINDOW(reused_dialog), reused_dialog_title);
    GtkWidget* reused_dialog_label = gtk_label_new(GTK_WINDOW(reused_dialog)->title);
    gtk_container_add(
        GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(reused_dialog))),
        reused_dialog_label
    );
    gtk_widget_show_all(reused_dialog);
    gtk_dialog_run(GTK_DIALOG(reused_dialog));
    gtk_widget_hide(reused_dialog);
    gtk_container_remove(
        GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(reused_dialog))),
        reused_dialog_label
    );
    gtk_widget_hide(parent_dialog);
    gtk_widget_destroy(parent_dialog);
}

int main(int argc, char *argv[])
{
    gtk_init(&argc, &argv);
    main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(main_window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
    gtk_widget_show_all(main_window);

    /* This is a dialog which will be reused */
    GtkWidget* reused_dialog = gtk_dialog_new_with_buttons(
        "Reused dialog",
        GTK_WINDOW(main_window),
        GTK_DIALOG_MODAL,
        GTK_STOCK_OK,
        GTK_RESPONSE_ACCEPT,
        NULL
    );
    gtk_container_add(
        GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(reused_dialog))),
        gtk_label_new(GTK_WINDOW(reused_dialog)->title)
    );

    /* Show first dialog which will display reused dialog */
    run_reused_dialog(
        reused_dialog,
        "First dialog. Click OK to display reused dialog",
        "Reused dialog. Click OK to close"
    );

    /* Show second dialog which will display reused dialog */
    run_reused_dialog(
        reused_dialog,
        "Second dialog. Click OK to display reused dialog",
        "Reused dialog. Switch to another application and switch back"
    );

    gtk_main();
    return 0;
}

当显示“重用对话框。切换到另一个应用程序并切换回”对话框时,它会忽略鼠标,但会对键盘输入作出反应。有时切换到另一个应用程序并返回会触发此问题。


问题:

  1. 我做错了什么或是Windows GTK端口的错误?

  2. 如何在不使用每次使用对话框的情况下解决此问题?

  3. 我是否可以重复使用GTK对话框?


  4. 示例程序源和带有所需GTK库的已编译可执行文件是here。这是使用i686-pc-mingw32-gcc gtk-reused-dialog.c $(mingw32-pkg-config --cflags --libs gtk+-2.0) -mwindows在Fedora Linux 15上使用mingw32-gtk2包进行交叉编译,并安装了它的依赖项。

1 个答案:

答案 0 :(得分:1)

这是我的猜测:

  1. 问题与焦点攫取有关;
  2. 窗口小部件仅在模态标志changes its state;
  3. 时调用抓取API
  4. 平台之间的差异主要是由于实施细节;
  5. 你不能只有一个模态窗口。
  6. 当您显示reused_dialog时,不清楚哪个对话框是模态的(parent_window仍然存在)。

    正确的解决方案:我怀疑如果您重构代码以从回调中显示reused_dialog(例如,使用response信号),您将获得所需的结果,因为这是< em>通常方式™。

    如果您不想重构,可以尝试其中一种解决方案/解决方案(大致按照我认为更好的顺序):

    • 在运行之前始终取消激活reused_dialog的模态状态; gtk_dialog_run() will set it再次触发请求:

      ...
      gtk_window_set_modal(GTK_WINDOW(reused_dialog), FALSE);
      gtk_dialog_run(GTK_DIALOG(reused_dialog));
      ...
      
    • 在运行之前手动抓住焦点reused_dialog

      ...
      gtk_grab_add(reused_dialog);
      gtk_dialog_run(GTK_DIALOG(reused_dialog));
      ...
      
    • 运行后停用parent_window的模态状态:

      ...
      gtk_dialog_run(GTK_DIALOG(parent_dialog));
      gtk_window_set_modal(GTK_WINDOW(parent_dialog), FALSE);
      ...