LINUX.ORG.RU

GTK+ и ресайз


0

0

Всем привет. Есть вот такая програмка, демонстрирующая поведение GTK+ при изменении размера контейнера (в данном случае GtkWindow):

#include <gtk/gtk.h>

static void
window_resize_cb (GtkWidget *window, GtkAllocation *allocation, gpointer data)
{
  g_message ("window: new size %dx%d", allocation->width, allocation->height);
}

static void
button_resize_cb (GtkWidget *window, GtkAllocation *allocation, gpointer data)
{
  g_message ("button: new size %dx%d", allocation->width, allocation->height);
}

static void
window_size_request_cb (GtkWidget *window, GtkRequisition *requisition, gpointer data)
{
  g_message ("window: request size %dx%d", requisition->width, requisition->height);
}

static void
button_size_request_cb (GtkWidget *window, GtkRequisition *requisition, gpointer data)
{
  g_message ("button: request size %dx%d", requisition->width, requisition->height);
}

int
main (int argc, char *argv[])
{
  GtkWidget *window, *button;

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_container_set_border_width (GTK_CONTAINER (window), 10);
  g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);

  button = gtk_button_new_with_label ("some label");
  gtk_container_add (GTK_CONTAINER (window), button);

  g_signal_connect (G_OBJECT (window), "size-allocate",
		    G_CALLBACK (window_resize_cb), NULL);
  g_signal_connect (G_OBJECT (button), "size-allocate",
		    G_CALLBACK (button_resize_cb), NULL);
  g_signal_connect (G_OBJECT (window), "size-request",
		    G_CALLBACK (window_size_request_cb), NULL);
  g_signal_connect (G_OBJECT (button), "size-request",
		    G_CALLBACK (button_size_request_cb), NULL);

  gtk_widget_show_all (window);

  gtk_main ();
  return 0;
}

Собираем так: gcc -Wall -pedantic `pkg-config --cflags --libs gtk+-2.0` resizing.c -o resizing

Запускаем:

.$ ./resizing 
** Message: button: request size 74x29
** Message: window: request size 94x49
** Message: button: new size 74x29
** Message: window: new size 94x49

-- здесь вопросов нету. Теперь делаем разовый ресайз окна средствами WM --

** Message: window: request size 94x49
** Message: button: new size 84x29
** Message: window: new size 104x49
** Message: window: request size 94x49
** Message: window: new size 104x49

Вот здесь начинаются вопросы.
Насколько мне известно, для вычисления новых размеров компонентов внутри контейнера,
контейнер рекурсивно запрашивает *желаемые* размеры "детей" (структура GtkRequisition). Это стадия 1.
Потом происходит фактическое выделение размеров (структура GtkAllocation). Это стадия 2.
В нормальных условиях, если свойство "resizable" окна не установлено в FALSE, то реальные размеры компонентов будут такими, какими они были на стадии 1.

Мы же видим следующее:
> ** Message: window: request size 94x49
Окно запрашивает старый размер
> ** Message: button: new size 84x29
Кнопка получает новый размер
> ** Message: window: new size 104x49
Окно получает новый размер
> ** Message: window: request size 94x49
Окно запрашивает старый размер и ...
> ** Message: window: new size 104x49
... получает новый.

Какая-то ерунда получается.
У меня есть подозрение, что я как-то неправильно полагаюсь на сигналы size-request и size-allocate,
хотя даже при этом условии как-то всё происходит странно.

Если кто-то в этом что-то понимает, поясните, плиз.
★★★★

>> ** Message: window: request size 94x49 >Окно запрашивает старый размер

Если callback выполняется до вызова собственно метода size_request, цифры будут неправильными. Если вопрос о цифрах, конечно.

welkam ★★
()
Ответ на: комментарий от welkam

> Если callback выполняется до вызова собственно метода size_request, цифры будут неправильными. Если вопрос о цифрах, конечно.

А ты куда этот callback не воткни, всё равно непонятно, зачем после изменения размера окна средствами WM окну запрашивать старый размер.

Bohtvaroh ★★★★
() автор топика
Ответ на: комментарий от welkam

А насчёт того, что WM у top-level окна несколько раз спрашивает размер, да, такое есть. Но объяснить для чего это трудно.

welkam ★★
()
Ответ на: комментарий от welkam

> Кстати, есть --enable-debug=geometry

Точно, спасибо, только это переменная окружения, типа:
$ GTK_DEBUG=geometry ./resizing

Bohtvaroh ★★★★
() автор топика
Ответ на: комментарий от welkam

> А насчёт того, что WM у top-level окна несколько раз спрашивает размер

Это здесь вообще не причём.

size-request - это вычисление размера виджета, в зависимости от выбранной темы, шрифта и т.п.

size-allocate - убеждаемся, что нет никаких препятствий выделить виджету размер, который он заявил в size-request, и выделяем

Я посмотрел в gdb - все цифры отображаются верно, так что тут зарыта какая-то странная логика...

Bohtvaroh ★★★★
() автор топика
Ответ на: комментарий от Bohtvaroh

Мне пришло в голову, что GtkWindow не совсем обычный виджет контейнера. Я добавил GtkHBox и в него положил кнопку, теперь при ресайзе, никаких size-request-ов у бокса или кнопки не происходит, сразу выделяется нужный размер. Предположительно, так и надо...

Bohtvaroh ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.