3232
3333#include " drop_target_windows.h"
3434#include " os_windows.h"
35+ #include " scene/main/window.h"
3536#include " wgl_detect_version.h"
3637
3738#include " core/config/project_settings.h"
8384
8485#define WM_INDICATOR_CALLBACK_MESSAGE (WM_USER + 1 )
8586
87+ int constexpr FS_TRANSP_BORDER = 2 ;
88+
8689static String format_error_message (DWORD id) {
8790 LPWSTR messageBuffer = nullptr ;
8891 size_t size = FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
@@ -167,8 +170,11 @@ void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) {
167170
168171 WindowData &wd = windows[window_id];
169172
173+ int off_x = (wd.multiwindow_fs || (!wd.fullscreen && wd.borderless && wd.maximized )) ? FS_TRANSP_BORDER : 0 ;
174+
170175 RECT clipRect;
171176 GetClientRect (wd.hWnd , &clipRect);
177+ clipRect.right -= off_x;
172178 ClientToScreen (wd.hWnd , (POINT *)&clipRect.left );
173179 ClientToScreen (wd.hWnd , (POINT *)&clipRect.right );
174180 ClipCursor (&clipRect);
@@ -1925,23 +1931,37 @@ void DisplayServerWindows::window_set_mouse_passthrough(const Vector<Vector2> &p
19251931
19261932void DisplayServerWindows::_update_window_mouse_passthrough (WindowID p_window) {
19271933 ERR_FAIL_COND (!windows.has (p_window));
1928- if (windows[p_window].mpass || windows[p_window].mpath .size () == 0 ) {
1929- SetWindowRgn (windows[p_window].hWnd , nullptr , FALSE );
1934+
1935+ const WindowData &wd = windows[p_window];
1936+ bool clip_pixel = (wd.multiwindow_fs || (wd.borderless && wd.maximized ));
1937+ bool pass_set = (wd.mpath .size () > 0 );
1938+ if (!clip_pixel && !pass_set) {
1939+ SetWindowRgn (wd.hWnd , nullptr , TRUE );
19301940 } else {
1931- POINT *points = (POINT *)memalloc (sizeof (POINT) * windows[p_window].mpath .size ());
1932- for (int i = 0 ; i < windows[p_window].mpath .size (); i++) {
1933- if (windows[p_window].borderless ) {
1934- points[i].x = windows[p_window].mpath [i].x ;
1935- points[i].y = windows[p_window].mpath [i].y ;
1936- } else {
1937- points[i].x = windows[p_window].mpath [i].x + GetSystemMetrics (SM_CXSIZEFRAME);
1938- points[i].y = windows[p_window].mpath [i].y + GetSystemMetrics (SM_CYSIZEFRAME) + GetSystemMetrics (SM_CYCAPTION);
1941+ HRGN region = nullptr ;
1942+ if (pass_set) {
1943+ Vector<POINT> points;
1944+ points.resize (wd.mpath .size ());
1945+ POINT *points_ptr = points.ptrw ();
1946+ for (int i = 0 ; i < wd.mpath .size (); i++) {
1947+ if (wd.borderless ) {
1948+ points_ptr[i].x = wd.mpath [i].x ;
1949+ points_ptr[i].y = wd.mpath [i].y ;
1950+ } else {
1951+ points_ptr[i].x = wd.mpath [i].x + GetSystemMetrics (SM_CXSIZEFRAME);
1952+ points_ptr[i].y = wd.mpath [i].y + GetSystemMetrics (SM_CYSIZEFRAME) + GetSystemMetrics (SM_CYCAPTION);
1953+ }
19391954 }
1955+ region = CreatePolygonRgn (points.ptr (), points.size (), ALTERNATE);
1956+ } else {
1957+ region = CreateRectRgn (0 , 0 , wd.width , wd.height );
19401958 }
1941-
1942- HRGN region = CreatePolygonRgn (points, windows[p_window].mpath .size (), ALTERNATE);
1943- SetWindowRgn (windows[p_window].hWnd , region, FALSE );
1944- memfree (points);
1959+ if (clip_pixel) {
1960+ HRGN region_clip = CreateRectRgn (0 , 0 , wd.width , wd.height );
1961+ CombineRgn (region, region, region_clip, RGN_AND);
1962+ DeleteObject (region_clip);
1963+ }
1964+ SetWindowRgn (wd.hWnd , region, FALSE );
19451965 }
19461966}
19471967
@@ -1972,14 +1992,16 @@ void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_wi
19721992 if (wd.fullscreen ) {
19731993 Point2 pos = screen_get_position (p_screen) + _get_screens_origin ();
19741994 Size2 size = screen_get_size (p_screen);
1995+ int off_x = (wd.multiwindow_fs || (!wd.fullscreen && wd.borderless && wd.maximized )) ? FS_TRANSP_BORDER : 0 ;
19751996
1976- MoveWindow (wd.hWnd , pos.x , pos.y , size.width , size.height , TRUE );
1997+ MoveWindow (wd.hWnd , pos.x , pos.y , size.width + off_x , size.height , TRUE );
19771998 } else if (wd.maximized ) {
19781999 Point2 pos = screen_get_position (p_screen) + _get_screens_origin ();
19792000 Size2 size = screen_get_size (p_screen);
2001+ int off_x = (wd.multiwindow_fs || (!wd.fullscreen && wd.borderless && wd.maximized )) ? FS_TRANSP_BORDER : 0 ;
19802002
19812003 ShowWindow (wd.hWnd , SW_RESTORE);
1982- MoveWindow (wd.hWnd , pos.x , pos.y , size.width , size.height , TRUE );
2004+ MoveWindow (wd.hWnd , pos.x , pos.y , size.width + off_x , size.height , TRUE );
19832005 ShowWindow (wd.hWnd , SW_MAXIMIZE);
19842006 } else {
19852007 Rect2i srect = screen_get_usable_rect (p_screen);
@@ -2228,7 +2250,8 @@ Size2i DisplayServerWindows::window_get_size(WindowID p_window) const {
22282250
22292251 RECT r;
22302252 if (GetClientRect (wd.hWnd , &r)) { // Retrieves area inside of window border, including decoration.
2231- return Size2 (r.right - r.left , r.bottom - r.top );
2253+ int off_x = (wd.multiwindow_fs || (!wd.fullscreen && wd.borderless && wd.maximized )) ? FS_TRANSP_BORDER : 0 ;
2254+ return Size2 (r.right - r.left - off_x, r.bottom - r.top );
22322255 }
22332256 return Size2 ();
22342257}
@@ -2241,7 +2264,8 @@ Size2i DisplayServerWindows::window_get_size_with_decorations(WindowID p_window)
22412264
22422265 RECT r;
22432266 if (GetWindowRect (wd.hWnd , &r)) { // Retrieves area inside of window border, including decoration.
2244- return Size2 (r.right - r.left , r.bottom - r.top );
2267+ int off_x = (wd.multiwindow_fs || (!wd.fullscreen && wd.borderless && wd.maximized )) ? FS_TRANSP_BORDER : 0 ;
2268+ return Size2 (r.right - r.left - off_x, r.bottom - r.top );
22452269 }
22462270 return Size2 ();
22472271}
@@ -2280,9 +2304,6 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_initiali
22802304 r_style |= WS_MAXIMIZEBOX;
22812305 }
22822306 }
2283- if ((p_fullscreen && p_multiwindow_fs) || p_maximized_fs) {
2284- r_style |= WS_BORDER; // Allows child windows to be displayed on top of full screen.
2285- }
22862307 } else {
22872308 if (p_resizable) {
22882309 if (p_minimized) {
@@ -2340,8 +2361,8 @@ void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repain
23402361 if (p_repaint) {
23412362 RECT rect;
23422363 GetWindowRect (wd.hWnd , &rect);
2343-
2344- MoveWindow (wd.hWnd , rect.left , rect.top , rect.right - rect.left , rect.bottom - rect.top , TRUE );
2364+ int off_x = (wd. multiwindow_fs || (!wd. fullscreen && wd. borderless && wd. maximized )) ? FS_TRANSP_BORDER : 0 ;
2365+ MoveWindow (wd.hWnd , rect.left , rect.top , rect.right - rect.left + off_x , rect.bottom - rect.top , TRUE );
23452366 }
23462367}
23472368
@@ -2359,6 +2380,10 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
23592380 bool was_fullscreen = wd.fullscreen ;
23602381 wd.was_fullscreen_pre_min = false ;
23612382
2383+ if (p_mode == WINDOW_MODE_MAXIMIZED && wd.borderless ) {
2384+ p_mode = WINDOW_MODE_FULLSCREEN;
2385+ }
2386+
23622387 if (wd.fullscreen && p_mode != WINDOW_MODE_FULLSCREEN && p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
23632388 RECT rect;
23642389
@@ -2410,11 +2435,10 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
24102435
24112436 if (p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
24122437 wd.multiwindow_fs = false ;
2413- _update_window_style (p_window, false );
2414- } else {
2438+ } else if (p_mode == WINDOW_MODE_FULLSCREEN) {
24152439 wd.multiwindow_fs = true ;
2416- _update_window_style (p_window, false );
24172440 }
2441+ _update_window_style (p_window, false );
24182442
24192443 if ((p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) && !wd.fullscreen ) {
24202444 if (wd.minimized || wd.maximized ) {
@@ -2440,7 +2464,8 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
24402464
24412465 _update_window_style (p_window, false );
24422466
2443- MoveWindow (wd.hWnd , pos.x , pos.y , size.width , size.height , TRUE );
2467+ int off_x = (wd.multiwindow_fs || (!wd.fullscreen && wd.borderless && wd.maximized )) ? FS_TRANSP_BORDER : 0 ;
2468+ MoveWindow (wd.hWnd , pos.x , pos.y , size.width + off_x, size.height , TRUE );
24442469
24452470 // If the user has mouse trails enabled in windows, then sometimes the cursor disappears in fullscreen mode.
24462471 // Save number of trails so we can restore when exiting, then turn off mouse trails
@@ -2449,6 +2474,7 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
24492474 SystemParametersInfoA (SPI_SETMOUSETRAILS, 0 , nullptr , 0 );
24502475 }
24512476 }
2477+ _update_window_mouse_passthrough (p_window);
24522478}
24532479
24542480DisplayServer::WindowMode DisplayServerWindows::window_get_mode (WindowID p_window) const {
@@ -2498,8 +2524,8 @@ void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, W
24982524 } break ;
24992525 case WINDOW_FLAG_BORDERLESS: {
25002526 wd.borderless = p_enabled;
2501- _update_window_style (p_window);
25022527 _update_window_mouse_passthrough (p_window);
2528+ _update_window_style (p_window);
25032529 ShowWindow (wd.hWnd , (wd.no_focus || wd.is_popup ) ? SW_SHOWNOACTIVATE : SW_SHOW); // Show the window.
25042530 } break ;
25052531 case WINDOW_FLAG_ALWAYS_ON_TOP: {
@@ -2550,7 +2576,6 @@ void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, W
25502576 } break ;
25512577 case WINDOW_FLAG_MOUSE_PASSTHROUGH: {
25522578 wd.mpass = p_enabled;
2553- _update_window_mouse_passthrough (p_window);
25542579 } break ;
25552580 case WINDOW_FLAG_EXCLUDE_FROM_CAPTURE: {
25562581 wd.hide_from_capture = p_enabled;
@@ -4529,30 +4554,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
45294554 SendMessageW (windows[window_id].hWnd , WM_PAINT, 0 , 0 );
45304555 }
45314556 } break ;
4532- case WM_NCPAINT: {
4533- if (RenderingServer::get_singleton () && (windows[window_id].borderless || (windows[window_id].fullscreen && windows[window_id].multiwindow_fs ))) {
4534- Color color = RenderingServer::get_singleton ()->get_default_clear_color ();
4535- HDC hdc = GetWindowDC (hWnd);
4536- if (hdc) {
4537- HPEN pen = CreatePen (PS_SOLID, 1 , RGB (color.r * 255 .f , color.g * 255 .f , color.b * 255 .f ));
4538- if (pen) {
4539- HGDIOBJ prev_pen = SelectObject (hdc, pen);
4540- HGDIOBJ prev_brush = SelectObject (hdc, GetStockObject (NULL_BRUSH));
4541-
4542- RECT rc;
4543- GetWindowRect (hWnd, &rc);
4544- OffsetRect (&rc, -rc.left , -rc.top );
4545- Rectangle (hdc, rc.left , rc.top , rc.right , rc.bottom );
4546-
4547- SelectObject (hdc, prev_pen);
4548- SelectObject (hdc, prev_brush);
4549- DeleteObject (pen);
4550- }
4551- ReleaseDC (hWnd, hdc);
4552- }
4553- return 0 ;
4554- }
4555- } break ;
45564557 case WM_NCHITTEST: {
45574558 if (windows[window_id].mpass ) {
45584559 return HTTRANSPARENT;
@@ -5558,24 +5559,26 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
55585559 } break ;
55595560
55605561 case WM_WINDOWPOSCHANGED: {
5562+ WindowData &window = windows[window_id];
5563+
5564+ int off_x = (window.multiwindow_fs || (!window.fullscreen && window.borderless && IsZoomed (hWnd))) ? FS_TRANSP_BORDER : 0 ;
55615565 Rect2i window_client_rect;
55625566 Rect2i window_rect;
55635567 {
55645568 RECT rect;
55655569 GetClientRect (hWnd, &rect);
55665570 ClientToScreen (hWnd, (POINT *)&rect.left );
55675571 ClientToScreen (hWnd, (POINT *)&rect.right );
5568- window_client_rect = Rect2i (rect.left , rect.top , rect.right - rect.left , rect.bottom - rect.top );
5572+ window_client_rect = Rect2i (rect.left , rect.top , rect.right - rect.left - off_x , rect.bottom - rect.top );
55695573 window_client_rect.position -= _get_screens_origin ();
55705574
55715575 RECT wrect;
55725576 GetWindowRect (hWnd, &wrect);
5573- window_rect = Rect2i (wrect.left , wrect.top , wrect.right - wrect.left , wrect.bottom - wrect.top );
5577+ window_rect = Rect2i (wrect.left , wrect.top , wrect.right - wrect.left - off_x , wrect.bottom - wrect.top );
55745578 window_rect.position -= _get_screens_origin ();
55755579 }
55765580
55775581 WINDOWPOS *window_pos_params = (WINDOWPOS *)lParam;
5578- WindowData &window = windows[window_id];
55795582
55805583 bool rect_changed = false ;
55815584 if (!(window_pos_params->flags & SWP_NOSIZE) || window_pos_params->flags & SWP_FRAMECHANGED) {
@@ -5644,6 +5647,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
56445647 if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
56455648 RECT crect;
56465649 GetClientRect (window.hWnd , &crect);
5650+ crect.right -= off_x;
56475651 ClientToScreen (window.hWnd , (POINT *)&crect.left );
56485652 ClientToScreen (window.hWnd , (POINT *)&crect.right );
56495653 ClipCursor (&crect);
@@ -6109,26 +6113,29 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
61096113
61106114 _get_window_style (window_id_counter == MAIN_WINDOW_ID, false , (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN), p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MINIMIZED, p_mode == WINDOW_MODE_MAXIMIZED, false , (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) | (p_flags & WINDOW_FLAG_POPUP), p_parent_hwnd, dwStyle, dwExStyle);
61116115
6112- RECT WindowRect;
6113-
6114- WindowRect.left = p_rect.position .x ;
6115- WindowRect.right = p_rect.position .x + p_rect.size .x ;
6116- WindowRect.top = p_rect.position .y ;
6117- WindowRect.bottom = p_rect.position .y + p_rect.size .y ;
6118-
61196116 int rq_screen = get_screen_from_rect (p_rect);
61206117 if (rq_screen < 0 ) {
61216118 rq_screen = get_primary_screen (); // Requested window rect is outside any screen bounds.
61226119 }
6120+ Rect2i usable_rect = screen_get_usable_rect (rq_screen);
61236121
61246122 Point2i offset = _get_screens_origin ();
61256123
6124+ RECT WindowRect;
6125+
6126+ int off_x = (p_mode == WINDOW_MODE_FULLSCREEN || ((p_flags & WINDOW_FLAG_BORDERLESS_BIT) && p_mode == WINDOW_MODE_MAXIMIZED)) ? FS_TRANSP_BORDER : 0 ;
6127+
6128+ WindowRect.left = p_rect.position .x ;
6129+ WindowRect.right = p_rect.position .x + p_rect.size .x + off_x;
6130+ WindowRect.top = p_rect.position .y ;
6131+ WindowRect.bottom = p_rect.position .y + p_rect.size .y ;
6132+
61266133 if (!p_parent_hwnd) {
61276134 if (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
61286135 Rect2i screen_rect = Rect2i (screen_get_position (rq_screen), screen_get_size (rq_screen));
61296136
61306137 WindowRect.left = screen_rect.position .x ;
6131- WindowRect.right = screen_rect.position .x + screen_rect.size .x ;
6138+ WindowRect.right = screen_rect.position .x + screen_rect.size .x + off_x ;
61326139 WindowRect.top = screen_rect.position .y ;
61336140 WindowRect.bottom = screen_rect.position .y + screen_rect.size .y ;
61346141 } else {
@@ -6139,7 +6146,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
61396146 }
61406147
61416148 WindowRect.left = wpos.x ;
6142- WindowRect.right = wpos.x + p_rect.size .x ;
6149+ WindowRect.right = wpos.x + p_rect.size .x + off_x ;
61436150 WindowRect.top = wpos.y ;
61446151 WindowRect.bottom = wpos.y + p_rect.size .y ;
61456152 }
@@ -6277,15 +6284,15 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
62776284 return INVALID_WINDOW_ID;
62786285 }
62796286
6280- rendering_context->window_set_size (id, real_client_rect.right - real_client_rect.left , real_client_rect.bottom - real_client_rect.top );
6287+ rendering_context->window_set_size (id, real_client_rect.right - real_client_rect.left - off_x , real_client_rect.bottom - real_client_rect.top );
62816288 rendering_context->window_set_vsync_mode (id, p_vsync_mode);
62826289 wd.context_created = true ;
62836290 }
62846291#endif
62856292
62866293#ifdef GLES3_ENABLED
62876294 if (gl_manager_native) {
6288- if (gl_manager_native->window_create (id, wd.hWnd , hInstance, real_client_rect.right - real_client_rect.left , real_client_rect.bottom - real_client_rect.top ) != OK) {
6295+ if (gl_manager_native->window_create (id, wd.hWnd , hInstance, real_client_rect.right - real_client_rect.left - off_x , real_client_rect.bottom - real_client_rect.top ) != OK) {
62896296 memdelete (gl_manager_native);
62906297 gl_manager_native = nullptr ;
62916298 windows.erase (id);
@@ -6295,7 +6302,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
62956302 }
62966303
62976304 if (gl_manager_angle) {
6298- if (gl_manager_angle->window_create (id, nullptr , wd.hWnd , real_client_rect.right - real_client_rect.left , real_client_rect.bottom - real_client_rect.top ) != OK) {
6305+ if (gl_manager_angle->window_create (id, nullptr , wd.hWnd , real_client_rect.right - real_client_rect.left - off_x , real_client_rect.bottom - real_client_rect.top ) != OK) {
62996306 memdelete (gl_manager_angle);
63006307 gl_manager_angle = nullptr ;
63016308 windows.erase (id);
@@ -6390,21 +6397,20 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
63906397 ClientToScreen (wd.hWnd , (POINT *)&r.left );
63916398 ClientToScreen (wd.hWnd , (POINT *)&r.right );
63926399 wd.last_pos = Point2i (r.left , r.top ) - _get_screens_origin ();
6393- wd.width = r.right - r.left ;
6400+ wd.width = r.right - r.left - off_x ;
63946401 wd.height = r.bottom - r.top ;
63956402 } else {
63966403 wd.last_pos = p_rect.position ;
63976404 wd.width = p_rect.size .width ;
63986405 wd.height = p_rect.size .height ;
63996406 }
64006407
6408+ wd.create_completed = true ;
64016409 // Set size of maximized borderless window (by default it covers the entire screen).
6402- if (p_mode == WINDOW_MODE_MAXIMIZED && (p_flags & WINDOW_FLAG_BORDERLESS_BIT)) {
6403- Rect2i srect = screen_get_usable_rect (rq_screen);
6404- SetWindowPos (wd.hWnd , HWND_TOP, srect.position .x , srect.position .y , srect.size .width , srect.size .height , SWP_NOZORDER | SWP_NOACTIVATE);
6410+ if (!p_parent_hwnd && p_mode == WINDOW_MODE_MAXIMIZED && (p_flags & WINDOW_FLAG_BORDERLESS_BIT)) {
6411+ SetWindowPos (wd.hWnd , HWND_TOP, usable_rect.position .x - off_x, usable_rect.position .y , usable_rect.size .width + off_x, usable_rect.size .height , SWP_NOZORDER | SWP_NOACTIVATE);
64056412 }
6406-
6407- wd.create_completed = true ;
6413+ _update_window_mouse_passthrough (id);
64086414 window_id_counter++;
64096415 }
64106416
0 commit comments