# User data in signal callbacks backwards?

**URL:** <https://www.ruby-forum.com/t/user-data-in-signal-callbacks-backwards/211149>\
**Category:** Ruby-Gnome 2\
**Created:** [August 26, 2011, 11:23pm UTC](https://www.ruby-forum.com/t/user-data-in-signal-callbacks-backwards/211149 "2011-08-26T23:23:40Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![dubstep](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/cdc98d/32.png) [@dubstep](https://www.ruby-forum.com/u/dubstep)\
**Post date:** [August 26, 2011, 11:23pm UTC](https://www.ruby-forum.com/t/user-data-in-signal-callbacks-backwards/211149/1 "2011-08-26T23:23:40Z")

</div>

Hello,

I wrote a demo with some treeview to prototype list behaviour but  
there is one surprising feature of ruby-gtk2 which I found:

In C you are supposed to get this callback:

The “changed” signal

void user\_function  
(GtkTreeSelection \*treeselection,  
gpointer  
user\_data) : Run First

meaning that the object which triggered the signal is passed in as the  
first pointer which is usually used for the ‘self’ pointer in glib  
fake C object interface.

When I create a glade layout where I connect a tree view selection  
“changed” signal and pass another object as the user data I get the  
user data as self and the object that triggered the signal as  
argument. Effectively the arguments are reversed. Without user data I  
get the object that loaded the layout as self and the object that  
triggered the signal as argument.

Is it intentional that the callback interface is so much different from  
C?

I would expect to just get two arguments in the case with user data.  
It is the same order as C then and I get access to the layout that way  
and just adding user data does not change the call completely.

Thanks

Michal

---

<div class="post-metadata">

**Author:** ![Michal\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/779978/32.png) [@Michal\_S](https://www.ruby-forum.com/u/Michal_S)\
**Post date:** [August 27, 2011, 8:20am UTC](https://www.ruby-forum.com/t/user-data-in-signal-callbacks-backwards/211149/2 "2011-08-27T08:20:06Z")

</div>

Hi,

In [CAOMqctTB\_5p=aL=removed\_email\_address@domain.invalid](mailto:CAOMqctTB_5p=aL=removed_email_address@domain.invalid)  
“[ruby-gnome2-devel-en] User data in signal callbacks backwards?” on  
Fri, 26 Aug 2011 23:22:43 +0200,  
Michal S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> user\_data) : Run First  
> triggered the signal as argument.  
> Could you give us a sample Ruby code and a glade file for  
> this problem?  
> If you provide them to us, we may fix it.

## Thanks,

kou

---

<div class="post-metadata">

**Author:** ![Michal\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/779978/32.png) [@Michal\_S](https://www.ruby-forum.com/u/Michal_S)\
**Post date:** [August 28, 2011, 12:23pm UTC](https://www.ruby-forum.com/t/user-data-in-signal-callbacks-backwards/211149/3 "2011-08-28T12:23:09Z")

</div>

On 27 August 2011 08:18, Kouhei S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> >

I am not sure it is actually an error. It just looks backwards if you  
look both at Ruby sample and C sample.

Attaching code for both.

Thanks

Michal

---

<div class="post-metadata">

**Author:** ![Michal\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/779978/32.png) [@Michal\_S](https://www.ruby-forum.com/u/Michal_S)\
**Post date:** [August 30, 2011, 4:05pm UTC](https://www.ruby-forum.com/t/user-data-in-signal-callbacks-backwards/211149/4 "2011-08-30T16:05:02Z")

</div>

On 27 August 2011 08:18, Kouhei S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> >

OK, perhaps the sample I sent is too long so I will put only the  
relevant excerpts here.

In C I write:

void selection\_changed (GtkTreeSelection \*self, gpointer data)

g\_signal\_connect (lsel, “changed”,  
G\_CALLBACK(selection\_changed), rsel);

Now when lsel changes selection\_changed is called with arguments lsel,  
rsel - selection\_changed (lsel, rsel).

In glade I have

```
                  <object class="GtkTreeView" id="treeview1">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="model">liststore</property>
                    <property name="enable_search">False</property>
                    <child internal-child="selection">
                      <object class="GtkTreeSelection"

```

id=“treeview-selection1”\>

when treewiew-selection1 changes treewiew-selection2.selection\_changed  
treeview\_selection1 is called.

In my demo it is useful that it’s called that way but since I did not  
opt for swapped call I see this as backwards.

The other call is performed as .selection\_changed selection1.

The glade loading incantation is taken from some sample:

```
  @builder = Gtk::Builder.new
  @builder << path_or_data
  @builder.connect_signals {|name| method(name)}

```

In C there is special call to connect the signals swapped which I  
would expect to result in calling the method on the argument:

g\_signal\_connect\_swapped (button, “clicked”,  
G\_CALLBACK (gtk\_widget\_destroy),  
window);

Thanks

Michal

---

<div class="post-metadata">

**Author:** ![Michal\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/779978/32.png) [@Michal\_S](https://www.ruby-forum.com/u/Michal_S)\
**Post date:** [August 31, 2011, 11:32am UTC](https://www.ruby-forum.com/t/user-data-in-signal-callbacks-backwards/211149/5 "2011-08-31T11:32:58Z")

</div>

Michal S. wrote in post #1018884:

> On 27 August 2011 08:18, Kouhei S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > >
> 
> I am not sure it is actually an error. It just looks backwards if you  
> look both at Ruby sample and C sample.
> 
> Attaching code for both.
> 
> Thanks
> 
> Michal

Looking at attached files, I don’t quite get where you try to use “user  
data”. In fact, I don’t think you can retrieve “user data” with  
Gtk::Builder in ruby.

Looking at treeselection1, you have 2 handlers, one with user data, and  
one without. However, if you just comment out the one without user data,  
you will notice that the one _with_ is just discarded, nothing is  
connected.

Just add puts “Adding callback #{name}” to the builder.connect\_signal,  
and you will see it is called only once for each selection.

You might think it is backward because, when you change something in  
ts1, if it changes something in ts2, the ts2 ‘selection\_changed’ is then  
called, and it is called before you finish what you were doing in ts1.  
At least, that’s the only way I can think of.

The main problem, afaik, is that ruby gtk::builder does not handle “user  
data”. I took a look at rbgtkbuilder.c, but I’m really too bad at C to  
understand what is going on.

regards

Simon

---

<div class="post-metadata">

**Author:** ![Michal\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/779978/32.png) [@Michal\_S](https://www.ruby-forum.com/u/Michal_S)\
**Post date:** [August 31, 2011, 12:26pm UTC](https://www.ruby-forum.com/t/user-data-in-signal-callbacks-backwards/211149/6 "2011-08-31T12:26:34Z")

</div>

On 31 August 2011 11:32, Simon A.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > Thanks  
> > connected.  
> > No, that’s not how things work.

The user data in glade can be set to one of the other objects in the  
glade layout.

If the callback was just discarded the demo would not work which is  
not what I see.

The callback selection\_changed is set on treeview-selection1 with user  
data treeview-selection2 and when triggered on treeview-selection1  
treeview-selection2.selection\_changed treeview\_selection1 is called.

> Just add puts “Adding callback #{name}” to the builder.connect\_signal,  
> and you will see it is called only once for each selection.

It is called twice with selection\_changed.

When I comment out the two with user data it is also called twice but  
the demo does not work then so the signals with user data are not  
connected in the block but are still connected.

> You might think it is backward because, when you change something in  
> ts1, if it changes something in ts2, the ts2 ‘selection\_changed’ is then  
> called, and it is called before you finish what you were doing in ts1.  
> At least, that’s the only way I can think of.

No, when I have Item 4 selected in one view and select item 4 in the  
other I get:  
sel “Item 4” “Item 4”  
sel “Item 4” nil  
sav “Item 4” nil  
sav “Item 5” “Item 4”

So the other callback fires before the first finishes due to the  
unselect call - the method producing the sav output is called from the  
callback.  
There is no problem with that, though. The sel output is produced at  
the very start of the callback and is in order.

> The main problem, afaik, is that ruby gtk::builder does not handle “user  
> data”. I took a look at rbgtkbuilder.c, but I’m really too bad at C to  
> understand what is going on.

Obviously it does.

Thanks

Michal

---

<div class="post-metadata">

**Author:** ![Michal\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/779978/32.png) [@Michal\_S](https://www.ruby-forum.com/u/Michal_S)\
**Post date:** [August 31, 2011, 2:51pm UTC](https://www.ruby-forum.com/t/user-data-in-signal-callbacks-backwards/211149/7 "2011-08-31T14:51:53Z")

</div>

Michal S. wrote in post #1019345:

> The callback selection\_changed is set on treeview-selection1 with user  
> data treeview-selection2 and when triggered on treeview-selection1  
> treeview-selection2.selection\_changed treeview\_selection1 is called.

Indeed. I tested this, see attachment, and this is really bad.

Basically, ruby Gtk::Builder sends a message to the “user data” object,  
with the name of the callback, passing expected arguments for the  
signal. And it does so even if you do not connect\_signals. Just comment  
out ‘method(handler)’ line 20 to be sure.

> > Just add puts “Adding callback #{name}” to the builder.connect\_signal,  
> > and you will see it is called only once for each selection.
> 
> It is called twice with selection\_changed.

And it should be called 4 times. It’s only called for the one without  
“user data”.

> When I comment out the two with user data it is also called twice but  
> the demo does not work then so the signals with user data are not  
> connected in the block but are still connected.

That’s because of the buggy behaviour of gtk::builder I outline above.

> > You might think it is backward because, when you change something in  
> > ts1, if it changes something in ts2, the ts2 ‘selection\_changed’ is then  
> > called, and it is called before you finish what you were doing in ts1.  
> > At least, that’s the only way I can think of.
> 
> No, when I have Item 4 selected in one view and select item 4 in the  
> other I get:  
> sel “Item 4” “Item 4”  
> sel “Item 4” nil  
> sav “Item 4” nil  
> sav “Item 5” “Item 4”
> 
> So the other callback fires before the first finishes due to the  
> unselect call - the method producing the sav output is called from the  
> callback.  
> There is no problem with that, though. The sel output is produced at  
> the very start of the callback and is in order.

After more thorough testing, it calls 3 callbacks.  
The first two are the _backward_ callback, which I would call _buggy_,  
and should not exist.  
The third one is the expected callback, which just sets the title, and  
nothing else.

> > The main problem, afaik, is that ruby gtk::builder does not handle “user  
> > data”. I took a look at rbgtkbuilder.c, but I’m really too bad at C to  
> > understand what is going on.
> 
> Obviously it does.

I still think it does not. It just has a buggy behaviour which makes it  
work somewhat, but is not what I expect.

for example, if I have :

I want to write somewhere in my code :

def my\_callback(button, user\_data)

and not :

my\_entry = builder[‘y\_entry’]  
def my\_entry.my\_callback(button)

or even worse, reopening Gtk::Entry, like you do on TreeSelection :  
class Gtk::Entry  
def my\_callback(button)

I think it should be fixed. And signals should handle “user data”, and  
passing them as the last argument of the signal, if they are present.

Simon

---

<div class="post-metadata">

**Author:** ![Michal\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/779978/32.png) [@Michal\_S](https://www.ruby-forum.com/u/Michal_S)\
**Post date:** [September 1, 2011, 6:07pm UTC](https://www.ruby-forum.com/t/user-data-in-signal-callbacks-backwards/211149/8 "2011-09-01T18:07:45Z")

</div>

On 27 August 2011 08:18, Kouhei S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > When I create a glade layout where I connect a tree view selection  
> > “changed” signal and pass another object as the user data I get the  
> > user data as self and the object that triggered the signal as  
> > argument. Effectively the arguments are reversed. Without user data I  
> > get the object that loaded the layout as self and the object that  
> > triggered the signal as argument.
> 
> Could you give us a sample Ruby code and a glade file for  
> this problem?  
> If you provide them to us, we may fix it.

I think it may be fixed with something like this:

— ../../lib/gtk2/base.rb~ 1970-01-01 01:00:00.000000000 +0100  
+++ ../../lib/gtk2/base.rb 2011-09-01 18:04:16.000000000 +0200  
@@ -76,6 +76,11 @@  
handler\_name, connect\_object, flags)  
handler\_name = canonical\_handler\_name(handler\_name)  
if connect\_object

- 

```
      if ! flags.swapped? then

```

- 

```
         tmp = object

```

- 

```
         object = connect_object

```

- 

```
         connect_object = tmp

```

- 

```
      end
     handler = connect_object.method(handler_name)
   else
     handler = connector.call(handler_name)

```

Will test later.

Thanks

Michal

---

<div class="post-metadata">

**Author:** ![Michal\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/779978/32.png) [@Michal\_S](https://www.ruby-forum.com/u/Michal_S)\
**Post date:** [September 2, 2011, 12:52am UTC](https://www.ruby-forum.com/t/user-data-in-signal-callbacks-backwards/211149/9 "2011-09-02T00:52:07Z")

</div>

On 1 September 2011 18:06, Michal S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > In C you are supposed to get this callback:  
> > > fake C object interface.  
> > > If you provide them to us, we may fix it.
> 
> I think it may be fixed with something like this:

Hmm. forget that.

The current function generally does not work for any but the simplest  
case.

There is a fundamental problem that the ruby-gtk2 callback mechanism  
calls a method on an object and hands it the arguments gtk provides,  
and first of the arguments is what would be normally considered the  
receiver in Glib.

The other fundamental issue is that swapped callbacks should ‘just  
work’ so they are called on the data, with arguments ignored.

Given button B and window W you can g\_signal\_connect( B, ‘clicked’ ,  
gtk\_widget\_destroy, W) to have gtk\_widget\_destroy(B,W) called whenever  
B is clicked. Of course, you will probably want  
g\_signal\_connect\_swapped( B, ‘clicked’ , gtk\_widget\_destroy, W) to  
have gtk\_widget\_destroy(W,B) called. Destroy takes one argument so B  
is ignored.

Now in Ruby you would connect a method, not a function. So what would  
get called is something like  
O.destroy B,W or O.destroy W,B where O is some arbitrary object chosen  
when connecting the signal.

To make the swapped signal work as expected so that “glade programs”  
work builder connects  
W.destroy when W is set as data for the (B - clicked - destroy)  
connection in glade. The arguments B,W or W,B passed by GTK are  
ignored because destroy takes no argument in Ruby.

Maybe whatever does the callback dispatching in ruby-gtk2 could weed  
out the first argument if it is equal to the receiver. That would not  
give consistent results when calling callbacks on different objects,  
though.

I put together this update to the connect\_signals method which  
distinguishes three cases:

1. no user data (connect\_object) passed to signal in Glade - ask user  
for method, as before

2. user data is supplied and signal marked as swapped - connect to  
data, as before

3. user data is supplied and signal is not swapped - ask user for  
method - previously the signal was handled as swapped

signal  
#{signal\_name.inspect} of #{trigger} to #{handler\_name}" + (receiver ?  
" on #{receiver}" : “”)) if $DEBUG && data  
trigger.send(\*args) {handler.call}  
else  
$stderr.puts(“Insufficient arity: #{handler.arity} of  
#{handler} while connecting signal  
#{signal\_name.inspect} of #{trigger} to #{handler\_name}” + (receiver ?  
" on #{receiver}" : “”)) if $DEBUG && data && (handler.arity \< 2)  
trigger.send(\*args, &handler)  
end  
end

Thanks

Michal

---

<div class="post-metadata">

**Author:** ![Michal\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/779978/32.png) [@Michal\_S](https://www.ruby-forum.com/u/Michal_S)\
**Post date:** [August 31, 2011, 4:08pm UTC](https://www.ruby-forum.com/t/user-data-in-signal-callbacks-backwards/211149/10 "2011-08-31T16:08:58Z")

</div>

On 31 August 2011 14:51, Simon A.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Michal S. wrote in post #1019345:

> > sav “Item 5” “Item 4”  
> > The third one is the expected callback, which just sets the title, and  
> > nothing else.

So we can agree what’s called, and that it is not what is expected.

> for example, if I have :  
> and not :
> 
> my\_entry = builder[‘y\_entry’]  
> def my\_entry.my\_callback(button)
> 
> or even worse, reopening Gtk::Entry, like you do on TreeSelection :  
> class Gtk::Entry  
> def my\_callback(button)

I would totally reopen the TreeSelection even if I got the callbacks  
correctly. It fits my use case nicely. The problem is I have to, even  
though I did not opt for this.

My first guess would be that Gtk::Builder somehow interprets the  
swapped=“no” as meaning swapped because earlier glades only generated  
swapped=“yes” and not swapped=“no”.

The swapped=“yes” callbacks should arguably be handled internally as  
they would be in C. The  
g\_signal\_connect\_swapped (button, “clicked”,  
G\_CALLBACK (gtk\_widget\_destroy),  
window);  
can be done in Glade by   
to produce a button that closes the application without any C code.

Indeed, adding to the treeviews and  
replacing the app\_quit handlers on the button with   
allows closing the application window without running any code of my  
own.

Thanks

Michal
