LINUX.ORG.RU

[gtk] Как выполняется маршрутизация button press/release от GdkWindow до конкретного GtkWidget?

 


0

1

Как известно, Gtk может использовать одно окно графической системы для отображения произвольного дерева виджетов. Когда от окна поступают сообщения типа button press/release, сигнал от GdkWindow пересылается тому GtkWidget, в пределах которого в данный момент находится мышь.

Вот не могу в сорцах gtk найти код, выполняющий эту маршрутизацию. Подскажите, куда копать.

Вообще необязательно одно окно, кнопки например в x11 создают собственные event-only окна внутри окна родительского виджета. Щас так не вспомню, но вроде все события от оконной подсистемы приходят через майнлуп, найди грепом вхождения gdk_event_handler_set(), ему передается callback, оттуда ноги и растут. Все это скорее всего лежит в gtkwidget.c.

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

gtk устанавливает вызовом gdk_event_handler_set() коллбэк на gtk_main_do_event().

gtk_main_do_event() получает от gdk события. Событие содержит поле GkdWindow window. С каждому GkdWindow приязан указатель на виджет, его создавший. Соотвественно gtk_main_do_event() извлекает этот указатель и получает корневой виджет для заданного окна.

Дальше диспетчерезация событий может идти «вниз» и «вверх». Диспетчерезация «вверх» обрабатывается в gtk_propagate_event(): если виджет сам не обрабатывает событие, берем его родительский виджет и пытаемся всучить событие ему. И так в цикле, пока кто-нибудь не обрабатает событие, или пока не достигнем общего корня всего дерева виджетов.

Тут всё ясно.

А вот с обработкой «вниз» — херня. Событие передаётся в gtk_widget_event(). Оттуда дергаются сигналы, соответствующие конкретному типу события. Однако если виджет является контейнером, мы должны попытаться передать событие дальше в дочерний виджет — в тот, который «под мышью». Но вот как именно это происходит? Там я вижу только код для запуска сигнала, но не вижу ничего, относящегося к обработке элементов контейнера.

Хорошо, допустим эта логика обрабатывается не на урвоне события, а на уровне отдельных сигналов. Тогда надо смотреть обработчики сигналов. Но поиск по button_press_event или button-press-event не находит вообще ничего, относящегося к этому вопросу.

Вот такая ерунда...

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

Я не уверен, что такой проброс вниз реализован. Проще всего тебе повеситься на button-press-event нужного виджета и там под гдб сделать аборт. Вообще если такими вещами занимаешься, имеет смысл пересобрать гтк с отладочной информацией.

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

Вот это навевает мне мысль о том, что и правда у каждого интерактивного виджета должно быть свое окно. Я когда свои виджеты делал, всегда создавал для этих целей свои окна, не знаю что меня побуждало именно так делать. Может я тогда ман какой-то прочитал, а теперь забыл.. хз :)

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

Я не уверен, что такой проброс вниз реализован

Вот такой пример:

#!/usr/bin/env ruby

require 'gtk2'

class App
	def initialize
		super

		@window = Gtk::Window.new
		box = Gtk::VBox.new()
		@window.add box

		3.times { |n|
			eb = Gtk::EventBox.new()
			eb.set_flags Gtk::Widget::NO_WINDOW
			box.pack_start eb, false
			l = Gtk::Label.new(n.to_s)
			eb.add l
			eb.signal_connect('button-press-event'){|w| puts w.child.text}
		}

		@window.show_all

		Gtk.main()
	end

end

App.new
Как видишь, EventBox-у установлен флаг NO_WINDOW. gtkparasite подтверждает, что всё дерево виджетов относится к одному окну и тому же.

Тем не менее, обработчики button-press-event работают.

-------------------------------------------

И в этом месте до меня дошло. Озарило, блин. Если EventBox заюзать с NO_WINDOW, он создаёт невидимое input only окно поверх себя и берет события из него. А я ведь прекрасно знал про эту фичу. Только забыл начисто.

Всё. Вопрос снят. :}

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

fix

s/к одному окну и тому же./к одному и тому же окну./

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