andrewktmeikle
andrewktmeikle

Reputation: 487

Place popup menu below widget GTK

I am having some trouble placing my popup menu where I want in GTK(along the same y axis as my button so it seems to dropdown from the button).

I got it working when I was coding a similar thing in win32 but for the life of me I cannot get this thing to draw where I want!

I've done my research and I know what (I think) should work and that is when I make the call to gtk_menu_popup()

I should pass it in a function pointer to a method for placing the popup (link to the method specification - http://developer.gnome.org/gtk/2.24/GtkMenu.html#GtkMenuPositionFunc )

But i'm a bit rubbish with function pointers ( I have the Kernighan and ritchie book beside as I speak) but I'm pretty sure I'm doing it right.

Heres my attempt at the method :

void set_position(GtkMenu *menu,gint *x,gint *y,gboolean push_in,gpointer user_data)
{
 printf("Help!\n";
 GtkWidget *originButton = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(menu),"button");
 gdk_window_get_position(originButton->window,x,y);
 //now I realise this will place it at the top of the widget but thats acceptable for now, I just want the method to be called!
}

I call it from the button handler by doing this :

static gboolean handler (GtkWidget *widget,GdkEvent *event)
{
 GdkEventButton *bevent = (GdkEventButton *) event;
 gtk_menu_popup(GTK_MENU(widget),NULL,NULL,set_position,bevent->button,bevent->button,bevent->time);
}

But when I compile this it says its not a GtkMenuPositionFunc, so I just cast it (dont know if thats right though).

The problem is that I dont think my method is getting called because it never prints out help :( plus it still spawns the menu wherever I click (probably due to it not calling the method or whatever it should be doing).

Any help/ideas would be greatly received :) thanks :)

Upvotes: 2

Views: 2486

Answers (2)

andrewktmeikle
andrewktmeikle

Reputation: 487

Okay, thanks very much to Pfeiffer for his sample code. I had to make some changes to it because I was getting compiler errors (i have Werror on though).

In the set poisition method I ended up casting to a GTK_WIDGET instead of a GTK_BUTTON becauses thats what it was expecting

So my new set position method looked like :

static void set_position(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data) {

  GtkWidget *button = GTK_WIDGET(user_data);

  gdk_window_get_origin(button->window, x, y);
  *x += button->allocation.x;
  *y += (button->allocation.y + (button->allocation.height));


}

And as I couldn't figure out how to connect and pass the two widgets that Pfeiffer was passing I have this currently :

static gboolean handler(GtkWidget *widget, gpointer data) {

  gtk_menu_popup(GTK_MENU(data), NULL, NULL,(GtkMenuPositionFunc)set_position,widget,(guint)widget, gtk_get_current_event_time());

  return TRUE;

}

Also had to cast widget to a (guint) otherwise I got a compiler error about the 6th parameter :)

I will probably end up putting more in this method but this is the bare minimum I needed to get it to work.

That is connected using the normal gtk_signal_connect method

    gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(handler), GTK_OBJECT(menu));

where button and menu are GtkButton and GtkMenu instances I was using previously :)

Full credit goes to Pfeiffer for the answer, i'm just showing what worked for me :)

Thanks and hope this helps someone :)

Upvotes: 2

Szilárd Pfeiffer
Szilárd Pfeiffer

Reputation: 1646

I had the same problem earlier. I used the following code.

static void
set_position(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data)
{
  GtkWidget *button = GTK_BUTTON(user_data);

  gdk_window_get_origin(button->window, x, y);
  *x += button->allocation.x;
  *y += (button->allocation.y + (button->allocation.height));
}

static void
handler(GtkWidget *menu, GtkWidget *button)
{
  GtkRequisition requisition;

  gtk_widget_size_request(menu, &requisition);
  if (button->allocation.width > requisition.width)
    gtk_widget_set_size_request(menu, button->allocation.width, -1);

  gtk_menu_popup(GTK_MENU (menu),
                 NULL, NULL,
                 (GtkMenuPositionFunc) set_position, button,
                 0, gtk_get_current_event_time());
}

Upvotes: 3

Related Questions