Gtk creates new XEMBED Socket when Socket is moved from one Notebook to another

197 Views Asked by At

I am working on a GUI application using Python 3.7 and PyGTK 3.0. My GUI consists of multiple GTK.Notebooks, which are all in the same group and all their tabs are set to be detachable. This way, I can drag away a page from one Notebook and drop it on another. This works great with most widgets I am using, but I am struggling to get it to work with GTK.Socket. I want to run external programs and show their GUI as a page in one of the Notebooks. This works well, but when I drag a page to a different Notebook, the page is empty.

I tried to connect to the page-added and page-removed signals and print some debug information to the console. I noticed that on each move of the GTK.Socket (drag & drop to another notebook), the GTK.Socket gets a new ID. After the first move, the ID is already different from the ID the Socket had after it was created and added. This leaves me thinking that each time I move the page, a new Socket is created and obviously the external program takes no note of that change and still draws onto the old Socket, which I cannot display any more.

Here is a MWE for my Problem. It creates a Window with two Notebooks set up in a HPaned container. Each Notebook gets a TextView as their first page (so it is not empty) and the right Notebook also gets a Socket (which in this case relays to a gtkwave session). I also added the listeners for page-added and page-removed with some debug output.

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()

If you run the code, you will see the following messages:

...
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) ...

The first ID is 0x0 because the Socket was not added to a Window yet, that is expected behaviour. This also explains the error (which is gone if I do not connect the Signal). Just before calling Gtk.main() the Socket is valid though and the ID can be printed. Now move the tab with the GTKWave session around and you will see the following message for each move:

...
ID after ADD: 0x74001ae
...

This ID is different from the first valid ID and is different for each move. I would expect this ID to stay the same so the external GUI can still be shown. Why is a new Socket created and how can I work around this issue?

0

There are 0 best solutions below