summaryrefslogtreecommitdiff
path: root/platform/windows
diff options
context:
space:
mode:
authorHein-Pieter van Braam <hp@tmm.cx>2018-05-08 16:44:35 +0200
committerGitHub <noreply@github.com>2018-05-08 16:44:35 +0200
commite668757aa9ff4ccd3a90b1f402aba8a424b4c11d (patch)
treee569a46b16008d39e541d484fed95ad58ee4068a /platform/windows
parentaacd7f012ebcfb7f8023ebecba2e003fcd018e98 (diff)
parentddae098deec89d67228a74623ebe7f5db39f425b (diff)
Merge pull request #14622 from bruvzg/non-rectangular-windows
Experimental support for windows with per-pixel transparency.
Diffstat (limited to 'platform/windows')
-rw-r--r--platform/windows/os_windows.cpp121
-rw-r--r--platform/windows/os_windows.h13
2 files changed, 134 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
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 584f6fb334..221109318e 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -93,6 +93,12 @@ class OS_Windows : public OS {
HINSTANCE hInstance; // Holds The Instance Of The Application
HWND hWnd;
+ HBITMAP hBitmap; //DIB section for layered window
+ uint8_t *dib_data;
+ Size2 dib_size;
+ HDC hDC_dib;
+ bool layered_window;
+
uint32_t move_timer_id;
HCURSOR hCursor;
@@ -212,6 +218,13 @@ public:
virtual void set_borderless_window(bool p_borderless);
virtual bool get_borderless_window();
+ virtual bool get_window_per_pixel_transparency_enabled() const;
+ virtual void set_window_per_pixel_transparency_enabled(bool p_enabled);
+
+ virtual uint8_t *get_layered_buffer_data();
+ virtual Size2 get_layered_buffer_size();
+ virtual void swap_layered_buffer();
+
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false);
virtual Error close_dynamic_library(void *p_library_handle);
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false);