On Wed, 19 Jun 2019 22:13:07 +0200, Mike Wey wrote:

On 19-06-2019 15:40, Alex X wrote:

I have a list of items(a GtkTreeView) and I'm trying to get the selected item when clicked.

What I'd really like to do is get get the index of the item under the mouse when it is clicked.

I could do this if, say, I had the position of the cursor and new the height's of the items and the exact layout. e.g.,

floor(y/itemHeight)

but that makes a lot of assumptions that may not hold.

Do you see where I'm going with this? ;)

The reason I'd like to do this is because my code is a little more complicated. What is happening is that when I click the selection change is updated after I get the selection and so is always out of sync.

I click and my code is ran and then the internals change the selection item(I guess because I'm returning false from the button press handler).

e.g.,

  1. click
  2. get selection(but it hasn't changed yet)
  3. act on selection(but acts wrong).
  4. selection is changed(internally by gtk)

when it's repeated the 3 then acts on the previous selection which was correct previously.

But I don't know how to do 4 myself except hacking it which may be invalid.

In the button handler I do get the x and y and if they are correct and I can get the true height of the rows(including padding, etc) then I could do the calculation myself.

I think technically I would have to iterate through them and add up the individual row heights since they could all be different.

Maybe I am going about it wrong or there is a simpler way?

Maybe you can use getPathAtPos to get a TreePath to the row under the
mouse pointer.

https://api.gtkd.org/gtk.TreeView.TreeView.getPathAtPos.html

Future Reference: One could get the heights by essentially trying all possible combinations if necessary

{
   q = TV.getPathAtPos(0, i, tp, tvc, a, b);
   k = tp.getIndices();
}

After trying various things the code seems to be quite simple:

x = cast(int)e.button().x; 
y = cast(int)e.button().y;
TV.getPathAtPos(x, y, tp, tvc, a, b);
is = tp.getIndices();

I'm not sure how robust it is though but it seems to work.

  1. I noticed that different window values are referring to different objects

  • win 0x0000023886c246e0 {gObject=0x000002388805d650 {gTypeInstance={gClass=0x0000023886ed40c0 {gType=2441805070144}}, ...}, ...} gdk.Window.Window
  • gObject 0x000002388805d650 {gTypeInstance={gClass=0x0000023886ed40c0 {gType=2441805070144}}, refCount=5, qdata=0x0000023887ff5d41} gobject.c.types.GObject*
  • win2 0x000002388805d650 {} gdk.c.types.GdkWindow*
 // markup was cutting out this line below for some reason
	auto win = TV.getBinWindow();
	auto win2 = e.any.window;

These are mixing types which could result in hard to find errors ;/

win.gObject == win2 but many will do win == win2 resulting in a failed comparison ;/

I imagine there are a lot of subtle issues in GdkD like this? ;/

Maybe gdk.Event.Event

needs not to return the gtk struct but wrap it and return D structs/classes that use properties to return wrapped gtk structs/classes

The problem is that gdk.Event.Event return gdkEvent which is of gdk.c.types.GdkEvent

  • e 0x0000023886d5fcc0 {gdkEvent=0x0000023886eadbf0 {type=4, any={type=4, window=0x000002388805d650 {}, sendEvent=0}, ...}, ...} gdk.Event.Event
  • gdkEvent 0x0000023886eadbf0 {type=4, any={type=4, window=0x000002388805d650 {}, sendEvent=0}, expose={type=4, window=0x000002388805d650, ...}, ...} gdk.c.types.GdkEvent*

Not really sure the best solution. It would be nice if the compiler could figure out what is going on but that probably won't be possible...

Another way may be to have opEquals for the gtkD types and just do the inner compare on the gdk types.

Thanks for all your help!