diff options
Diffstat (limited to 'platform/windows/os_windows.cpp')
-rw-r--r-- | platform/windows/os_windows.cpp | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 7b46608c55..54a5d91eb4 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -637,6 +637,28 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) maximized = false; minimized = false; } + if (is_layered_allowed() && layered_window) { + DeleteObject(hBitmap); + + RECT r; + GetWindowRect(hWnd, &r); + dib_size = Size2(r.right - r.left, r.bottom - r.top); + + BITMAPINFO bmi; + ZeroMemory(&bmi, sizeof(BITMAPINFO)); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = dib_size.x; + bmi.bmiHeader.biHeight = dib_size.y; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = dib_size.x, dib_size.y * 4; + hBitmap = CreateDIBSection(hDC_dib, &bmi, DIB_RGB_COLORS, (void **)&dib_data, NULL, 0x0); + SelectObject(hDC_dib, hBitmap); + + ZeroMemory(dib_data, dib_size.x * dib_size.y * 4); + } + //return 0; // Jump Back } break; case WM_ENTERSIZEMOVE: { @@ -1151,6 +1173,9 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int SetFocus(hWnd); // Sets Keyboard Focus To } + if (p_desired.layered_splash) { + set_window_per_pixel_transparency_enabled(true); + } return OK; } @@ -1542,6 +1567,9 @@ void OS_Windows::set_window_fullscreen(bool p_enabled) { if (video_mode.fullscreen == p_enabled) return; + if (layered_window) + set_window_per_pixel_transparency_enabled(false); + if (p_enabled) { if (pre_fs_valid) { @@ -1646,10 +1674,97 @@ bool OS_Windows::is_window_always_on_top() const { return video_mode.always_on_top; } +bool OS_Windows::get_window_per_pixel_transparency_enabled() const { + + if (!is_layered_allowed()) return false; + return layered_window; +} + +void OS_Windows::set_window_per_pixel_transparency_enabled(bool p_enabled) { + + if (!is_layered_allowed()) return; + if (layered_window != p_enabled) { + if (p_enabled) { + set_borderless_window(true); + //enable per-pixel alpha + hDC_dib = CreateCompatibleDC(GetDC(hWnd)); + + SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED); + + RECT r; + GetWindowRect(hWnd, &r); + dib_size = Size2(r.right - r.left, r.bottom - r.top); + + BITMAPINFO bmi; + ZeroMemory(&bmi, sizeof(BITMAPINFO)); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = dib_size.x; + bmi.bmiHeader.biHeight = dib_size.y; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = dib_size.x * dib_size.y * 4; + hBitmap = CreateDIBSection(hDC_dib, &bmi, DIB_RGB_COLORS, (void **)&dib_data, NULL, 0x0); + SelectObject(hDC_dib, hBitmap); + + ZeroMemory(dib_data, dib_size.x * dib_size.y * 4); + + layered_window = true; + } else { + //disable per-pixel alpha + layered_window = false; + + SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) & ~WS_EX_LAYERED); + + //cleanup + DeleteObject(hBitmap); + DeleteDC(hDC_dib); + } + } +} + +uint8_t *OS_Windows::get_layered_buffer_data() { + + return (is_layered_allowed() && layered_window) ? dib_data : NULL; +} + +Size2 OS_Windows::get_layered_buffer_size() { + + return (is_layered_allowed() && layered_window) ? dib_size : Size2(); +} + +void OS_Windows::swap_layered_buffer() { + + if (is_layered_allowed() && layered_window) { + + //premultiply alpha + for (int y = 0; y < dib_size.y; y++) { + for (int x = 0; x < dib_size.x; x++) { + float alpha = (float)dib_data[y * (int)dib_size.x * 4 + x * 4 + 3] / (float)0xFF; + dib_data[y * (int)dib_size.x * 4 + x * 4 + 0] *= alpha; + dib_data[y * (int)dib_size.x * 4 + x * 4 + 1] *= alpha; + dib_data[y * (int)dib_size.x * 4 + x * 4 + 2] *= alpha; + } + } + //swap layered window buffer + POINT ptSrc = { 0, 0 }; + SIZE sizeWnd = { (long)dib_size.x, (long)dib_size.y }; + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.AlphaFormat = AC_SRC_ALPHA; + bf.SourceConstantAlpha = 0xFF; + UpdateLayeredWindow(hWnd, NULL, NULL, &sizeWnd, hDC_dib, &ptSrc, 0, &bf, ULW_ALPHA); + } +} + void OS_Windows::set_borderless_window(bool p_borderless) { if (video_mode.borderless_window == p_borderless) return; + if (!p_borderless && layered_window) + set_window_per_pixel_transparency_enabled(false); + video_mode.borderless_window = p_borderless; _update_window_style(); @@ -2582,6 +2697,8 @@ Error OS_Windows::move_to_trash(const String &p_path) { OS_Windows::OS_Windows(HINSTANCE _hInstance) { key_event_pos = 0; + layered_window = false; + hBitmap = NULL; force_quit = false; alt_mem = false; gr_mem = false; @@ -2615,6 +2732,10 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { } OS_Windows::~OS_Windows() { + if (is_layered_allowed() && layered_window) { + DeleteObject(hBitmap); + DeleteDC(hDC_dib); + } #ifdef STDOUT_FILE fclose(stdo); #endif |