Повторное использование модального диалога с другим родителем в GTK + в MS Windows - разбитый фокус - PullRequest
4 голосов
/ 22 июня 2011

Я повторно использую модальное диалоговое окно в 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?


Пример исходного кода программы и скомпилированного исполняемого файла с необходимыми библиотеками GTK: здесь .Он кросс-компилируется с использованием i686-pc-mingw32-gcc gtk-reused-dialog.c $(mingw32-pkg-config --cflags --libs gtk+-2.0) -mwindows в Fedora Linux 15 с пакетом mingw32-gtk2 и его зависимостями.

1 Ответ

1 голос
/ 26 июня 2011

Это мое предположение:

  1. проблема связана с захватом фокуса;
  2. виджет окна вызывает API захвата только тогда, когда модальный флаг меняет свое состояние ;
  3. различия между платформами в основном связаны с деталями реализации;
  4. вы не можете иметь более одного модального окна.

В момент показа reused_dialog, не ясно, какой диалог является модальным (parent_window все еще жив).

Правильное решение: я подозреваю, если вы реорганизуете свой код, чтобы показать reused_dialog из обратного вызова (используя ответный сигнал , например), вы получите желаемый результат, потому что это обычный способ ™ .

Если вы не хотите проводить рефакторинг, вы можете попробовать один изэти решения / обходные пути (примерно в порядке, который, на мой взгляд, лучше):

  • всегда отключать модальное состояние reused_dialog перед его запуском;gtk_dialog_run() снова установит его , запустив то, что было запрошено:

    ...
    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);
    ...
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...