diff --git a/demos/events.c b/demos/events.c index 0cb2d56..4e9a44e 100644 --- a/demos/events.c +++ b/demos/events.c @@ -56,6 +56,17 @@ static void mouse_button_press(float x, float y, int button, int modifiers, void gral_timer_delete(window->application->timer); window->application->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 fe7c586..b93edf9 100644 --- a/gral.h +++ b/gral.h @@ -96,6 +96,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; @@ -171,6 +174,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 d5891f5..972000e 100644 --- a/gral_linux.c +++ b/gral_linux.c @@ -669,6 +669,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 8673ce4..8ae7588 100644 --- a/gral_macos.m +++ b/gral_macos.m @@ -714,6 +714,24 @@ 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) { + NSMenu *menu = [[NSMenu alloc] init]; + for (; items->text; ++items) { + NSMenuItem *item; + if (items->text[0] == '-') { + item = [NSMenuItem separatorItem]; + } + else { + item = [[NSMenuItem alloc] init]; + item.title = [NSString stringWithUTF8String:items->text]; + } + [menu addItem:item]; + [item release]; + } + [NSMenu popUpContextMenu:menu withEvent:[NSApp currentEvent] forView:[(GralWindow *)window contentView]]; + [menu release]; +} + struct gral_timer *gral_timer_create(int milliseconds, void (*callback)(void *user_data), void *user_data) { GralCallbackObject *callback_object = [[GralCallbackObject alloc] init]; callback_object->callback = callback; diff --git a/gral_windows.cpp b/gral_windows.cpp index 697cc05..e8a3504 100644 --- a/gral_windows.cpp +++ b/gral_windows.cpp @@ -1108,6 +1108,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);