Skip to content

Commit 79d2ac4

Browse files
SiegeLordExSiegeLord
authored andcommitted
Get the popup menu working under GTK.
The old code was broken, probably by the GTK3 migration. Fixes #1280
1 parent cc5c63c commit 79d2ac4

File tree

1 file changed

+49
-19
lines changed

1 file changed

+49
-19
lines changed

addons/native_dialog/gtk_menu.c

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@ struct ARGS
3737
int i;
3838
};
3939

40+
typedef struct POPUP_ARGS POPUP_ARGS;
41+
42+
struct POPUP_ARGS
43+
{
44+
/* Must be first. */
45+
ARGS_BASE base;
46+
47+
GtkWidget *gtk_window;
48+
ALLEGRO_MENU *menu;
49+
int x;
50+
int y;
51+
};
52+
4053

4154
static void build_menu(GtkWidget *gmenu, ALLEGRO_MENU *amenu);
4255

@@ -368,14 +381,12 @@ static void popop_on_hide(ALLEGRO_MENU *menu)
368381
/* [gtk thread] */
369382
static gboolean do_show_popup_menu(gpointer data)
370383
{
371-
ARGS *args = (ARGS *) data;
384+
POPUP_ARGS *args = (POPUP_ARGS *) data;
372385

373386
_al_gtk_lock_args(args);
374387

375-
GtkWidget *menu = NULL;
376388
if (!args->menu->extra1) {
377-
menu = gtk_menu_new();
378-
389+
GtkWidget *menu = gtk_menu_new();
379390
build_menu(menu, args->menu);
380391

381392
gtk_widget_show(menu);
@@ -385,22 +396,33 @@ static gboolean do_show_popup_menu(gpointer data)
385396
G_CALLBACK(popop_on_hide), (gpointer) args->menu);
386397
}
387398

388-
bool position_called = false;
389-
if (menu)
390-
/* gtk_menu_popup_at_widget only exists in gtk newer than 3.22 */
391399
#if GTK_CHECK_VERSION(3, 22, 0)
392-
gtk_menu_popup_at_widget(args->menu->extra1, menu, GDK_GRAVITY_SOUTH_WEST,
393-
GDK_GRAVITY_NORTH_WEST,
394-
NULL);
400+
GtkWidget *vbox = gtk_bin_get_child(GTK_BIN(args->gtk_window));
401+
GList* list = gtk_container_get_children(GTK_CONTAINER(vbox));
402+
int menu_height = 0;
403+
if (g_list_length(list) == 2) {
404+
GtkAllocation alloc;
405+
gtk_widget_get_allocation(GTK_WIDGET(list->data), &alloc);
406+
menu_height = alloc.height;
407+
}
408+
g_list_free(list);
409+
410+
411+
GdkSeat* seat = gdk_display_get_default_seat(
412+
gdk_window_get_display(gtk_widget_get_window(args->gtk_window)));
413+
GdkDevice *device = gdk_seat_get_pointer(seat);
414+
GdkEventButton event = { };
415+
event.type = GDK_BUTTON_RELEASE;
416+
event.time = GDK_CURRENT_TIME;
417+
event.device = device;
418+
GdkRectangle rect = { .x=args->x, .y=args->y + menu_height, .width=1, .height=1 };
419+
gtk_menu_popup_at_rect(args->menu->extra1, gtk_widget_get_window(args->gtk_window),
420+
&rect, GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, (GdkEvent*)&event);
395421
#else
396-
gtk_menu_popup(args->menu->extra1, NULL, NULL, NULL, NULL, 1, 0);
422+
gtk_menu_popup(args->menu->extra1, NULL, NULL, NULL, NULL, 1, 0);
397423
#endif
398424

399-
if (!position_called) {
400-
ALLEGRO_DEBUG("Position canary not called, most likely the menu didn't show "
401-
"up due to outstanding mouse events.\n");
402-
}
403-
args->base.response = position_called;
425+
args->base.response = true;
404426

405427
_al_gtk_release_args(args);
406428

@@ -409,15 +431,23 @@ static gboolean do_show_popup_menu(gpointer data)
409431

410432
bool _al_show_popup_menu(ALLEGRO_DISPLAY *display, ALLEGRO_MENU *menu)
411433
{
412-
ARGS args;
413-
(void)display;
434+
GtkWidget *gtk_window;
435+
POPUP_ARGS args;
436+
ALLEGRO_MOUSE_STATE state;
437+
438+
al_get_mouse_state(&state);
439+
440+
if (!(gtk_window = _al_gtk_get_window(display)))
441+
return false;
414442

415443
if (!_al_gtk_init_args(&args, sizeof(args))) {
416444
return false;
417445
}
418446

419-
args.gtk_window = NULL;
447+
args.gtk_window = gtk_window;
420448
args.menu = menu;
449+
args.x = al_get_mouse_state_axis(&state, 0);
450+
args.y = al_get_mouse_state_axis(&state, 1);
421451

422452
return _al_gtk_wait_for_args(do_show_popup_menu, &args);
423453
}

0 commit comments

Comments
 (0)