Better Win32 transparent window support

This commit is contained in:
Sam Huang
2023-08-27 12:56:44 -07:00
committed by Sam Lantinga
parent 923d612ca1
commit c191d6c306

View File

@@ -47,14 +47,20 @@
typedef HRESULT (WINAPI *DwmSetWindowAttribute_t)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute); typedef HRESULT (WINAPI *DwmSetWindowAttribute_t)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
/* Transparent window support */ /* Transparent window support */
#ifndef DWM_BB_ENABLE
#define DWM_BB_ENABLE 0x00000001
#endif
#ifndef DWM_BB_BLURREGION
#define DWM_BB_BLURREGION 0x00000002
#endif
typedef struct typedef struct
{ {
int left_width; DWORD flags;
int right_width; BOOL enable;
int top_height; HRGN blur_region;
int bottom_height; BOOL transition_on_maxed;
} MARGINS; } DWM_BLURBEHIND;
typedef HRESULT (WINAPI *DwmExtendFrameIntoClientArea_t)(HWND hwnd, const MARGINS *pMarInSet); typedef HRESULT(WINAPI *DwmEnableBlurBehindWindow_t)(HWND hwnd, const DWM_BLURBEHIND *pBlurBehind);
/* Windows CE compatibility */ /* Windows CE compatibility */
#ifndef SWP_NOCOPYBITS #ifndef SWP_NOCOPYBITS
@@ -593,25 +599,29 @@ int WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
ShowWindow(hwnd, SW_SHOWMINNOACTIVE); ShowWindow(hwnd, SW_SHOWMINNOACTIVE);
} }
if (!(window->flags & SDL_WINDOW_OPENGL)) { /* FIXME: does not work on all hardware configurations with different renders (i.e. hybrid GPUs) */
return 0;
}
/* Only OpenGL has transparent framebuffer which is handled by above */
/* FIXME: Transparent window support for renderers other than OpenGL possible? */
if (window->flags & SDL_WINDOW_TRANSPARENT) { if (window->flags & SDL_WINDOW_TRANSPARENT) {
void *handle = SDL_LoadObject("dwmapi.dll"); void *handle = SDL_LoadObject("dwmapi.dll");
if (handle) { if (handle) {
DwmExtendFrameIntoClientArea_t DwmExtendFrameIntoClientAreaFunc = (DwmExtendFrameIntoClientArea_t)SDL_LoadFunction(handle, "DwmExtendFrameIntoClientArea"); DwmEnableBlurBehindWindow_t DwmEnableBlurBehindWindowFunc = (DwmEnableBlurBehindWindow_t)SDL_LoadFunction(handle, "DwmEnableBlurBehindWindow");
if (DwmExtendFrameIntoClientAreaFunc) { if (DwmEnableBlurBehindWindowFunc) {
/* Negative margins create "sheet of glass" effect, thus transparent */ /* The region indicates which part of the window will be blurred and rest will be transparent. This
MARGINS margins = {-1, -1, -1, -1}; is because the alpha value of the window will be used for non-blurred areas
DwmExtendFrameIntoClientAreaFunc(hwnd, &margins); We can use (-1, -1, 0, 0) boundary to make sure no pixels are being blurred
*/
HRGN rgn = CreateRectRgn(-1, -1, 0, 0);
DWM_BLURBEHIND bb = {DWM_BB_ENABLE | DWM_BB_BLURREGION, TRUE, rgn, FALSE};
DwmEnableBlurBehindWindowFunc(hwnd, &bb);
DeleteObject(rgn);
} }
SDL_UnloadObject(handle); SDL_UnloadObject(handle);
} }
} }
if (!(window->flags & SDL_WINDOW_OPENGL)) {
return 0;
}
/* The rest of this macro mess is for OpenGL or OpenGL ES windows */ /* The rest of this macro mess is for OpenGL or OpenGL ES windows */
#ifdef SDL_VIDEO_OPENGL_ES2 #ifdef SDL_VIDEO_OPENGL_ES2
if ((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES || if ((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES ||