I'm trying to convert old Gtk2 perl script to Gtk3. Here is how the Gtk2 version looks like:
#!/usr/bin/perl
use 5.30.0;
use strict;
use warnings;
use diagnostics;
use Gtk2 '-init';
use Goo::Canvas;
my $canvas = Goo::Canvas->new;
my $pattern = Cairo::SolidPattern->create_rgba(0, 0, 0, 0);
$pattern = Goo::Cairo::Pattern->new($pattern);
my $rect = Goo::Canvas::Rect->new(
$canvas->get_root_item,
0, 0, 100, 100,
'fill-pattern' => $pattern,
'line-dash' => Goo::Canvas::LineDash->new([5, 5]),
'line-width' => 1,
'stroke-color' => 'black',
);
This is my Gtk3 attempt:
#!/usr/bin/perl
use 5.30.0;
use strict;
use warnings;
use diagnostics;
use Gtk3 '-init';
use GooCanvas2;
my $canvas = GooCanvas2::Canvas->new;
my $pattern = Cairo::SolidPattern->create_rgba(0, 0, 0, 0);
my $rect = GooCanvas2::CanvasRect->new(
parent => $canvas->get_root_item,
x => 0, y => 0, width => 100, height => 100,
'fill-pattern' => $pattern,
'line-dash' => GooCanvas2::CanvasLineDash->newv([5, 5]),
'line-width' => 1,
'stroke-color' => 'black',
);
But this results in error:
Uncaught exception from user code:
Cairo::SolidPattern=SCALAR(0x558de4acb260) is not of type GooCanvas2::CairoPattern at /usr/lib64/perl5/vendor_perl/5.30.1/x86_64-linux/Glib.pm line 222.
Glib::Object::_LazyLoader::AUTOLOAD("GooCanvas2::CanvasRect", "parent", GooCanvas2::CanvasGroup=HASH(0x558de4abe1a0), "x", 0, "y", 0, "width", ...) called at test.pl line 14
I also tried to insert $pattern = GooCanvas2::CairoPattern->new($pattern); but that didn't help:
Uncaught exception from user code:
Could not fetch information for package GooCanvas2::CairoPattern; perhaps it has not been loaded via Glib::Object::Introspection? at test.pl line 13.
But looking at source of GooCanvas2.pm, it does load GooCanvas2 via Glib::Object::Introspection.
Any suggestions how to fix this?
I tried to install libgoocanvas-2.0-dev on Ubuntu 20.04 and it installs the introspection XML file for GooCanvas as
/usr/share/gir-1.0/GooCanvas-2.0.gir. In this file I see the definition for the binding forGooCanvas2::CanvasRect->new():I notice that the definition for the
fill-patternparameter is probably included in the lastname="..."parameter pack. So it is not clear what type the parameter should be. But later in the file there is maybe a clue, on line 244 we have:I am not sure what exactly the
glib:boxedmeans, but according to the documentation for Glib::Object::Introspection :So
boxedtypes get their own namespace in Perl. More about boxed types here.The error message:
Indicates that it expects a
GooCanvas2::CairoPatterntype, but when I try to use such a type, e.g.I get error message:
Update:
The following C program works fine and shows that the pattern should be of type
cairo_pattern_t:Update 2:
Some more debugging info: The call
GooCanvas2::CanvasRect->new()is redirected to line 1327 inGObject.xs:at line 1359 it finds the expected type for the property argument
fill-pattern. It looks like this is type G_TYPE_BOXED. Then at line 1378It tries to retrieve the boxed value from the supplied Perl argument (of type
Cairo::SolidPattern) which leads to line 136The first check fails so it enters the second alternative
g_value_set_static_boxed()which first callsgperl_get_boxed_check(), see line 558 inGBoxed.xs. On line 568boxed_infois returned asBoxedInfo *with contentand at line 575
unwrapis set to_default_wrapper_class.unwrapand at line 583:which calls
default_boxed_unwrap()at line 420 :which croaks at line 429:
since
Cairo::SolidPatternis not derived fromGooCanvas2::CairoPattern.Update 3:
Looking at GooCanvas's source, it defines several setters/getters for the pattern:
fill-color,fill-color-rgba,fill-color-gdk-rgba,fill-pixbuf,fill-pattern, all of which internally set/get the same propertygoo_canvas_style_fill_pattern_id. And other setters don't have the issue of having the wrong introspection wrapper tocairo_pattern_t. Therefore this works:Moreover, after
$rectis constructed, we can getGooCanvas2::CairoPatternfrom it via$rect->get('fill-pattern').This doesn't let use other patterns created from cairo (linear, etc), but at least solid color works by providing arbitrary RGBA, and pixbuf setter should be enough for other needs.
Update 4:
I wrote GooCanvas2::CairoTypes to work this around at least for Patterns.
It uses
gperl_register_boxed_synonym(CAIRO_GOBJECT_TYPE_PATTERN, GOO_TYPE_CAIRO_PATTERN);to letCairo::Patternbe used asGooCanvas::CairoPattern, and additionally provides a function to explicitly convertGooCanvas::CairoPatterntoCairo::Patternviagperl_new_boxed(gperl_get_boxed_check(input, GOO_TYPE_CAIRO_PATTERN), CAIRO_GOBJECT_TYPE_PATTERN, 0).