2011-06-22 71 views
4

我在GTK中重複使用模態對話框—我使用gtk_window_set_transient_for設置了它的父對話框,運行它,稍後重置它的父對象到另一個對話框並再次運行它。在MS Windows上GTK +中重複使用模式對話框 - 焦點不對

在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對話框嗎?


樣品節目源,並用所需的GTK庫編譯的可執行文件是here。這是在Fedora Linux 15上使用i686-pc-mingw32-gcc gtk-reused-dialog.c $(mingw32-pkg-config --cflags --libs gtk+-2.0) -mwindowsmingw32-gtk2軟件包進行交叉編譯並安裝了依賴項。

+1

我可以重現問題米打破它的部分是'GTK_DIALOG_MODAL's;如果你刪除其中的一個(在* parent *或* reused *對話框中),代碼工作正常。我很確定這是一個GTK + bug;我沒有看到任何會引發這種行爲的事情。你應該[報告](http://bugzilla.gnome.org/)。 –

回答

1

這是我的猜想:

  1. 問題重點抓有關;
  2. 窗口小部件調用僅在模態標誌changes its state;
  3. 平臺之間的差異主要是由於實現細節;
  4. 你不能只有一個模態窗口。

在你展示reused_dialog的時間,目前尚不清楚該對話框模式(parent_window還活着)。

正確的解決辦法:我想,如果你重構代碼,顯示從回調reused_dialog(使用response信號,例如),你會得到想要的結果,因爲這是™的通常的方式。

如果你不想重構,你可以嘗試以下解決方案/變通辦法之一(大約在我認爲爲了更好):

  • 之前總是disactivate的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); 
    ...