From 1377d34359aeb17f2490086b6f7bb928eeb808f9 Mon Sep 17 00:00:00 2001 From: Elias Aebi Date: Mon, 2 Sep 2024 08:49:16 +0200 Subject: [PATCH] gral_window_show_context_menu --- demos/events.c | 11 +++++++++++ gral.h | 4 ++++ gral_linux.c | 19 +++++++++++++++++++ gral_macos.m | 4 ++++ gral_windows.cpp | 23 +++++++++++++++++++++++ 5 files changed, 61 insertions(+) diff --git a/demos/events.c b/demos/events.c index 99415ec..1dccee9 100644 --- a/demos/events.c +++ b/demos/events.c @@ -43,6 +43,17 @@ static void mouse_button_press(float x, float y, int button, int modifiers, void gral_timer_delete(demo->timer); demo->timer = 0; } + if (button == GRAL_SECONDARY_MOUSE_BUTTON) { + static struct gral_menu_item items[] = { + {"First"}, + {"Second"}, + {"Third"}, + {"-"}, + {"Last"}, + {NULL} + }; + gral_window_show_context_menu(demo->window, x, y, items); + } } static void mouse_button_release(float x, float y, int button, void *user_data) { diff --git a/gral.h b/gral.h index 3b4d4d2..190e2dc 100644 --- a/gral.h +++ b/gral.h @@ -90,6 +90,9 @@ struct gral_window_interface { void (*focus_enter)(void *user_data); void (*focus_leave)(void *user_data); }; +struct gral_menu_item { + char const *text; +}; struct gral_timer; struct gral_file; struct gral_directory_watcher; @@ -157,6 +160,7 @@ void gral_window_show_open_file_dialog(struct gral_window *window, void (*callba void gral_window_show_save_file_dialog(struct gral_window *window, void (*callback)(char const *file, void *user_data), void *user_data); void gral_window_clipboard_copy(struct gral_window *window, char const *text); void gral_window_clipboard_paste(struct gral_window *window, void (*callback)(char const *text, void *user_data), void *user_data); +void gral_window_show_context_menu(struct gral_window *window, float x, float y, struct gral_menu_item *items); struct gral_timer *gral_timer_create(int milliseconds, void (*callback)(void *user_data), void *user_data); void gral_timer_delete(struct gral_timer *timer); diff --git a/gral_linux.c b/gral_linux.c index e35c5fc..8fb6354 100644 --- a/gral_linux.c +++ b/gral_linux.c @@ -638,6 +638,25 @@ void gral_window_clipboard_paste(struct gral_window *window, void (*callback)(ch gtk_clipboard_request_text(clipboard, paste_callback, callback_data); } +void gral_window_show_context_menu(struct gral_window *window, float x, float y, struct gral_menu_item *items) { + GtkWidget *area = gtk_bin_get_child(GTK_BIN(window)); + GtkWidget *menu = gtk_menu_new(); + gtk_menu_attach_to_widget(GTK_MENU(menu), area, NULL); + for (; items->text; ++items) { + GtkWidget *item; + if (items->text[0] == '-') { + item = gtk_separator_menu_item_new(); + } + else { + item = gtk_menu_item_new_with_label(items->text); + } + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + } + gtk_widget_show_all(menu); + GdkRectangle rect = {x, y, 1, 1}; + gtk_menu_popup_at_rect(GTK_MENU(menu), gtk_widget_get_window(area), &rect, GDK_GRAVITY_SOUTH_EAST, GDK_GRAVITY_NORTH_WEST, NULL); +} + typedef struct { void (*callback)(void *user_data); void *user_data; diff --git a/gral_macos.m b/gral_macos.m index bc0d5ec..0ac0574 100644 --- a/gral_macos.m +++ b/gral_macos.m @@ -667,6 +667,10 @@ void gral_window_clipboard_paste(struct gral_window *window, void (*callback)(ch } } +void gral_window_show_context_menu(struct gral_window *window, float x, float y, struct gral_menu_item *items) { + // TODO: implement +} + @interface TimerCallbackObject: NSObject { @public void (*callback)(void *user_data); diff --git a/gral_windows.cpp b/gral_windows.cpp index 1c83f48..a349bf2 100644 --- a/gral_windows.cpp +++ b/gral_windows.cpp @@ -1054,6 +1054,29 @@ void gral_window_clipboard_paste(gral_window *window, void (*callback)(char cons CloseClipboard(); } +void gral_window_show_context_menu(gral_window *window, float x, float y, gral_menu_item *items) { + HMENU menu = CreatePopupMenu(); + for (; items->text; ++items) { + MENUITEMINFO item; + item.cbSize = sizeof(MENUITEMINFO); + item.fMask = 0; + if (items->text[0] == '-') { + AppendMenu(menu, MF_SEPARATOR, 0, NULL); + } + else { + item.fType = MFT_STRING; + AppendMenu(menu, MF_STRING, 0, utf8_to_utf16(items->text)); + } + //InsertMenuItem(menu, ); + } + POINT point; + point.x = (LONG)x; + point.y = (LONG)y; + ClientToScreen((HWND)window, &point); + TrackPopupMenuEx(menu, TPM_LEFTALIGN | TPM_TOPALIGN, point.x, point.y, (HWND)window, NULL); + DestroyMenu(menu); +} + static void CALLBACK timer_completion_routine(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue) { gral_timer *timer = (gral_timer *)lpArgToCompletionRoutine; timer->callback(timer->user_data);