Add a function to display the system menu for a window

Add SDL_ShowWindowSystemMenu() to display the system-level menu for windows. Typically, this is done by right-clicking on the system provided window decorations, however, if an application is rendering its own client-side decorations, there is currently no way to display it. This menu is provided by the system and can provide privileged desktop functionality such as moving or pinning a window to a specific workspace or display, setting the always-on-top property, or taking screenshots. In many cases, there are no APIs which allow applications to perform these actions manually.

Implemented for Wayland via functionality provided by the xdg_toplevel protocol, Win32 via the undocumented message 0x313 (typically called WM_POPUPSYSTEMMENU), and X11 via the "_GTK_SHOW_WINDOW_MENU" atom (supported in GNOME and KDE).
This commit is contained in:
Frank Praznik
2023-07-30 11:24:24 -04:00
parent be5f66c84e
commit 70323a8350
18 changed files with 124 additions and 0 deletions

View File

@@ -51,6 +51,14 @@ typedef HRESULT (WINAPI *DwmSetWindowAttribute_t)(HWND hwnd, DWORD dwAttribute,
#define SWP_NOCOPYBITS 0
#endif
/* An undocumented message to create a popup system menu
* - wParam is always 0
* - lParam = MAKELONG(x, y) where x and y are the screen coordinates where the menu should be displayed
*/
#ifndef WM_POPUPSYSTEMMENU
#define WM_POPUPSYSTEMMENU 0x313
#endif
/* #define HIGHDPI_DEBUG */
/* Fake window to help with DirectInput events. */
@@ -1485,6 +1493,17 @@ int WIN_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperati
return 0;
}
void WIN_ShowWindowSystemMenu(SDL_Window *window, int x, int y)
{
const SDL_WindowData *data = window->driverdata;
POINT pt;
pt.x = x;
pt.y = y;
ClientToScreen(data->hwnd, &pt);
SendMessage(data->hwnd, WM_POPUPSYSTEMMENU, 0, MAKELPARAM(pt.x, pt.y));
}
#endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/
void WIN_UpdateDarkModeForHWND(HWND hwnd)