I have an application written using pygobject with Gtk4. I have been working on a feature which allows the application to take screenshots of itself for documentation purposes.
I believe the “front door” for taking a screenshot would be:
Get a Gtk.Snapshot
Grab the main Gsk.RenderNode from it.
Use a Gsk.Renderer to convert the RenderNode to a Gdk.Texture
Save the Gdk.Texture to a file.
There are other ways, involving cairo , but every way I’ve found depends on Gsk in some way or another.
I have noticed a few issues when using these Gsk objects:
Gsk.CairoRenderer.render_texture seems to expect a GObject as the first argument, but it actually takes a GskRenderNode which is not a GObject . As a result, I don’t believe it can be used.
GskRenderNode.serialize causes the application to seg. fault.
GskRenderNode.draw to a cairo.Context causes the application to seg. fault.
My questions are as follows: Is Gsk supported in pygobject? Will it be supported in the future? What is the best way to take a screenshot of the application?
@ebassi
I believe these bindings may be broken then. Here’s some example code to explain why I think the bindings may be broken. This is all from the master branch of pygobject:
Python 3.8.6 (default, Sep 30 2020, 04:00:38)
[GCC 10.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from gi.repository import Gsk, Graphene, Gdk
<stdin>:1: PyGIWarning: Gsk was imported without specifying a version first. Use gi.require_version('Gsk', '4.0') before import to ensure that the right version gets loaded.
# Create a Gsk.RenderNode
>>> rect = Graphene.Rect().init(0, 0, 100, 100) # Create a rectangle
>>> color = Gdk.RGBA() # Create a color
>>> color_node = Gsk.ColorNode.new(color, rect) # Create a color node
<stdin>:1: Warning: g_object_get_qdata: assertion 'G_IS_OBJECT (object)' failed
<stdin>:1: Warning: g_object_is_floating: assertion 'G_IS_OBJECT (object)' failed
** (process:226131): CRITICAL **: 11:14:09.836: pygobject_register_wrapper: assertion 'PyObject_TypeCheck(self, &PyGObject_Type)' failed
# Something is already upset, because it expects Gsk.RenderNode to be a GObject, and it isn't.
>>> renderer = Gsk.CairoRenderer.new() # Create a renderer
>>> renderer.render_texture(color_node, None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: expected GObject but got <gi.repository.Gsk.ColorNode object at 0x7f3a7d16efa0>
# It _really_ wants Gsk.RenderNode to be a GObject
This same error happens when I grab the Gsk.RenderNode from the Gtk.Snapshot, although sometimes it seg. faults as well. In fact, in the above example, if you do a help(color_node) you will get a seg fault.
By my understanding, the bindings really expect Gsk.RenderNode to be a GObject, and it isn’t one.
@matthiasc
As for GtkWidgetPaintable, I don’t see a way to turn that into a screenshot without calling the snapshot function. It appears I really want a Gdk.Texture object, and to get one I need to run through a Gsk.Renderer with a Gdk or GtkSnapshot.