I'm trying to get an input shape to apply to a window, so I can have a transparent frame with only the interesting parts to be clickable, etc.
I'm using Cairo graphics with PyGObject (Python 3).
The Object is a regular Gtk Windows object, which then defines a Cairo drawing area:
class Face(Gtk.Window):
def __init__(self):
super(Face, self).__init__()
self.init_ui()
def init_ui(self):
[...]
self.darea = Gtk.DrawingArea()
self.darea.connect("draw", self.on_draw)
self.add(self.darea)
def on_draw(self, widget, cr):
[... (drawing a couple shapes into the context)]
sface = cr.get_group_target()
mregion = Gdk.cairo_region_create_from_surface(sface)
# the above line produces the error
# the following lines is wishful thinking at this point...
#self.get_window().input_shape_combine_region(mregion, 0, 0)
So, the function on_draw()
gets called whenever the draw area has to be redrawn, which is when the window is moved, resized, revealed after being hidden, and so on.
most of the window is actually empty, as it is supposed to be a mostly translucent frame, only visible parts are supposed to be clickable. However, I'm getting the following error:
Traceback (most recent call last):
File "./lsc.py", line 236, in on_draw
mregion = Gdk.cairo_region_create_from_surface(sface)
TypeError: Couldn't find foreign struct converter for 'cairo.Region'
python3: cairo-surface.c:953: cairo_surface_destroy: Assertion `CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count)' failed.
zsh: abort (core dumped) ./lsc.py
The packages for Python3, the PyGObject and the Cairo libs are installed, and I've also imported both parts of Cairo:
from gi.repository import Gtk, Gdk, cairo
import cairo
At this point I'm not entirely sure, whether this is a Python problem, or an error on my part.
I'm unsure if even using the cairo.Region
is even applicable like that, the example I'm going by on, is this: http://www.programcreek.com/python/example/81481/cairo.Region
Edit
At this point I'm seriously confused what's going on. I've been looking a bit into this and this is for what what I've found out:
There seems to be some sort of error with PyGI and Cairo.
When I use just the introspection part of cairo:
from gi.repository import Gtk, Gdk, cairo
#import cairo
And then run my script, I get this error:
raceback (most recent call last):
File "./lsc.py", line 164, in on_draw
cr.set_operator(cairo.OPERATOR_SOURCE)
File "/usr/lib64/python3.5/site-packages/gi/module.py", line 139, in __getattr__
self.__name__, name))
AttributeError: 'gi.repository.cairo' object has no attribute 'OPERATOR_SOURCE'
Obviously I'm using cairo.OPERATOR_SOURCE
in my code to draw to a cairo context. However the introspected package doesn't even seem to contain te operators used to draw on a surface. Very strange.
When I use just the non-introspected module:
from gi.repository import Gtk, Gdk
import cairo
I get the same error as in my first part of the question.
for completion, this is the list of cairo packages, that I have currently installed:
cairo-devel-1.14.6-1.fc24.x86_64
pycairo-devel-1.10.0-4.fc24.x86_64
cairo-gobject-1.14.6-1.fc24.i686
mingw32-cairo-1.14.6-1.fc24.noarch
python3-cairocffi-0.7.2-5.fc24.noarch
cairo-1.14.6-1.fc24.i686
cairo-1.14.6-1.fc24.x86_64
pycairo-1.10.0-4.fc24.x86_64
python3-cairosvg-1.0.19-3.fc24.noarch
cairomm-devel-1.12.0-2.fc24.x86_64
cairo-clock-0.3.4-17.fc24.x86_64
cairomm-1.12.0-2.fc24.x86_64
cairo-gobject-1.14.6-1.fc24.x86_64
python3-cairo-1.10.0-15.fc24.x86_64
mingw32-cairomm-1.12.0-2.fc24.noarch
python3-cairo-devel-1.10.0-15.fc24.x86_64
cairo-gobject-devel-1.14.6-1.fc24.x86_64
I think you'll find, that all of them are quite recent, and meet the requirements as stated in the example I've linked above.
Also, please consider the lines 268 - 274 of countdown.py
:
# make window click-through, this needs pycairo 1.10.0 for python3
# to work
rect = cairo.RectangleInt (0, 0, 1, 1)
region = cairo.Region (rect)
if (not region.is_empty ()):
self.window.input_shape_combine_region (None)
self.window.input_shape_combine_region (region)
The author isn't using the introspected cairo
, he just does import cairo
, which leads me to believe it's the more correct way, perhaps.
Anyway, the whole script doesn't work either.
At this point I'm kinda stuck again. I don't seem to be able to find a recent and/or working example of how to make use of this functionality.
So far it seems, as if using the introspected version of cairo
is of no use, at it defines almost no elements of the original. However, when using the regular pycairo
(by importing with import cairo
), I get the error that made me post this question in the first place.
I'm beginning to believe I'm having a conceptual error, maybe?