jhass / crystal-gobject Goto Github PK
View Code? Open in Web Editor NEWgobject-introspection for Crystal
License: BSD 3-Clause "New" or "Revised" License
gobject-introspection for Crystal
License: BSD 3-Clause "New" or "Revised" License
I think, all this fun (for example, _init_AboutDialog) only return GType(a numerical value which represents the unique identifier of a registered type), not initialize any instance of class.Their uses in initialize methods make no sense.
It is only my opinion.
crystal run samples/gtk_hello_world.cr
returns :
Syntax error in lib/gobject/g_i_repository/info/base_info.cr:115: unexpected token: :
def dump(dumper, & : BaseInfo ->)
I
This is probably a noob question, so I admit I am pretty unfamiliar with Gtk and relatively new in Crystal. But I think the former is great to get a real app build and the latter is just a breeze to write.
So here come the question:
How is the best way to find out, what classes are available and how the methods are called on them? I am reading the GTK docs and also found great course material about TextView but they explain and describe the C code.
An example: Making a GTK TextView object editable seems to be done in C using
gtk_text_view_set_editable (text_view, true);
But to do this in Crystal I have to do this:
gtk_text_view_set_editable (text_view, true);
And how gtk_text_buffer_get_iter_at_line(โฆ)
translates to Crystal I have no clue, cannot find a similar method on the Gtk::TextBuffer
instance. For this I use a macro that prints out all methods of a class.
So, what transformations are done with all the classes and methods? How do the C code translate to Crystal code? How is the best way to explore it? I somehow cannot really read it from the code in this Repo, so it seems still magic to me. :)
I appreciate a hint where to look and I strongly appreciate this Library and the work you put into it. Great stuff. Also, the examples also helped a bit (although the CSS example does not work for me, but that's probably another story I can figure out, when I know how to figure stuff out...)
So: Thanks again and in advance ๐
I thought about create this issue at malloc_pthread_shim
shard, but as it's a fix for this one, I created here, please correct me if this isn't the right place.
To reproduce the crash:
$ git clone https://github.com/hugopl/tijolo.git
$ cd tijolo && git checkout 5b55a519e37c0c02fb4eed56cbf5f8be87494fe8
$ shards build
$ ./bin/tijolo
The crash doesn't happen with GC disabled. I tried to reduce the code to create a minimal example, but seems that it was not enough entropy to trigger the bug.
If I remove the require "malloc_pthread_shim"
at src.main.cr it works... but crash later on GtkSource::Language.set_language
as expected.
If I comment lines 66 and 68 (some signal connections) at src/application.cr it works... but probably just a coincidence.... anyway the crash happens inside the setup_actions.
Here's the output with the following libraries compiled as debug:
libgailutil-3.so
libgdk-3.so
libgio-2.0.so
libglib-2.0.so
libgmodule-2.0.so
libgobject-2.0.so
libgthread-2.0.so
libgtk-3.so
$ LD_LIBRARY_PATH=/opt/debug/usr/lib/ GC_PRINT_VERBOSE_STATS=1 ./bin/tijolo
Grow heap to 64 KiB after 0 bytes allocated
Number of processors = 8
Started 7 mark helper threads
Initiating full world-stop collection!
0 bytes in heap blacklisted for interior pointers
--> Marking for collection #1 after 0 allocated bytes
Pushed 1 thread stacks
Starting marking for mark phase number 0
Starting mark helper 0
Starting mark helper 1
Starting mark helper 2
Starting mark helper 3
Starting mark helper 4
Starting mark helper 5
Starting mark helper 6
Starting mark helper 7
Finished mark helper 0
Finished mark helper 7
Finished mark helper 4
Finished mark helper 2
Finished mark helper 1
Finished mark helper 6
Finished mark helper 5
Finished mark helper 3
Finished marking for mark phase number 0
GC #1 freed 0 bytes, heap 64 KiB (+ 0 KiB unmapped)
World-stopped marking took 1 msecs (1 in average)
Bytes recovered before sweep - f.l. count = 0
In-use heap: 0% (0 KiB pointers + 0 KiB other)
Immediately reclaimed 0 bytes, heapsize: 65536 bytes (0 unmapped)
0 finalization entries; 0/0 short/long disappearing links alive
0 finalization-ready objects; 0/0 short/long links cleared
Finalize plus initiate sweep took 0 + 0 msecs
Complete collection took 1 msecs
Adding block map for size of 3 granules (48 bytes)
Grow heap to 156 KiB after 48 bytes allocated
Adding block map for size of 0 granules (0 bytes)
Adding block map for size of 1 granules (16 bytes)
Adding block map for size of 16 granules (256 bytes)
Adding block map for size of 32 granules (512 bytes)
Adding block map for size of 128 granules (2048 bytes)
Adding block map for size of 2 granules (32 bytes)
Adding block map for size of 4 granules (64 bytes)
Adding block map for size of 6 granules (96 bytes)
Adding block map for size of 9 granules (144 bytes)
Adding block map for size of 5 granules (80 bytes)
Adding block map for size of 8 granules (128 bytes)
Adding block map for size of 10 granules (160 bytes)
Adding block map for size of 12 granules (192 bytes)
Grow heap to 220 KiB after 112400 bytes allocated
Adding block map for size of 64 granules (1024 bytes)
Grew fo table to 1 entries
Adding block map for size of 15 granules (240 bytes)
Grew fo table to 2 entries
Grow heap to 296 KiB after 140448 bytes allocated
Adding block map for size of 11 granules (176 bytes)
Grew fo table to 4 entries
Adding block map for size of 7 granules (112 bytes)
Adding block map for size of 17 granules (272 bytes)
Grew fo table to 8 entries
Grew dl table to 1 entries
Adding block map for size of 13 granules (208 bytes)
Grew dl table to 2 entries
Adding block map for size of 21 granules (336 bytes)
Grow heap to 396 KiB after 179504 bytes allocated
Adding block map for size of 20 granules (320 bytes)
Adding block map for size of 14 granules (224 bytes)
Grew fo table to 16 entries
Initiating full world-stop collection!
0 bytes in heap blacklisted for interior pointers
--> Marking for collection #2 after 242816 allocated bytes
Pushed 1 thread stacks
Starting marking for mark phase number 1
Starting mark helper 0
Starting mark helper 1
Starting mark helper 2
Starting mark helper 3
Starting mark helper 4
Starting mark helper 5
Starting mark helper 6
Finished mark helper 3
Finished mark helper 4
Finished mark helper 5
Finished mark helper 0
Finished mark helper 6
Finished mark helper 1
Finished mark helper 2
Finished marking for mark phase number 1
GC #2 freed 0 bytes, heap 396 KiB (+ 0 KiB unmapped)
World-stopped marking took 1 msecs (1 in average)
Bytes recovered before sweep - f.l. count = -126240
In-use heap: 54% (209 KiB pointers + 5 KiB other)
Immediately reclaimed -109856 bytes, heapsize: 405504 bytes (0 unmapped)
10 finalization entries; 3/0 short/long disappearing links alive
1 finalization-ready objects; 0/0 short/long links cleared
Finalize plus initiate sweep took 0 + 0 msecs
Complete collection took 1 msecs
Grow heap to 580 KiB after 0 bytes allocated
Adding block map for size of 42 granules (672 bytes)
Adding block map for size of 24 granules (384 bytes)
Adding block map for size of 50 granules (800 bytes)
Adding block map for size of 84 granules (1344 bytes)
Grow heap to 776 KiB after 354400 bytes allocated
Grow heap to 1036 KiB after 750640 bytes allocated
Adding block map for size of 18 granules (288 bytes)
Initiating full world-stop collection!
4096 bytes in heap blacklisted for interior pointers
--> Marking for collection #3 after 2088480 allocated bytes
Pushed 2 thread stacks
Starting marking for mark phase number 2
Starting mark helper 0
Starting mark helper 1
Starting mark helper 2
Starting mark helper 3
Starting mark helper 4
Starting mark helper 5
Starting mark helper 6
Starting mark helper 7
Finished mark helper 7
Finished mark helper 6
Finished mark helper 0
Finished mark helper 2
Finished mark helper 5
Finished mark helper 1
Finished mark helper 3
Finished mark helper 4
Finished marking for mark phase number 2
Recycle 65536/65536 scratch-allocated bytes at 0x7f6392888000
Grew mark stack to 8192 frames
GC #3 freed -24416 bytes, heap 1100 KiB (+ 0 KiB unmapped)
World-stopped marking took 2 msecs (1 in average)
Bytes recovered before sweep - f.l. count = -230480
In-use heap: 59% (652 KiB pointers + 7 KiB other)
Immediately reclaimed -222288 bytes, heapsize: 1126400 bytes (0 unmapped)
10 finalization entries; 3/0 short/long disappearing links alive
2 finalization-ready objects; 0/0 short/long links cleared
Finalize plus initiate sweep took 0 + 0 msecs
Complete collection took 2 msecs
Adding block map for size of 19 granules (304 bytes)
Adding block map for size of 23 granules (368 bytes)
Grow heap to 1468 KiB after 107824 bytes allocated
Adding block map for size of 22 granules (352 bytes)
Grow heap to 1960 KiB after 607136 bytes allocated
Initiating full world-stop collection!
0 bytes in heap blacklisted for interior pointers
--> Marking for collection #4 after 1296688 allocated bytes
Pushed 3 thread stacks
Starting marking for mark phase number 3
Starting mark helper 0
Starting mark helper 1
Starting mark helper 2
Starting mark helper 3
Starting mark helper 4
Starting mark helper 5
Starting mark helper 6
Starting mark helper 7
Finished mark helper 4
Finished mark helper 6
Finished mark helper 7
Finished mark helper 2
Finished mark helper 1
Finished mark helper 5
Finished mark helper 3
Finished mark helper 0
Finished marking for mark phase number 3
Recycle 131072/131072 scratch-allocated bytes at 0x7f63895c1000
Grew mark stack to 16384 frames
GC #4 freed -92608 bytes, heap 2088 KiB (+ 0 KiB unmapped)
World-stopped marking took 3 msecs (1 in average)
Bytes recovered before sweep - f.l. count = -100080
In-use heap: 72% (1502 KiB pointers + 5 KiB other)
Immediately reclaimed -91888 bytes, heapsize: 2138112 bytes (0 unmapped)
10 finalization entries; 3/0 short/long disappearing links alive
0 finalization-ready objects; 0/0 short/long links cleared
Finalize plus initiate sweep took 0 + 0 msecs
Complete collection took 3 msecs
Grow heap to 2792 KiB after 149440 bytes allocated
Grow heap to 3724 KiB after 978080 bytes allocated
Initiating full world-stop collection!
12288 bytes in heap blacklisted for interior pointers
--> Marking for collection #5 after 2542128 allocated bytes
Pushed 3 thread stacks
Starting marking for mark phase number 4
Starting mark helper 0
Starting mark helper 1
Starting mark helper 2
Starting mark helper 3
Starting mark helper 4
Starting mark helper 5
Starting mark helper 6
Starting mark helper 7
Finished mark helper 0
Finished mark helper 6
Finished mark helper 3
Finished mark helper 4
Finished mark helper 2
Finished mark helper 7
Finished mark helper 1
Finished mark helper 5
Finished marking for mark phase number 4
Recycle 262144/262144 scratch-allocated bytes at 0x7f6388c27000
Grew mark stack to 32768 frames
GC #5 freed -45568 bytes, heap 3980 KiB (+ 0 KiB unmapped)
World-stopped marking took 5 msecs (2 in average)
Bytes recovered before sweep - f.l. count = -77136
In-use heap: 80% (3185 KiB pointers + 5 KiB other)
Immediately reclaimed -64848 bytes, heapsize: 4075520 bytes (0 unmapped)
10 finalization entries; 3/0 short/long disappearing links alive
0 finalization-ready objects; 0/0 short/long links cleared
Finalize plus initiate sweep took 0 + 0 msecs
Complete collection took 6 msecs
Grow heap to 5308 KiB after 343744 bytes allocated
Invalid memory access (signal 11) at address 0x78b
Segmentation fault (core dumped)
exitcode 139.
GDB information about the crash:
(gdb) info threads
Id Target Id Frame
1 Thread 0x7ffff4116980 (LWP 18561) "tijolo" 0x00007ffff6dda8f4 in do_futex_wait.constprop () from /usr/lib/libpthread.so.0
2 Thread 0x7ffff4105700 (LWP 18565) "tijolo" 0x00007ffff6dd7e32 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0
3 Thread 0x7ffff3904700 (LWP 18566) "tijolo" 0x00007ffff6dd7e32 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0
4 Thread 0x7ffff3103700 (LWP 18567) "tijolo" 0x00007ffff6dd7e32 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0
5 Thread 0x7ffff2902700 (LWP 18568) "tijolo" 0x00007ffff6dd7e32 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0
6 Thread 0x7ffff2101700 (LWP 18569) "tijolo" 0x00007ffff6dd7e32 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0
7 Thread 0x7ffff1900700 (LWP 18570) "tijolo" 0x00007ffff6dd7e32 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0
8 Thread 0x7ffff10ff700 (LWP 18571) "tijolo" 0x00007ffff6dd7e32 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0
* 9 Thread 0x7fffef4f4700 (LWP 18572) "gmain" 0x00007ffff6c7605f in poll () from /usr/lib/libc.so.6
Thread 9 backtrace:
#0 0x00007ffff6c7605f in poll () from /usr/lib/libc.so.6
#1 0x00007ffff70b4f28 in g_main_context_poll (priority=<optimized out>, n_fds=1, fds=0x7fffef807c50, timeout=<optimized out>, context=0x7fffef8839a0) at ../glib/glib/gmain.c:4346
#2 g_main_context_iterate.constprop.0 (context=context@entry=0x7fffef8839a0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/glib/gmain.c:4042
#3 0x00007ffff7066211 in g_main_context_iteration (context=0x7fffef8839a0, may_block=may_block@entry=1) at ../glib/glib/gmain.c:4108
#4 0x00007ffff7066262 in glib_worker_main (data=<optimized out>) at ../glib/glib/gmain.c:5996
#5 0x00007ffff708f501 in g_thread_proxy (data=0x7fffef7fb360) at ../glib/glib/gthread.c:807
#6 0x00007ffff6e0eb35 in ?? () from /usr/lib/libgc.so.1
#7 0x00007ffff6dfcda7 in GC_call_with_stack_base () from /usr/lib/libgc.so.1
#8 0x00007ffff6dd1422 in start_thread () from /usr/lib/libpthread.so.0
#9 0x00007ffff6c80bf3 in clone () from /usr/lib/libc.so.6
Thread 1 backtrace:
#0 0x00007ffff6dda8f4 in do_futex_wait.constprop () from /usr/lib/libpthread.so.0
#1 0x00007ffff6dda9f8 in __new_sem_wait_slow.constprop.0 () from /usr/lib/libpthread.so.0
#2 0x00007ffff6df3454 in ?? () from /usr/lib/libgc.so.1
#3 0x00007ffff6e01ef9 in ?? () from /usr/lib/libgc.so.1
#4 0x00007ffff6e020bc in ?? () from /usr/lib/libgc.so.1
#5 0x00007ffff6e06a8a in ?? () from /usr/lib/libgc.so.1
#6 0x00007ffff6e06eaf in ?? () from /usr/lib/libgc.so.1
#7 0x00007ffff6e072b7 in ?? () from /usr/lib/libgc.so.1
#8 0x00007ffff6e0b61a in GC_generic_malloc () from /usr/lib/libgc.so.1
#9 0x00007ffff6e0b875 in GC_malloc_kind_global () from /usr/lib/libgc.so.1
#10 0x00007ffff6e0da34 in GC_posix_memalign () from /usr/lib/libgc.so.1
#11 0x0000555555625096 in posix_memalign () at /home/hugo/src/tijolo/lib/malloc_pthread_shim/src/malloc_pthread_shim.cr:200
#12 0x00007ffff708463a in allocator_memalign (memsize=2032, alignment=2048) at ../glib/glib/gslice.c:1411
#13 allocator_add_slab (allocator=0x7ffff713cf00 <allocator>, chunk_size=128, ix=<optimized out>) at ../glib/glib/gslice.c:1283
#14 slab_allocator_alloc_chunk (chunk_size=chunk_size@entry=128) at ../glib/glib/gslice.c:1329
#15 0x00007ffff7085df3 in magazine_cache_pop_magazine (countp=0x7ffff08ed888, ix=7) at ../glib/glib/gslice.c:730
#16 thread_memory_magazine1_reload (ix=7, tmem=<optimized out>) at ../glib/glib/gslice.c:800
#17 g_slice_alloc (mem_size=mem_size@entry=120) at ../glib/glib/gslice.c:1013
#18 0x00007ffff7085e4b in g_slice_alloc0 (mem_size=mem_size@entry=120) at ../glib/glib/gslice.c:1050
#19 0x00007ffff716e629 in g_type_create_instance (type=<optimized out>) at ../glib/gobject/gtype.c:1849
#20 0x00007ffff715ad29 in g_param_spec_internal (param_type=140737288140192, name=name@entry=0x7ffff72e1eed "fd", nick=0x7ffff72d9874 "File descriptor", blurb=blurb@entry=0x7ffff72d9858 "The sockets file descriptor",
flags=flags@entry=235) at ../glib/gobject/gparam.c:445
#21 0x00007ffff715af8b in g_param_spec_int (name=name@entry=0x7ffff72e1eed "fd", nick=<optimized out>, blurb=blurb@entry=0x7ffff72d9858 "The sockets file descriptor", minimum=minimum@entry=-2147483648, maximum=maximum@entry=2147483647,
default_value=default_value@entry=-1, flags=235) at ../glib/gobject/gparamspecs.c:1784
#22 0x00007ffff7222bb1 in g_socket_class_init (klass=0x7fffef899a80) at ../glib/gio/gsocket.c:961
#23 g_socket_class_intern_init (klass=0x7fffef899a80) at ../glib/gio/gsocket.c:268
#24 0x00007ffff7175092 in type_class_init_Wm (pclass=0x7ffff4110d80, node=0x7fffef83ed20) at ../glib/gobject/gtype.c:2235
#25 g_type_class_ref (type=<optimized out>) at ../glib/gobject/gtype.c:2950
#26 0x00007ffff729d2c1 in ensure_type (gtype=<optimized out>) at ../glib/gio/gdbusprivate.c:222
#27 ensure_required_types () at ../glib/gio/gdbusprivate.c:261
#28 _g_dbus_initialize () at ../glib/gio/gdbusprivate.c:1972
#29 0x00007ffff7291b1a in _g_dbus_initialize () at ../glib/gio/gdbusconnection.c:7334
#30 g_bus_get_sync (bus_type=G_BUS_TYPE_SESSION, cancellable=0x0, error=0x0) at ../glib/gio/gdbusconnection.c:7326
#31 0x00007ffff725fdb9 in g_application_impl_register (error=0x7fffffffdf20, cancellable=0x0, remote_actions=0x7fffef896098, exported_actions=0x7ffff08b1210, flags=G_APPLICATION_NON_UNIQUE, appid=0x7ffff4107880 "io.github.hugopl.Tijolo",
application=0x7fffef8960f0) at ../glib/gio/gapplicationimpl-dbus.c:601
#32 g_application_register (application=application@entry=0x7fffef8960f0, cancellable=cancellable@entry=0x0, error=error@entry=0x7fffffffdf20) at ../glib/gio/gapplication.c:2188
#33 0x00007ffff72608ac in g_application_real_local_command_line (application=0x7fffef8960f0, arguments=0x7fffffffdf88, exit_status=0x7fffffffdf84) at ../glib/gio/gapplication.c:1106
#34 0x00007ffff7260c0a in g_application_run (application=0x7fffef8960f0, argc=-8316, argv=<optimized out>) at ../glib/gio/gapplication.c:2528
#35 0x000055555570d496 in run () at /home/hugo/src/tijolo/lib/gobject/src/gtk/gtk.cr:4
#36 0x000055555570c88d in run () at /home/hugo/src/tijolo/src/application.cr:131
#37 0x0000555555609e59 in __crystal_main () at /home/hugo/src/tijolo/src/main.cr:18
#38 0x0000555555785e66 in main_user_code () at /usr/lib/crystal/crystal/main.cr:105
#39 0x0000555555785cfc in main () at /usr/lib/crystal/crystal/main.cr:91
#40 0x0000555555615026 in main () at /usr/lib/crystal/crystal/main.cr:114
The other threads were just waiting...
#0 0x00007ffff6dd7e32 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0
#1 0x00007ffff6dfc555 in ?? () from /usr/lib/libgc.so.1
#2 0x00007ffff6dfc657 in ?? () from /usr/lib/libgc.so.1
#3 0x00007ffff6dd1422 in start_thread () from /usr/lib/libpthread.so.0
#4 0x00007ffff6c80bf3 in clone () from /usr/lib/libc.so.6
Environment: Archlinux, crystal 0.35, and debug versions of following Gtk packages: glib2 2.64.2-1
, gtk3 1:3.24.20-1
, gtksourceview4 4.6.0-1
.
If you manage to get past #37 and try to build something with require_gobject("Granite")
included, it fails:
syntax error in /usr/lib/x86_64-linux-gnu/girepository-1.0/Granite-1.0.typelib/ServicesLogger:12
Error: unexpected token: NEWLINE
I don't know if this is due to my hacking around the array constant however.
There's an array constant in this class (Granite-1.0.gir):
<class name="Application" c:type="GraniteApplication" glib:type-name="GraniteApplication" glib:get-type="granite_application_get_type" glib:t
ype-struct="ApplicationClass" parent="Gtk.Application" abstract="1" deprecated="1" deprecated-version="0.5.0">
<field name="parent_instance">
<type name="Gtk.Application" c:type="GtkApplication"/>
</field>
<field name="priv">
<type name="ApplicationPrivate" c:type="GraniteApplicationPrivate*"/>
</field>
<field name="build_data_dir">
<type name="utf8" c:type="gchar*"/>
</field>
...
<constant name="options" c:identifier="GRANITE_APPLICATION_options" value="(null)">
<array>
<type name="GLib.OptionEntry" c:type="GOptionEntry"/>
</array>
</constant>
Which results in:
Unhandled exception: Bug: Unhandled constant type ARRAY (Exception)
I tried making it at least compile:
--- constant_info_orig.cr 2020-01-20 07:24:10.511492609 +0000
+++ constant_info.cr 2020-01-20 07:23:23.614319006 +0000
@@ -49,6 +49,8 @@
when .utf8?
string = String.new(value.v_string)
string.inspect
+ when .array?
+ "# ARRAY CONSTANT #{name} #{size}" # ???
when .interface?
"# INTERFACE CONSTANT #{name} #{size}" # debug, should never end up being generated
else
@@ -60,6 +62,8 @@
def lib_definition
if type.tag.interface?
" # #{name} = ungeneratable value"
+ elsif type.tag.array?
+ " # #{name} = ???"
else
" #{name} = #{literal} # : #{type.lib_definition}"
end
And it works (now the bindings at least generate), but this probably isn't how it should be handled. I don't know enough about GIRs or C. StaticArray
?
Working on a small program which loads an image into a Gtk::Image.
I am trying to get the mouse (x,y) position when I click on the image and moves
the mouse. Using a Gtk::EventBox around the Gtk::Image.
Things seem to work, loading and displaying the image, capturing the mouse down and mouse move events
except I am not getting the correct x,y values.
Either these values are not set or most likely I am doing something wrong.
Here is the code
require "gobject/gtk/autorun"
builder = Gtk::Builder.new_from_file("#{__DIR__}/main.glade")
builder.connect_signals
window = Gtk::Window.cast builder["window1"]
# close application when window's 'x' button is clicked
window.connect("destroy", &->Gtk.main_quit)
window.set_default_size(1920,1080)
menu_filequit = Gtk::MenuItem.cast(builder["file_quit"])
menu_fileopen = Gtk::MenuItem.cast(builder["file_open"])
viewport = Gtk::Viewport.cast(builder["viewport1"])
imagebuffer = Gtk::Image.cast(builder["image1"])
eventbox = Gtk::EventBox.cast(builder["eventbox1"])
eventbox.events = Gdk::EventMask::EXPOSURE_MASK | Gdk::EventMask::LEAVE_NOTIFY_MASK | Gdk::EventMask::BUTTON_PRESS_MASK | Gdk::EventMask::POINTER_MOTION_MASK | Gdk::EventMask::POINTER_MOTION_HINT_MASK
statusbar1 = Gtk::Statusbar.cast(builder["statusbar1"])
filechooser_open = Gtk::Button.cast(builder["filechooser_open"])
filechooser_cancel = Gtk::Button.cast(builder["filechooser_cancel"])
filechooser_dialog = Gtk::FileChooserDialog.cast(builder["filechooserdialog1"])
# event is of type Gdk::EventButton
eventbox.on_button_press_event do |widget,eventbutton|
context_id = statusbar1.context_id("statusbar")
statusbar1.push(context_id, "mouse moved (#{eventbutton.x},#{eventbutton.y})")
true
end
# event is of type Gdk::EventMotion
eventbox.on_motion_notify_event do |widget,eventmotion|
context_id = statusbar1.context_id("statusbar")
statusbar1.push(context_id, "mouse moved (#{eventmotion.x},#{eventmotion.y})")
true
end
# exit application
menu_filequit.on_activate do |button|
exit
end
# file chooser dialog
menu_fileopen.on_activate do |button|
filechooser_dialog.show
end
filechooser_open.on_clicked do |button|
x = filechooser_dialog.filename()
if File.directory?(x) == false && File.readable?(x)
filechooser_dialog.hide()
window.title = window.title + " | " + "loaded image #{x}"
imagebuffer.file = x
end
end
filechooser_cancel.on_clicked do |button|
filechooser_dialog.hide()
end
# maximize shows title and window buttons
window.maximize
window.show_all
Hello.
Please tell me how to destroy GTK events.
I have an application that shows notifications, but there is one problem.
When a notification is viewed, i.e. an GTK event and no longer fall into this cycle for the next notifi:
while !Gtk.events_pending
Gtk.main_iteration
break if notification.on_closed { next true }
end
I am poorly versed in GTK and tried different options, and the best thing I think is to restart the application from myself with this code:
if Gtk.events_pending
File.write LOCK, e.pubDate
parent = Process.pid
fork = Process.fork do
Process.exec("#{PROGRAM_NAME}")
end
Process.kill(Signal::KILL, parent)
end
But the thought do this without restarting the application does not give me rest. :)
how would i remove Lib
from the following code?
# prints the supported filename extensions
list = GdkPixbuf::Pixbuf.formats
while !list.null?
list = list.as(LibGLib::SList*)
fp = list.value.data.as(LibGdkPixbuf::PixbufFormat*)
f = GdkPixbuf::PixbufFormat.new fp
f.extensions.each { |ext| puts ext }
list = list.value.next_
end
i have to cast pointers to the Lib
types
Tried to generate bindings for Gee:
require_gobject("Gee")
Results in:
There was a problem expanding macro 'require_gobject'
Code in src/gtk-test.cr:5:1
5 | require_gobject("Gee")
^
Called macro defined in lib/gobject/src/gobject.cr:7:1
7 | macro require_gobject(namespace)
Which expanded to:
> 1193 | get_remaining_capacity : -> Void
> 1194 | get_is_full : -> Void
> 1195 | UNBOUNDED_CAPACITY = -1 # : Int32
^
Error: expecting identifier 'end', not 'UNBOUNDED_CAPACITY'
It seems to generate an invalid struct:
> 1186 | struct Queue # interface
> 1187 | parent_iface : LibGObject::TypeInterface
> 1188 | offer : -> Void
> 1189 | peek : -> Void
> 1190 | poll : -> Void
> 1191 | drain : -> Void
> 1192 | get_capacity : -> Void
> 1193 | get_remaining_capacity : -> Void
> 1194 | get_is_full : -> Void
> 1195 | UNBOUNDED_CAPACITY = -1 # : Int32
> 1196 | # Requires Collection
> 1197 | # Virtual function offer
> 1198 | # Virtual function peek
> 1199 | # Virtual function poll
> 1200 | # Virtual function drain
> 1201 | # Virtual function get_capacity
> 1202 | # Virtual function get_remaining_capacity
> 1203 | # Virtual function get_is_full
> 1204 | # Property capacity : Int32
> 1205 | # Property remaining_capacity : Int32
> 1206 | # Property is_full : Bool
> 1207 | end
Currently code blocks just get left as is, it would be nice to have them parse properly. An example is this:
|[<!-- language="C" --> enum {
PROP_0,
PROP_FOO,
PROP_LAST
}; ]|
It should be possible to get the parser to recognize these blocks and swap them out for proper markdown blocks.
Following code doesn't compile:
require "gobject/gtk/autorun"
def changed(widget : Gtk::Editable)
puts Gtk::Entry.cast(widget).text
end
window = Gtk::Window.new(title: "Enter something!", border_width: 10)
window.connect "destroy", &->Gtk.main_quit
entry = Gtk::Entry.new
entry.on_changed(&->changed(Gtk::Editable))
window.add entry
window.show_all
Error:
Error target crash failed to compile:
Showing last frame. Use --error-trace for full trace.
There was a problem expanding macro 'require_gobject'
Code in lib/gobject/src/gtk/gtk.cr:7:1
7 | require_gobject "Gtk"
^
Called macro defined in lib/gobject/src/gobject.cr:8:1
8 | macro require_gobject(namespace)
Which expanded to:
> 29256 | callback = ->(arg0 : LibGtk::Editable*) {
> 29257 | return_value = block.call(Editable.new(arg0))
> 29258 | return_value
^--
Error: undefined method 'new' for Gtk::Editable:Module
(Hi, first of all, thanks for working on this โ I've been looking on GI bindings that work as compile-time macros / type providers, and for something to use Crystal forโฆ :D)
I can't get examples working, first there's this:
Code in macro 'require_gobject'
7 | require_gobject("Graphene")
^
Called macro defined in lib/gobject/gobject.cr:7:1
7 | macro require_gobject(namespace)
Which expanded to:
> 513 | VEC3_LEN = 3 # : Int32
> 514 | VEC4_LEN = 4 # : Int32
> 515 | false = 0 # : Int32
^
Error: unexpected token: false
I'm not sure why these constants are even there (reported: ebassi/graphene#180), but I added them to skip_info?
. Then, new error:
syntax error in /usr/local/lib/girepository-1.0/Graphene-1.0.typelib/Matrix:164
Error: expecting any of these tokens: IDENT, CONST, `, <<, <, <=, ==, ===, !=, =~, !~, >>, >, >=, +, -, *, /, //, !, ~
, %, &, |, ^, **, [], []?, []=, <=>, &+, &-, &*, &** (not 'NUMBER')
That one I'm not sure what's happeningโฆ why isn't there a snippet of the generated source?
(Also not sure why it's even trying to use Graphite, according to my package manager it's only a dependency of gstreamer1-plugins-gl
, while I'm not touching anything GStreamer related, just running Gtk examplesโฆ)
Not sure if this is caused by wrong GIR annotations on GtkSourceView [1], but the generated bindings for GtkSource::StyleSchemeManager#scheme
is not returing nil
when the C method returns a null pointer.
def scheme(scheme_id : ::String)
__return_value = LibGtkSource.style_scheme_manager_get_scheme(@pointer.as(LibGtkSource::StyleSchemeManager*), scheme_id.to_unsafe)
GtkSource::StyleScheme.new(__return_value)
end
So the following code crash:
require "gobject/gtk/autorun"
require_gobject "GtkSource"
GtkSource.init
manager = GtkSource::StyleSchemeManager.default
puts manager.to_unsafe
manager.scheme("any wrong id")
Backtrace
Pointer(LibGtkSource::StyleSchemeManager)@0x55fa564ff0e0
Invalid memory access (signal 11) at address 0x0
[0x55fa548e37f6] *CallStack::print_backtrace:Int32 +118
[0x55fa548d62ce] __crystal_sigfault_handler +286
[0x7f4d0efa5800] ???
[0x55fa5493a294] *GtkSource::StyleScheme +4
[0x55fa5493a286] *GtkSource::StyleScheme +6
[0x55fa5493a253] *GtkSource::StyleScheme#initialize<Pointer(LibGtkSource::StyleScheme)>:Nil +67
[0x55fa5493a1f8] *GtkSource::StyleScheme::new<Pointer(LibGtkSource::StyleScheme)>:GtkSource::StyleScheme +104
[0x55fa54939fe2] *GtkSource::StyleSchemeManager#scheme<String>:GtkSource::StyleScheme +66
[0x55fa548c1ae5] __crystal_main +1157
[0x55fa5493ad86] *Crystal::main_user_code<Int32, Pointer(Pointer(UInt8))>:Nil +6
[0x55fa548d633c] main +60
[0x7f4d0ed71023] __libc_start_main +243
[0x55fa548c158e] _start +46
[0x0] ???
I'm trying to build gi-doc so I can generate some documentation for myself. Unfortunately, running shards build
produces this error:
ฮป shards build
Dependencies are satisfied
Building: gi-generator
Building: gi-dump
Building: gi-doc
Error target gi-doc failed to compile:
/usr/bin/ld: /var/lib/snapd/snap/crystal/331/share/crystal/src/llvm/ext/llvm_ext.o: in function `llvm::MetadataTracking::track(llvm::Metadata*&)':
llvm_ext.cc:(.text._ZN4llvm16MetadataTracking5trackERPNS_8MetadataE[_ZN4llvm16MetadataTracking5trackERPNS_8MetadataE]+0x42): undefined reference to `llvm::MetadataTracking::track(void*, llvm::Metadata&, llvm::PointerUnion<llvm::MetadataAsValue*, llvm::Metadata*>)'
collect2: error: ld returned 1 exit status
Error: execution of command failed with code: 1: `cc "${@}" -o '/home/sim/Downloads/crystal-gobject/bin/gi-doc' -rdynamic -lz `command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libssl || printf %s '-lssl -lcrypto'` `command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libcrypto || printf %s '-lcrypto'` /var/lib/snapd/snap/crystal/331/share/crystal/src/llvm/ext/llvm_ext.o `/usr/bin/llvm-config --libs --system-libs --ldflags 2> /dev/null` -lstdc++ -lgirepository-1.0 -lxml2 -lpcre -lm /var/lib/snapd/snap/crystal/331/bin/../lib/crystal/lib/libgc.a -lpthread /var/lib/snapd/snap/crystal/331/share/crystal/src/ext/libcrystal.a -levent -lrt -ldl -L/var/lib/snapd/snap/crystal/331/bin/../lib/crystal/lib -L/var/lib/snapd/snap/crystal/331/bin/../lib/crystal/lib`
I've got all the dependencies and LLVM installed. Is this a problem on my end, or is this an issue with the build?
hello again, here's another Lib
usage:
def handler(event, data)
puts event.value.type
end
LibGdk.event_handler_set ->handler, nil, nil
you can add this to the gdk_window sample, anywhere before GLib::MainLoop
i develop some gobject-introspectable libraries in vala. as those are not packaged when i develop them, they tend to land in /usr/local/lib/x86_64-linux-gnu/girepository-1.0
instead of /usr/lib/x86_64-linux-gnu/girepository-1.0
.
Usually I am able to compensate with exporting the environment variable GI_TYPELIB_PATH:
export GI_TYPELIB_PATH=/usr/local/lib/x86_64-linux-gnu/girepository-1.0
However, crystal-gobject does not seem to be able to handle those libs. Strace shows that it indeed opens the correct typelib, but somehow fails to take the process further.
Strace for things in /usr
:
open("/usr/lib/x86_64-linux-gnu/girepository-1.0/GFlow-0.2.typelib", O_RDONLY) = 9
open("/usr/lib/girepository-1.0", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 8
Generate GFlow... open("src/generated/lib_g_flow.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
open("src/generated/g_flow/g_flow.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
open("src/generated/g_flow/node_error.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
open("src/generated/g_flow/simple_node.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
open("src/generated/g_flow/simple_node_private.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
open("src/generated/g_flow/simple_sink.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
open("src/generated/g_flow/simple_sink_private.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
open("src/generated/g_flow/simple_source.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
open("src/generated/g_flow/simple_source_private.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
open("src/generated/g_flow/dock.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
open("src/generated/g_flow/node.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
open("src/generated/g_flow/sink.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
open("src/generated/g_flow/source.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
open("src/generated/g_flow/module_functions.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
done.
Strace for things in /usr/local
:
open("/usr/local/lib/x86_64-linux-gnu/girepository-1.0", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 8
open("/usr/local/lib/x86_64-linux-gnu/girepository-1.0/GFlow-0.2.typelib", O_RDONLY) = 9
open("/usr/lib/x86_64-linux-gnu/girepository-1.0", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 8
open("/usr/lib/girepository-1.0", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 8
Generate GFlow... open("src/generated/lib_g_flow.cr", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644) = 8
Nil assertion failed (Exception)
open("./stage3", O_RDONLY|O_CLOEXEC) = 7
0x562cdccbb0b0: not_nil! at /opt/crystal/src/class.cr 65:0
0x562cdccaca5e: [] at /opt/crystal/src/string.cr 821:5
0x562cdcce6c0d: lib_definition at /home/grindhold/git/crystal-gobject/src/generator/namespace.cr 376:7
0x562cdcce67f5: write_lib at /home/grindhold/git/crystal-gobject/src/generator/namespace.cr 55:7
0x562cdcce6643: write at /home/grindhold/git/crystal-gobject/src/generator/namespace.cr 41:5
0x562cdcc7db34: __crystal_main at /home/grindhold/git/crystal-gobject/src/generator/generator.cr 23:1
0x562cdcc8ff39: main at /opt/crystal/src/main.cr 12:15
0x7f24c1fc82b1: __libc_start_main at ??
0x562cdcc7ccaa: _start at ??
0x0: ??? at ??
+++ exited with 1 +++
After the fix for #31, I tried building libgee again in the same way:
require_gobject("Gee")
Results in:
There was a problem expanding macro 'require_gobject'
Code in src/gtk-test.cr:5:1
5 | require_gobject("Gee")
^
Called macro defined in lib/gobject/src/gobject.cr:7:1
7 | macro require_gobject(namespace)
Which expanded to:
> 899 | fun future_wait_async = gee_future_wait_async(this : Future*, _callback : LibGio::AsyncReadyCallback, _callback__target : Void*) : Void
> 900 | fun future_wait_finish = gee_future_wait_finish(this : Future*, _res : LibGio::AsyncResult*, error : LibGLib::Error**) : Void*
> 901 | fun future_map = gee_future_map(this : Future*, a_type : UInt64, a_dup_func : LibGObject::BoxedCopyFunc, a_destroy_func : LibGLib::DestroyNotify, func : LibGee::FutureMapFunc, func_target : Void*, func_target_destroy_notify : LibGLib::DestroyNotify) : LibGee::Future*
^--------------------
Error: undefined constant LibGee::FutureMapFunc
Context (from error trace):
> 867 | struct Future # interface
> 868 | parent_iface : LibGObject::TypeInterface
> 869 | wait : -> Void
> 870 | wait_until : -> Void
> 871 | wait_async : -> Void
> 872 | wait_finish : -> Void
> 873 | map : -> Void
> 874 | light_map : -> Void
> 875 | light_map_broken : -> Void
> 876 | zip : -> Void
> 877 | flat_map : -> Void
> 878 | get_value : -> Void
> 879 | get_ready : -> Void
> 880 | get_exception : -> Void
> 881 | # Requires Object
> 882 | # Virtual function wait
> 883 | # Virtual function wait_until
> 884 | # Virtual function wait_async
> 885 | # Virtual function wait_finish
> 886 | # Virtual function map
> 887 | # Virtual function light_map
> 888 | # Virtual function light_map_broken
> 889 | # Virtual function zip
> 890 | # Virtual function flat_map
> 891 | # Virtual function get_value
> 892 | # Virtual function get_ready
> 893 | # Virtual function get_exception
> 894 | # Property ready : Bool
> 895 | # Property exception : LibGLib::Error**
> 896 | end
> 897 | fun future_wait = gee_future_wait(this : Future*, error : LibGLib::Error**) : Void*
> 898 | fun future_wait_until = gee_future_wait_until(this : Future*, end_time : Int64, value : Void**, error : LibGLib::Error**) : Bool
> 899 | fun future_wait_async = gee_future_wait_async(this : Future*, _callback : LibGio::AsyncReadyCallback, _callback__target : Void*) : Void
> 900 | fun future_wait_finish = gee_future_wait_finish(this : Future*, _res : LibGio::AsyncResult*, error : LibGLib::Error**) : Void*
> 901 | # line causing error below
> 901 | fun future_map = gee_future_map(this : Future*, a_type : UInt64, a_dup_func : LibGObject::BoxedCopyFunc, a_destroy_func : LibGLib::DestroyNotify, func : LibGee::FutureMapFunc, func_target : Void*, func_target_destroy_notify : LibGLib::DestroyNotify) : LibGee::Future*
> 902 | fun future_light_map = gee_future_light_map_fixed(this : Future*, a_type : UInt64, a_dup_func : LibGObject::BoxedCopyFunc, a_destroy_func : LibGLib::DestroyNotify, func : LibGee::FutureLightMapFunc, func_target : Void*, func_target_destroy_notify : LibGLib::DestroyNotify) : LibGee::Future*
> 903 | fun future_light_map_broken = gee_future_light_map(this : Future*, a_type : UInt64, a_dup_func : LibGObject::BoxedCopyFunc, a_destroy_func : LibGLib::DestroyNotify, func : LibGee::FutureLightMapFunc, func_target : Void*) : LibGee::Future*
> 904 | fun future_zip = gee_future_zip(this : Future*, a_type : UInt64, a_dup_func : LibGObject::BoxedCopyFunc, a_destroy_func : LibGLib::DestroyNotify, b_type : UInt64, b_dup_func : LibGObject::BoxedCopyFunc, b_destroy_func : LibGLib::DestroyNotify, zip_func : LibGee::FutureZipFunc, zip_func_target : Void*, second : LibGee::Future*) : LibGee::Future*
> 905 | fun future_flat_map = gee_future_flat_map(this : Future*, a_type : UInt64, a_dup_func : LibGObject::BoxedCopyFunc, a_destroy_func : LibGLib::DestroyNotify, func : LibGee::FutureFlatMapFunc, func_target : Void*, func_target_destroy_notify : LibGLib::DestroyNotify) : LibGee::Future*
> 906 | fun future_get_value = gee_future_get_value(this : Future*) : Void*
> 907 | fun future_get_ready = gee_future_get_ready(this : Future*) : Bool
> 908 | fun future_get_exception = gee_future_get_exception(this : Future*) : LibGLib::Error**
Possibly the relevant file within Gee:
https://github.com/GNOME/libgee/blob/5e66324654b7d70d7c28793491a4edfe6d8a0d85/gee/future.vala#L132
Hi.
I was reading the Gtk documentation, and found that some classes, i.e. Gtk::ApplicationWindow
, implement some interfaces, i.e. Gio::ActionMap
.
The thing is it doesn't look like it's been mapped to crystal by the generator.
I found putting this at my project make it work:
module Gtk
class Application
include Gio::ActionMap
end
class ApplicationWindow
include Gio::ActionMap
end
end
Then I found the following code:
crystal-gobject/src/g_i_repository/info/object_info.cr
Lines 69 to 72 in 3022dec
And tried to change it to include #{interface.namespace}::#{interface.name}
, but it seems to crash in some references.
Is there any plans to make it work at "generator-time" or do you think it's better to patch it by the consumer?
I'm experiencing a crash with GtkSourceView, looks like a memory corruption, a bad cast... not sure.
I wrote a similar line-by-line C version and it works perfectly, the Crystal version crash with
$ ./bin/crash
Markup/Markdown
Invalid memory access (signal 11) at address 0x0
[0x56443a8eab76] *CallStack::print_backtrace:Int32 +118
[0x56443a8dd64e] __crystal_sigfault_handler +286
[0x7f52fcd17800] ???
[0x7f52fcf016e4] pcre_exec +3156
[0x7f52fcfa331d] g_match_info_next +157
[0x7f52fcfa4510] g_regex_match_full +128
[0x7f52fcfa46b9] g_regex_replace_eval +201
[0x7f52fde1941d] ???
[0x7f52fde25ab7] ???
[0x7f52fde24c4f] ??? (5 times)
[0x7f52fde4ff4d] ???
[0x7f52fde6a6d6] gtk_source_buffer_set_language +294
[0x56443a941623] *GtkSource::Buffer#language=<(GtkSource::Language | Nil)>:Nil +67
[0x56443a8c8da7] __crystal_main +1767
[0x56443a942446] *Crystal::main_user_code<Int32, Pointer(Pointer(UInt8))>:Nil +6
[0x56443a8dd6bc] main +60
[0x7f52fcae3023] __libc_start_main +243
[0x56443a8c85ee] _start +46
[0x0] ???
Crystal code:
require "gobject/gtk/autorun"
require_gobject "GtkSource"
GtkSource.init
builder = Gtk::Builder.new_from_file("#{__DIR__}/main.glade")
builder.connect_signals
# Get editor
editor = GtkSource::View.cast(builder["editor"])
buffer = GtkSource::Buffer.cast(editor.buffer)
buffer.set_text("Some contents", -1)
# Here the problem, seems to be just with markdown syntax.
lang = GtkSource::LanguageManager.default.guess_language("README.md", nil)
puts "#{lang.try(&.section)}/#{lang.try(&.name)}"
buffer.language = lang
# Show main window
main_window = Gtk::Window.cast(builder["main_window"])
main_window.show_all
C version
#include <gtk/gtk.h>
#include <gtksourceview/gtksource.h>
int main(int argc, char *argv[]) {
gtk_init(&argc, &argv);
gtk_source_init();
GtkBuilder* builder = gtk_builder_new_from_file("./src/main.glade");
gtk_builder_connect_signals(builder, NULL);
// get editor
GtkSourceView* editor = GTK_SOURCE_VIEW(gtk_builder_get_object(builder, "editor"));
GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(editor));
gtk_text_buffer_set_text(buffer, "Some contents", -1);
// Sets markdown syntax
GtkSourceLanguageManager* manager = gtk_source_language_manager_get_default();
GtkSourceLanguage* lang = gtk_source_language_manager_guess_language(manager, "README.md", NULL);
if (lang)
printf("%s/%s\n", gtk_source_language_get_section(lang), gtk_source_language_get_name(lang));
gtk_source_buffer_set_language(GTK_SOURCE_BUFFER(buffer), lang);
// Show main window
GtkWidget* window = GTK_WIDGET(gtk_builder_get_object(builder, "main_window"));
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
gtk_source_finalize();
}
XML used by GTK builder in the examples above.
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<requires lib="gtksourceview" version="4.0"/>
<object class="GtkApplicationWindow" id="main_window">
<property name="can_focus">False</property>
<property name="default_width">800</property>
<property name="default_height">600</property>
<signal name="destroy" handler="gtk_main_quit" swapped="no"/>
<child type="titlebar">
<placeholder/>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkSourceView" id="editor">
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
Works like the C version, i.e. just show a blank window with the text "Some Contents"
A crash.
The weird info is that if I change the file name used to guess the language to e.g. "foo.yaml", it doesn't crash.
Tested on ArchLinux GTK package gtk3 1:3.24.20-1
, GTK source view package gtksourceview4 4.6.0-1
.
C version compiled with:
gcc `pkg-config --cflags gtk+-3.0` `pkg-config --cflags gtksourceview-4` crash.c -o crash_c `pkg-config --libs gtk+-3.0` `pkg-config --libs gtksourceview-4`
The generated bindings only show a subset of the C API https://developer.gnome.org/gtk3/stable/GtkMessageDialog.html, and as expected the wrapper only wrap this subset.
struct MessageDialog # object
parent_instance : LibGtk::Dialog*
priv : LibGtk::MessageDialogPrivate*
# Property buttons : LibGtk::ButtonsType
# Property image : LibGtk::Widget*
# Property message_area : LibGtk::Widget*
# Property message_type : LibGtk::MessageType
# Property secondary_text : UInt8*
# Property secondary_use_markup : Bool
# Property text : UInt8*
# Property use_markup : Bool
end
fun message_dialog_get_image = gtk_message_dialog_get_image(this : MessageDialog*) : LibGtk::Widget*
fun message_dialog_get_message_area = gtk_message_dialog_get_message_area(this : MessageDialog*) : LibGtk::Widget*
fun message_dialog_set_image = gtk_message_dialog_set_image(this : MessageDialog*, image : LibGtk::Widget*) : Void
fun message_dialog_set_markup = gtk_message_dialog_set_markup(this : MessageDialog*, str : UInt8*) : Void
As the gtk_message_dialog_new
isn't available, creating these objects (without gtk builder) are impossible.
Bind generator doesn't use the GIR [array length=data_size]
annotation, e.g. the Gio function:
gchar *
g_content_type_guess (const gchar *filename,
const guchar *data,
gsize data_size,
gboolean *result_uncertain);```
Has the annotations:
Parameter | Type | Annotation |
---|---|---|
filename | a string, orย NULL. | [nullable] |
data | a stream of data, orย NULL. | [nullable][arraylength=data_size] |
data_size | the size ofย data | ย |
result_uncertain | return location for the certainty of the result, orย NULL. | [out][optional] |
And the generated binding is:
def self.content_type_guess(filename : ::String?, data : ::String, data_size : ::Int, result_uncertain : Bool?)
__return_value = LibGio.content_type_guess(filename ? filename.to_unsafe : nil, data ? data : nil, UInt64.new(data_size), result_uncertain)
GObject.raise_unexpected_null("g_content_type_guess") if __return_value.null?
::String.new(__return_value)
end
To make things more Crystal like it would be:
def self.content_type_guess(filename : ::String?, result_uncertain : Bool?)
__return_value = LibGio.content_type_guess(filename ? filename.to_unsafe : nil, data ? data : nil, filename ? filename.size : 0, out result_uncertain)
GObject.raise_unexpected_null("g_content_type_guess") if __return_value.null?
::String.new(__return_value)
end
BTW, this result_uncertain
parameter is unusable the way it's now, but this is another issue, maybe if the parameter have the out
annotation and it's a C primitive type, we could put it on return value as a Tuple with the current return value.
TreeView row-activated
signal is generating a bad signature.
GTK docs at https://developer.gnome.org/gtk3/stable/GtkTreeView.html#GtkTreeView-row-activated says the user function should be:
void user_function(GtkTreeView *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
gpointer user_data)
But the generated bindings have:
alias RowActivatedSignal = TreeView, Gtk::TreePath, Gtk::TreeViewColumn ->
def on_row_activated(&__block : RowActivatedSignal)
__callback = ->(_arg0 : LibGtk::TreeView*, _arg1 : LibGtk::TreePath*, _arg2 : LibGtk::TreeViewColumn**) {
__return_value = __block.call(TreeView.new(_arg0), Gtk::TreePath.new(_arg1), Gtk::TreeViewColumn.new(_arg2))
__return_value
}
connect("row-activated", __callback)
end
This doesn't compile, but if we monkey patch it with:
module Gtk
class Gtk::TreeViewColumn
def initialize(pointer : Pointer(Pointer(LibGtk::TreeViewColumn)))
@pointer = pointer.as(Void*)
end
end
end
it does, however the TreePath object is all zeros:
Crystal code to test it (using the glade file from examples)
require "gobject/gtk/autorun"
builder = Gtk::Builder.new_from_file("#{__DIR__}/../lib/gobject/samples/tree_view.glade")
builder.connect_signals
# Insert something into the model
model = Gtk::TreeStore.cast(builder["tree_model"])
root = Gtk::TreeIter.new
model.append(root, nil)
model.set(root, [0], GObject::Value.new("Root"), 1)
module Gtk
class Gtk::TreeViewColumn
def initialize(pointer : Pointer(Pointer(LibGtk::TreeViewColumn)))
@pointer = pointer.as(Void*)
end
end
end
# view
view = Gtk::TreeView.cast(builder["tree_view"])
puts "TreeView ptr before signal: #{view.to_unsafe}"
view.on_row_activated do |view, path, column|
puts "TreeView ptr inside signal: #{view.to_unsafe}"
puts "Path is empty!?: #{path.to_unsafe.value}"
puts "Column pointer: #{column.to_unsafe}"
end
# Show main view.
main_window = Gtk::Window.cast(builder["main_window"])
main_window.show_all
The initial bug is the signal generated code, but this path issue seems like some memory corruption too and need some investigation, a C example doesn't behave like that, I can write down a C example if it helps to debug the issue.
Hello ! I've been monitoring this project for a while, since I want to use gtk for a crystal application I plan on writing.
I saw you're still pushing commits every once in a while. Could you provide more details as to how usable this project is ? What works and what would be likely to break, if anything ?
Also, I'm quite curious as to how you generated these bindings. I searched a bit how bindings work in Crystal, and found the bindgen tool that can autogenerate bindings for a C library. Are you using something similar ? If I needed to add to or fix some bindings the ones you've already implemented, would bindgen be a good solution ?
Thank you !
i created some bindings to cairo.h
, and naturally i want to name the lib LibCairo
, which causes confusion with Libcairo
from this repo.
edit: alternatively, generate and include the cairo.h
bindings here
Hi, i just started with GTK so if something is wrong on my part, i apologize.
I am trying to make a custom right click menu. The code below throws a Error: wrong number of block argument's arguments (given 1, expected 0)
:
connect("button-press-event", &->(e : Gdk::EventButton){
if e.type == Gdk::EventType::BUTTON_PRESS && e.button == Gdk::BUTTON_SECONDARY
menu.popup_at_pointer(e)
end
false
})
This is the entire code:
require "gobject/gtk"
require "gobject/g_lib"
class MainWindow < Gtk::ApplicationWindow
def self.new(app : Gtk::Application)
super
end
def initialize(ptr)
super(ptr)
self.border_width = 100
self.title = "Hello"
add Gtk::Label.new("Hello")
hide_titlebar_when_maximized = true;
maximize
wallpaper_item = Gtk::MenuItem.new_with_label("Change Wallpaperโฆ")
displays_item = Gtk::MenuItem.new_with_label("Display Settingsโฆ")
separator = Gtk::SeparatorMenuItem.new
settings_item = Gtk::MenuItem.new_with_label("System Settingsโฆ")
menu = Gtk::Menu.new
menu.attach_to_widget(self, nil)
menu.append(wallpaper_item);
menu.append(displays_item);
menu.append(separator);
menu.append(settings_item);
menu.show_all
connect("button-press-event", &->(e : Gdk::EventButton){
if e.type == Gdk::EventType::BUTTON_PRESS && e.button == Gdk::BUTTON_SECONDARY
menu.popup_at_pointer(e)
end
false
})
# More to do down here
end
end
class MyApp < Gtk::Application
def self.new(id, flags : Gio::ApplicationFlags)
super
end
def initialize(ptr)
super(ptr)
on_activate do |application|
window = MainWindow.new(self)
window.show_all
end
end
end
app = MyApp.new("org.crystal.mysample", :flags_none)
app.run()
In C we can connect signals using the macro g_signal_connect_after
, that just connect the signal using the AFTER flag.
This is useful to e.g. connect focus-out-event
signal, so your code is ran after the default signal handlers and some GTK widgets get happy with this.
My suggestion if to use a after_
prefix to connect these signals, e.g. for GtkWidget focus-out-event we would have on_focus_out_event
and after_focus_out_event
.
I tried to mimic this with current signals implementation but got no luck on my first tries:
require "gobject/gtk/autorun"
module Gtk
class Widget
def after_focus_out_event(&block : FocusOutEventSignal)
__var0 = ->(arg0 : LibGtk::Widget*, arg1 : LibGdk::EventFocus*, box : Void*) {
::Box(FocusOutEventSignal).unbox(box).call(Widget.new(arg0), arg1.null? ? GObject.raise_unexpected_null("event in focus_out_event") : Gdk::EventFocus.new(arg1))
}
__var1 = ::Box.box(FocusOutEventSignal.new { |arg0, arg1|
block.call(arg0, arg1)
})
LibGObject.signal_connect_data(@pointer.as(LibGObject::Object*), "focus-out-event", LibGObject::Callback.new(__var0.pointer, Pointer(Void).null), GObject::ClosureDataManager.register(__var1), ->GObject::ClosureDataManager.deregister, GObject::ConnectFlags::AFTER)
end
end
end
def hey(widget, event)
puts "hey"
false
end
def ho(widget, event)
puts "ho"
true
end
window = Gtk::Window.new(title: "Enter something!", border_width: 10)
window.connect "destroy", &->Gtk.main_quit
box = Gtk::Box.new(orientation: :vertical, spacing: 6)
window.add(box)
entry1 = Gtk::Entry.new
entry1.on_focus_out_event(&->hey(Gtk::Widget, Gdk::EventFocus))
entry1.after_focus_out_event(&->ho(Gtk::Widget, Gdk::EventFocus))
entry2 = Gtk::Entry.new
box.add(entry1)
box.add(entry2)
window.show_all
This was trying to mimic this C code:
#include <gtk/gtk.h>
#include <gtksourceview/gtksource.h>
gboolean focus_out1(GtkWidget *widget, GdkEvent *event,gpointer user_data) {
printf("hey\n");
return 0;
}
gboolean focus_out2(GtkWidget *widget, GdkEvent *event,gpointer user_data) {
printf("ho\n");
return 1;
}
int main(int argc, char *argv[]) {
gtk_init(&argc, &argv);
gtk_source_init();
GtkWidget* wnd = gtk_window_new(0);
g_signal_connect(wnd, "destroy", G_CALLBACK(gtk_main_quit), wnd);
GtkWidget* box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
gtk_container_add(GTK_CONTAINER(wnd), GTK_WIDGET(box));
GtkWidget* entry1 = gtk_entry_new();
GtkWidget* entry2 = gtk_entry_new();
g_signal_connect_data(entry1, "focus-out-event", G_CALLBACK(focus_out1), 0, 0, 0);
g_signal_connect_data(entry1, "focus-out-event", G_CALLBACK(focus_out2), 0, 0, G_CONNECT_AFTER);
// g_signal_connect(entry1, "focus-out-event", G_CALLBACK(focus_out1), entry1);
// g_signal_connect_after(entry1, "focus-out-event", G_CALLBACK(focus_out2), entry1);
gtk_container_add(GTK_CONTAINER(box), entry1);
gtk_container_add(GTK_CONTAINER(box), entry2);
// g_signal_connect(wnd, )
gtk_widget_show_all(GTK_WIDGET(wnd));
gtk_main();
gtk_source_finalize();
}
The following program fail to compile
require "gobject/gtk"
require_gobject "GtkSource"
class TroubleMaker
getter widget : Gtk::Label
def initialize(builder)
@widget = Gtk::Label.cast(builder["label"])
end
end
LibGtk.init pointerof(ARGC_UNSAFE), pointerof(ARGV_UNSAFE)
GtkSource.init
builder = Gtk::Builder.new_from_string(<<-EOF, -1)
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.36.0 -->
<interface>
<requires lib="gtk+" version="3.22"/>
<object class="GtkApplicationWindow" id="main_window">
<property name="can_focus">False</property>
<signal name="destroy" handler="gtk_main_quit" swapped="no"/>
<child>
<placeholder/>
</child>
<child type="titlebar">
<placeholder/>
</child>
</object>
<object class="GtkLabel" id="label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
</interface>
EOF
builder.connect_signals
main_window = Gtk::Window.cast(builder["main_window"])
trouble = TroubleMaker.new(builder)
# Compilation fail: Error: can't cast (Pointer(LibGtk::AccelLabel) | Pointer(LibGtk::Label)) to Pointer(LibGtk::Widget)
main_window.add(trouble.widget)
# But this works
# widget = Gtk::Label.cast(builder["label"])
# main_window.add(widget)
main_window.show_all
LibGtk.main
It fails with the error:
Which expanded to:
> 13937 | def add(widget : Gtk::Widget)
> 13938 | LibGtk.container_add(@pointer.as(LibGtk::Container*), widget.to_unsafe.as(LibGtk::Widget*))
> 13939 | nil
^
Error: can't cast (Pointer(LibGtk::AccelLabel) | Pointer(LibGtk::Label)) to Pointer(LibGtk::Widget)
If I use Gtk::Widget instead of Gtk::Label it fails as well, just the union is bigger with all know widget subclasses.
Show a small window with a label inside.
It fails to compile.
hello
first of all thank for this great work
trying the sample gtk_sample.cr I got this error
crystal run samples/gtk_sample.cr
Showing last frame. Use --error-trace for full trace.
In src/lib_cairo.cr:20:18
20 | rectangles : LibCairo::Rectangle*
^------------------
Error: undefined constant LibCairo::Rectangle
please note that crystal-gobject (another great work) samples work on my machine
is it a problem with my cairo release ?
my env. is
Linux Mint19 5.3.0-40-generic #32~18.04.1-Ubuntu SMP
libgtk 3.22.30 (standard installed)
libcairo, libcairo-gobject2 1.15.10
thanks for help
Hi,
When I use version 0.8.0 I am getting the following error
Showing last frame. Use --error-trace for full trace.
In lib/gobject/src/gtk/gtk.cr:18:7
18 | connect_signals nil
^--------------
Error: no overload matches 'Gtk::Builder#connect_signals' with type Nil
Overloads are:
- Gtk::Builder#connect_signals(user_data : ::Pointer(Void))
- Gtk::Builder#connect_signals()
This error does not occur when I use branch v0.3.1
dependencies:
gobject:
github: jhass/crystal-gobject
branch: v0.3.1
crystal build samples/gtk_hello_world.cr
Error in samples/gtk_hello_world.cr:5: instantiating 'Gtk::Window#connect(String)'
window.connect "destroy", &->Gtk.main_quit
^~~~~~~
in src/g_object/object.cr:10: instantiating 'connect(String, Proc(Nil))'
connect signal, callback
^~~~~~~
in src/g_object/object.cr:14: instantiating 'UInt64#tap()'
LibGObject.signal_connect_data(to_unsafe.as(LibGObject::Object*),
^~~
in src/g_object/object.cr:14: instantiating 'UInt64#tap()'
LibGObject.signal_connect_data(to_unsafe.as(LibGObject::Object*),
^~~
in src/g_object/object.cr:21: instantiating 'type_name()'
raise ArgumentError.new("Couldn't connect signal #{signal} to #{type_name} (#{self.class})")
^~~~~~~~~
in src/g_object/object.cr:63: instantiating 'type()'
GObject.type_name(type)
^~~~
in src/generated/gtk/window.cr:157: undefined fun 'window_get_type' for LibGtk
__return_value = LibGtk.window_get_type(to_unsafe.as(LibGtk::Window*))
^~~~~~~~~~~~~~~
Even after running the generator, the "window_get_type" is not generated. To make it work I edited the files and added manually the line
fun window_get_type = gtk_window_get_type(this : Window*) : LibGdk::WindowType
libgtk3 version: 3.18.9-1ubuntu3.3
Crystal version 0.23.1 [e2a1389e8] (2017-07-13) LLVM 3.8.1
If the block used on Glib.timeout
method access some member variable one line before it returns, the return value get some memory garbage and GTK think it's true, not false.
Compile and run the following code with -Dpreview_mt
.
require "log"
require "gobject/gtk/autorun"
window = Gtk::Window.new(title: "Hello World!", border_width: 10)
window.connect("destroy", &->Gtk.main_quit)
button = Gtk::Button.new label: "Hello World!"
button.connect("clicked", &->window.destroy)
window.add(button)
window.show_all
class Foo
@var = "hey"
def bar
spawn do
puts "Hi, I'm a new thread."
GLib.timeout(0) do
puts "I'm on main thread"
# access instance vars inside the block before the return call creates the problem
# comment this line and it works
@var = "ok"
# If uncomment this line, everything works too.
# Log.info { "fix" }
false
end
end
end
end
f = Foo.new
f.bar
A new version of pango and harfbuzz landed in Archlinux package repositories, when using then the generated bindings fail to compile, the problem seems to be on Harfbuzz, but Pango depends on Harfbuzz.
Broken versions:
Pango: 1.46.0
Harfbuzz: 2.7.1
Versions that work:
Pango: 1.44.7
Harfbuzz: 2.7.0
Test can be done with files under project sample directory:
$ crystal run gdk_window.cr
There was a problem expanding macro 'require_gobject'
Code in macro 'require_gobject'
7 | require_gobject("HarfBuzz", "0.0")
^
Called macro defined in lib/gobject/gobject.cr:25:1
25 | macro require_gobject(namespace, version = nil)
Which expanded to:
> 553 | ###########################################
> 554 |
> 555 | union hb_var_int_t
^
Error: expecting token 'CONST', not 'hb_var_int_t'
code 1
Hi there!
I'd like to use Glade templates in my Gtk application but I'm stuck with Error: undefined method 'set_template_from_resource' for Gtk::Widget.class
.
It seems that Gtk::Widget.class should implement set_template_from_resource
or set_template
https://lazka.github.io/pgi-docs/Gtk-3.0/classes/WidgetClass.html#Gtk.WidgetClass.set_template_from_resource to get it work.
To give you more context I'm rewriting a Ruby/Gtk3 application to Crystal/Gtk3 (https://github.com/jbox-web/ssh-tunnel) so I'm already using this technique and it works pretty well : https://github.com/jbox-web/ssh-tunnel/blob/master/lib/ssh-tunnel/ui/windows/application_window.rb
For creating terminal-emulators, https://developer.gnome.org/vte/unstable/VteTerminal.html is very useful, and support for it in crystal-gobject would be nice (perhaps it exists already, but a couple ripgrep's can't find it :/)
Gdk::WindowAttr.new(
event_mask: Gdk::EventMask::ZERO_NONE
)
no overload matches 'Gdk::WindowAttr.new', event_mask: LibGdk::EventMask
Overloads are:
- Gdk::WindowAttr.new(title : String | Nil = nil, event_mask : Int32 | Nil = nil, x : Int32 | Nil = nil, y : Int32 | Nil = nil, width : Int32 | Nil = nil, height : Int32 | Nil = nil, wclass : Gdk::WindowWindowClass | Nil = nil, visual : Gdk::Visual | Nil = nil, window_type : Gdk::WindowType | Nil = nil, cursor : Gdk::Cursor | Nil = nil, wmclass_name : String | Nil = nil, wmclass_class : String | Nil = nil, override_redirect : Bool | Nil = nil, type_hint : Gdk::WindowTypeHint | Nil = nil)
- Gdk::WindowAttr.new(gdk_window_attr : ::Pointer(LibGdk::WindowAttr))
also the flags have type UInt32
, but WindowAttr
wants them as Int32
Next problem after #33 was fixed:
Called macro defined in lib/gobject/gobject.cr:7:1
7 | macro require_gobject(namespace)
Which expanded to:
> 6463 | fun editable_delegate_get_property = gtk_editable_delegate_get_property(object : LibGObject::Object*, prop_id : UInt32, value : LibGObject::Value*, pspec : LibGObject::ParamSpec*) : Bool
> 6464 | fun editable_delegate_set_property = gtk_editable_delegate_set_property(object : LibGObject::Object*, prop_id : UInt32, value : LibGObject::Value*, pspec : LibGObject::ParamSpec*) : Bool
> 6465 | fun editable_install_properties = gtk_editable_install_properties(object_class : LibGObject::ObjectClass*, first_prop : UInt32) : UInt32
^----------------------
Error: undefined constant LibGObject::ObjectClass
(gtk3-3.24.10)
crystal build samples/greeter.cr
Error in samples/greeter.cr:27: instantiating 'greet(Gtk::Button+, Gtk::Window, Gtk::Label, Gtk::Entry)'
greet button, info, info_text, name
^~~~~
in samples/greeter.cr:12: instantiating 'Gtk::Button+#sensitive=(Bool)'
button.sensitive = false
^~~~~~~~~
in src/generated/gtk/widget.cr:1354: can't cast (Pointer(LibGtk::Button) | Pointer(LibGtk::CheckButton) | Pointer(LibGtk::ColorButton) | Pointer(LibGtk::FontButton) | Pointer(LibGtk::LinkButton) | Pointer(LibGtk::LockButton) | Pointer(LibGtk::MenuButton) | Pointer(LibGtk::ModelButton) | Pointer(LibGtk::RadioButton) | Pointer(LibGtk::ScaleButton) | Pointer(LibGtk::ToggleButton) | Pointer(LibGtk::VolumeButton)) to Pointer(LibGtk::Widget)
LibGtk.widget_set_sensitive(to_unsafe.as(LibGtk::Widget*), sensitive)
^
libgtk3 version: 3.18.9-1ubuntu3.3
Crystal version 0.23.1 [e2a1389e8] (2017-07-13) LLVM 3.8.1
It would be nice to have a sample on how to instantiate and use a Gtk::Application object
require "gobject/gdk"
attr = LibGdk::WindowAttr.new
win = Gdk::Window.new nil, attr, 0
$ crystal civ.cr
Error in ./civ.cr:4: instantiating 'Gdk::Window:Class#new(Nil, LibGdk::WindowAttr, Int32)'
win = Gdk::Window.new nil, attr, 0
^~~
in ./libs/gobject/generated/gdk/window.cr:13: struct LibGdk::WindowAttr has no field 'to_unsafe'
__return_value = LibGdk.window_new(parent && parent.to_unsafe.as(LibGdk::Window*), attributes.to_unsafe.as(LibGdk::WindowAttr*), attributes_mask)
^~~~~~~~~
i'm not clear on when to use LibGdk
vs Gdk
edit: it looks like we're supposed to do this?:
attrV = LibGdk::WindowAttr.new
attr = Gdk::WindowAttr.new pointerof(attrV)
Not sure what is happening here, but most of the samples don't work anymore
$ crystal version
Crystal 0.34.0 [4401e90f0] (2020-04-06)
LLVM: 8.0.0
Default target: x86_64-unknown-linux-gnu
shard.yml
dependencies:
gobject:
github: jhass/crystal-gobject
version: ~> 0.8.0
Error when trying to run a sample
crystal build gtk_menu_and_actions.cr
M-yA-pplication.o: In function `initialize:application_id':
/home/laptop/try/gtk/lib/gobject/samples/lib/gobject/gtk/gtk.cr:4: undefined reference to `g_object_new_with_properties'
G-tk5858A-pplicationW-indow.o: In function `initialize:application:title:default_width:default_height:icon_name':
/home/laptop/try/gtk/lib/gobject/samples/lib/gobject/gtk/gtk.cr:4: undefined reference to `g_object_new_with_properties'
G-tk5858M-enuI-tem.o: In function `initialize:label':
/home/laptop/try/gtk/lib/gobject/samples/lib/gobject/gtk/gtk.cr:4: undefined reference to `g_object_new_with_properties'
collect2: error: ld returned 1 exit status
Error: execution of command failed with code: 1: `cc "${@}" -o '/home/laptop/try/gtk/lib/gobject/samples/gtk_menu_and_actions' -rdynamic -lgdk-3 -lgtk-3 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lgobject-2.0 -lglib-2.0 -lpcre -lm /usr/bin/../lib/crystal/lib/libgc.a -lpthread /usr/share/crystal/src/ext/libcrystal.a -levent -lrt -ldl -L/usr/bin/../lib/crystal/lib -L/usr/bin/../lib/crystal/lib`
I use XUbuntu19.10 (gir1.2-freedesktop 1.62.0-1)
Compile-time bindings has follow code :
def children
__return_value = LibGtk.container_get_children(@pointer.as(LibGtk::Container*))
GObject.raise_unexpected_null("gtk_container_get_children") if __return_value.null?
GLib::ListIterator(Gtk::Widget, LibGtk::Widget*).new(GLib::SList.new(__return_value.as(LibGLib::List*)))
end
Matter in
GLib::SList.new
because
LibGtk.container_get_children
returns
LibGLib::List*
In my opinion, this method must have code as is follow:
def children
__return_value = LibGtk.container_get_children(@pointer.as(LibGtk::Container*))
GObject.raise_unexpected_null("gtk_container_get_children") if __return_value.null?
GLib::ListIterator(Gtk::Widget, LibGtk::Widget*).new(GLib::List.new(__return_value.as(LibGLib::List*)))
end
Hi, I'm translating some examples from Ruby-gnome2 bindings. The example Apps dir contains classes that inherits from Gtk::Application . I tried this:
require "gtk"
class ExampleAppWindow < Gtk::ApplicationWindow
def open(file)
end
end
class ExampleApp < Gtk::Application
def initialize
super # <----- error
on_activate do |application|
window = ExampleAppWindow.new(application)
window.present
end
...
end
I got:
wrong number of arguments for 'Gtk::Application#initialize' (given 0, expected 1)
Overloads are:
- Gtk::Application#initialize(pointer : ::Pointer(LibGtk::Application))
super
^~~~~
I'm trying to generate bindings for libvips:
GIRepository::Repository.instance.require "Vips"
Namespace.new("Vips").write "src/generated"
but it throws error:
Nil assertion failed (Exception)
0x10f34e1a5: *CallStack::unwind:Array(Pointer(Void)) at ??
0x10f34e141: *CallStack#initialize:Array(Pointer(Void)) at ??
0x10f34e118: *CallStack::new:CallStack at ??
0x10f335c85: *raise<Exception>:NoReturn at ??
0x10f335c31: *raise<String>:NoReturn at ??
0x10f37e363: *Nil#not_nil!:NoReturn at ??
0x10f36ed5b: *String#[]<Regex, Int32>:String at ??
0x10f3b095b: *Namespace#lib_definition<File>:Nil at ??
0x10f3b0609: *Namespace#write_lib<String>:Nil at ??
0x10f3b0475: *Namespace#write<String>:Nil at ??
0x10f335719: __crystal_main at ??
0x10f34aa98: main at ??
Crystal version: 0.23.0
vips version: 8.5.6
Hello!
I've tried gtk_hello_world
and gdk_window
samples, but they don't compile:
Error in src/shine-panel.cr:6: instantiating 'Gtk::Window:Class#new()'
window = Gtk::Window.new
^~~
in lib/gobject/src/gtk/gtk.cr:47: instantiating 'new(LibGtk::WindowType)'
new LibGtk::WindowType::TOPLEVEL
^~~
in lib/gobject/src/generated/gtk/window.cr:50: instantiating 'cast(Gtk::Widget)'
cast Gtk::Widget.new(__return_value)
^~~~
in lib/gobject/src/generated/gtk/window.cr:4: expanding macro
class Window < Bin
^
in macro 'inherited' expanded macro: included:1, line 3:
1. # Add run-time check
2. def self.cast(object) : self
> 3. new(object.to_unsafe as LibGtk::Window*)
4. end
5.
wrong number of arguments for 'Gtk::Widget#to_unsafe' (given 1, expected 0)
Overloads are:
- Gtk::Widget#to_unsafe()
- GObject::InitiallyUnowned#to_unsafe()
- GObject::Object#to_unsafe()
Crystal version is 0.20.3
GTK 3.22.6
Thanks.
I get the following:
$ shards install
Resolving dependencies
Fetching https://github.com/jhass/crystal-gobject.git
Installing gobject (0.3.0 at 09f02b85e533e6cdb74a96c78ef76727fac53b56)
Unhandled exception: Error creating symlink: '../../lib' -> '/home/renich/test/lib/gobject/lib': File exists (File::AlreadyExistsError)
from Crystal::System::File::symlink<String, String>:Int32
from File::symlink<String, String>:Int32
from Shards::Package#install:(Int32 | Nil)
from Shards::Commands::Install#install<Shards::Package>:(Shards::Package | Nil)
from Shards::Commands::Install#install<Array(Shards::Package)>:Nil
from Shards::Commands::Install#run:Nil
from Shards::Commands::Install
from ~procProc(Array(String), Array(String), Nil)
from OptionParser::ParseTask#parse:Nil
from OptionParser#parse<Array(String)>:Nil
from Shards::run:OptionParser
from __crystal_main
from Crystal::main_user_code<Int32, Pointer(Pointer(UInt8))>:Nil
from Crystal::main<Int32, Pointer(Pointer(UInt8))>:Int32
from main
from __libc_start_main
from _start
from ???
The following code fails to compile:
require "gobject/gio"
def file_changed(monitor : Gio::FileMonitor, file : Gio::File, other_file : Gio::File, event : Gio::FileMonitorEvent)
puts "something happpened"
end
monitor = Gio::File.new_for_path(".").monitor_directory(:watch_moves, nil)
monitor.on_changed(&->file_changed(Gio::FileMonitor, Gio::File, Gio::File, Gio::FileMonitorEvent))
Error:
There was a problem expanding macro 'require_gobject'
Code in lib/gobject/gio/gio.cr:4:1
4 | require_gobject "Gio"
^
Called macro defined in lib/gobject/gobject.cr:24:1
24 | macro require_gobject(namespace, version = nil)
Which expanded to:
> 17520 | def on_changed(&block : ChangedSignal)
> 17521 | __var0 = -> (arg1 : LibGio::File*, arg2 : LibGio::File*, arg3 : LibGio::FileMonitorEvent*, arg0 : LibGio::FileMonitor*) {
> 17522 | block.call(FileMonitor.new(arg0), Gio::File::Wrapper.new(arg1), Gio::File::Wrapper.new(arg2), Gio::FileMonitorEvent.new(arg3))
^--
Error: no overload matches 'Gio::FileMonitorEvent.new' with type Pointer(UInt32)
Overloads are:
- Gio::FileMonitorEvent.new(value : ::UInt32)
GFileMonitorEvent
is a enum in C.
Hey!
I'm trying to use this lib to create a simple Gtk application, but I'm having issues to setup the menu.
Here's the gist: https://gist.github.com/thiagoabreu/39858db3345904249505a41ccf408bd8
The problem I have is with this line:
action_entries = [
LibGio::ActionEntry.new(name: "quit", activate: ->{ puts "quit" }), # works
LibGio::ActionEntry.new(name: "quit", activate: ->{ self.quit }), # doesn't work
]
add_action_entries action_entries, action_entries.size, nil
The second entry raises an Error:
Error: can't set closure as C struct member
Is there something I'm doing wrong?
button=Gtk::Entry.new
Error in ./efinder.cr:8: wrong number of arguments for 'Gtk::Entry#initialize' (given 0, expected 1)
Overloads are:
- Gtk::Entry#initialize(gtk_entry)
entry=Gtk::Entry.new()
But where can i find gtk_entry?
This may be related to the last fixes on signals, this example shows that the first signal parameter is a union type instead of a Crystal gobject wrapper.
require "gobject/gtk/autorun"
builder = Gtk::Builder.new_from_file("#{__DIR__}/../lib/gobject/samples/gtk_tree_view.glade")
builder.connect_signals
# Insert something into the model
model = Gtk::TreeStore.cast(builder["tree_model"])
root = Gtk::TreeIter.new
model.append(root, nil)
model.set(root, [0], GObject::Value.new("Root"), 1)
# view
view = Gtk::TreeView.cast(builder["tree_view"])
view.on_row_activated do |view, path, column|
model = view.model.not_nil!
puts "model type: #{typeof(model)}"
puts "path type: #{typeof(path)}"
puts "column type: #{typeof(column)}"
if model.is_a?(Gtk::TreeStore)
puts "Crystal friendly object"
elsif model.is_a?(Pointer(LibGtk::TreeModel))
puts "Got the C pointer!?"
else
abort("caos")
end
end
# Show main view.
main_window = Gtk::Window.cast(builder["main_window"])
main_window.show_all
Output here after I double click in the tree view row:
model type: (Gtk::TreeStore | Pointer(LibGtk::TreeModel))
path type: Gtk::TreePath
column type: Gtk::TreeViewColumn
Got the C pointer!?
Tested on archlinux, crystal 0.34, crystal-gobject at 4f1e6c6.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.