Gtk создает новый сокет XEMBED при перемещении сокета из одного ноутбука в другой
Я работаю над приложением с графическим интерфейсом, используя Python 3.7 и PyGTK 3.0. Мой графический интерфейс состоит из нескольких GTK.Notebooks, которые находятся в одной группе, и все их вкладки настроены как съемные. Таким образом, я могу перетащить страницу из одной записной книжки на другую. Это прекрасно работает с большинством виджетов, которые я использую, но я изо всех сил пытаюсь заставить его работать с GTK.Socket. Я хочу запускать внешние программы и показывать их графический интерфейс в виде страницы в одной из записных книжек. Это хорошо работает, но когда я перетаскиваю страницу в другой Блокнот, страница становится пустой.
Я попытался подключиться к сигналам добавления страниц и удаления страниц и вывести на консоль некоторую отладочную информацию. Я заметил, что при каждом перемещении GTK.Socket (перетаскивание в другой блокнот) GTK.Socket получает новый идентификатор. После первого перемещения идентификатор уже отличается от идентификатора, который был у Socket после его создания и добавления. Это заставляет меня задуматься о том, что каждый раз, когда я перемещаю страницу, создается новый сокет, и, очевидно, внешняя программа не принимает к сведению это изменение и продолжает рисовать на старом сокете, который я больше не могу отображать.
Вот MWE для моей проблемы. Он создает окно с двумя записными книжками, установленными в контейнере HPaned. Каждый Блокнот получает TextView в качестве своей первой страницы (поэтому он не пустой), а правильный Блокнот также получает Сокет (который в этом случае относится к сеансу gtkwave). Я также добавил слушателей для добавления страниц и удаления страниц с некоторыми результатами отладки.
import subprocess
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
def handleAdd(notebook, child, pageNum):
print("Handle add")
if isinstance(child, Gtk.Socket):
print("ID after ADD: " + hex(child.get_id()))
def handleRemove(notebook, child, pageNum):
print("Handle remove")
if isinstance(child, Gtk.Socket):
print("ID after REMOVE: " + hex(child.get_id()))
window = Gtk.Window()
paned = Gtk.HPaned()
notebookLeft = Gtk.Notebook()
notebookRight = Gtk.Notebook()
notebookLeft.connect("page-added", handleAdd)
notebookLeft.connect("page-removed", handleRemove)
notebookRight.connect("page-added", handleAdd)
notebookRight.connect("page-removed", handleRemove)
textviewLeft = Gtk.TextView()
textviewRight = Gtk.TextView()
notebookLeft.append_page(textviewLeft)
notebookLeft.set_tab_detachable(textviewLeft, True)
notebookLeft.set_tab_reorderable(textviewLeft, True)
notebookLeft.set_group_name("Main")
notebookRight.append_page(textviewRight)
notebookRight.set_tab_detachable(textviewRight, True)
notebookRight.set_tab_reorderable(textviewRight, True)
notebookRight.set_group_name("Main")
socket = Gtk.Socket()
notebookRight.append_page(socket)
notebookRight.set_tab_detachable(socket, True)
notebookRight.set_tab_reorderable(socket, True)
paned.add1(notebookLeft)
paned.add2(notebookRight)
window.add(paned)
window.connect("delete-event", Gtk.main_quit)
window.show_all()
print("First socket id " + hex(socket.get_id()))
process = subprocess.Popen(["gtkwave", "/home/benedikt/repos/synpathic/synpathic/testsrc/tb_blake2b.ghw", "-X", hex(socket.get_id())])
Gtk.main()
Если вы запустите код, вы увидите следующие сообщения:
...
ID after ADD: 0x0
(test.py:18825): Gtk-CRITICAL **: 11:42:07.507: gtk_socket_get_id: assertion '_gtk_widget_get_anchored (GTK_WIDGET (socket))' failed
First socket id 0x7400010
... (GTKWave messages) ...
Первый идентификатор - 0x0, потому что сокет еще не был добавлен в окно, это ожидаемое поведение. Это также объясняет ошибку (которая исчезнет, если я не подключу сигнал). Непосредственно перед вызовом Gtk.main() Socket действителен, и ID может быть напечатан. Теперь переместите вкладку с сеансом GTKWave, и вы увидите следующее сообщение для каждого хода:
...
ID after ADD: 0x74001ae
...
Этот идентификатор отличается от первого действительного идентификатора и отличается для каждого хода. Я ожидаю, что этот идентификатор останется прежним, так что внешний GUI все еще может быть показан. Почему создается новый сокет и как я могу обойти эту проблему?