diff --git a/video/out/w32_common.c b/video/out/w32_common.c index 4015a199f7..6f59a5ee15 100644 --- a/video/out/w32_common.c +++ b/video/out/w32_common.c @@ -1532,7 +1532,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, } break; } - case WM_SYSCOMMAND: + case WM_SYSCOMMAND: { switch (wParam & 0xFFF0) { case SC_SCREENSAVE: case SC_MONITORPOWER: @@ -1550,7 +1550,18 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, } break; } + // All custom items must use ids of less than 0xF000. The context menu items are + // also larger than WM_USER, which excludes SCF_ISSECURE. + if (wParam > WM_USER && wParam < 0xF000) { + const char *cmd = mp_win32_menu_get_cmd(w32->menu_ctx, LOWORD(wParam)); + if (cmd) { + mp_cmd_t *cmdt = mp_input_parse_cmd(w32->input_ctx, bstr0(cmd), ""); + mp_input_queue_cmd(w32->input_ctx, cmdt); + return 0; + } + } break; + } case WM_NCACTIVATE: // Cosmetic to remove blinking window border when initializing window if (!w32->opts->border) @@ -2031,7 +2042,7 @@ static MP_THREAD_VOID gui_thread(void *ptr) goto done; } - w32->menu_ctx = mp_win32_menu_init(); + w32->menu_ctx = mp_win32_menu_init(w32->window); update_dark_mode(w32); update_corners_pref(w32); if (w32->opts->window_affinity) diff --git a/video/out/win32/menu.c b/video/out/win32/menu.c index 25681e8ae3..98891d32d6 100644 --- a/video/out/win32/menu.c +++ b/video/out/win32/menu.c @@ -25,6 +25,8 @@ #include "menu.h" struct menu_ctx { + HWND hwnd; + bool updated; HMENU menu; void *ta_data; // talloc context for MENUITEMINFOW.dwItemData }; @@ -178,9 +180,11 @@ static void build_menu(void *talloc_ctx, HMENU hmenu, struct mpv_node *node) } } -struct menu_ctx *mp_win32_menu_init(void) +struct menu_ctx *mp_win32_menu_init(HWND hwnd) { struct menu_ctx *ctx = talloc_ptrtype(NULL, ctx); + ctx->hwnd = hwnd; + ctx->updated = false; ctx->menu = CreatePopupMenu(); ctx->ta_data = talloc_new(ctx); return ctx; @@ -218,6 +222,17 @@ void mp_win32_menu_update(struct menu_ctx *ctx, struct mpv_node *data) talloc_free_children(ctx->ta_data); build_menu(ctx->ta_data, ctx->menu, data); + if (!ctx->updated) { + append_menu(GetSystemMenu(ctx->hwnd, FALSE), MIIM_FTYPE, MFT_SEPARATOR, 0, NULL, NULL, NULL); + append_menu(GetSystemMenu(ctx->hwnd, FALSE), MIIM_STRING | MIIM_SUBMENU, 0, 0, + build_title(ctx->ta_data, "mpv", NULL), ctx->menu, NULL); + ctx->updated = true; + } else if (data->format != MPV_FORMAT_NODE_ARRAY) { + // recreate ctx->menu because it is destroyed here + GetSystemMenu(ctx->hwnd, TRUE); + ctx->menu = CreatePopupMenu(); + ctx->updated = false; + } } const char* mp_win32_menu_get_cmd(struct menu_ctx *ctx, UINT id) diff --git a/video/out/win32/menu.h b/video/out/win32/menu.h index 8b1fe72c19..2bece0f1d8 100644 --- a/video/out/win32/menu.h +++ b/video/out/win32/menu.h @@ -23,7 +23,7 @@ struct mpv_node; struct menu_ctx; -struct menu_ctx *mp_win32_menu_init(void); +struct menu_ctx *mp_win32_menu_init(HWND hwnd); void mp_win32_menu_uninit(struct menu_ctx *ctx); void mp_win32_menu_show(struct menu_ctx *ctx, HWND hwnd); void mp_win32_menu_update(struct menu_ctx *ctx, struct mpv_node *data);