@@ -25,9 +25,9 @@ use windows_sys::Win32::{
25
25
Devices :: HumanInterfaceDevice :: MOUSE_MOVE_RELATIVE ,
26
26
Foundation :: { BOOL , HANDLE , HWND , LPARAM , LRESULT , POINT , RECT , WAIT_TIMEOUT , WPARAM } ,
27
27
Graphics :: Gdi :: {
28
- ClientToScreen , GetMonitorInfoW , GetUpdateRect , MonitorFromRect , MonitorFromWindow ,
29
- RedrawWindow , ScreenToClient , ValidateRect , MONITORINFO , MONITOR_DEFAULTTONULL ,
30
- RDW_INTERNALPAINT , SC_SCREENSAVE ,
28
+ GetMonitorInfoW , GetUpdateRect , MonitorFromRect , MonitorFromWindow , RedrawWindow ,
29
+ ScreenToClient , ValidateRect , MONITORINFO , MONITOR_DEFAULTTONULL , RDW_INTERNALPAINT ,
30
+ SC_SCREENSAVE ,
31
31
} ,
32
32
Media :: { timeBeginPeriod, timeEndPeriod, timeGetDevCaps, TIMECAPS , TIMERR_NOERROR } ,
33
33
System :: { Ole :: RevokeDragDrop , Threading :: GetCurrentThreadId , WindowsProgramming :: INFINITE } ,
@@ -50,20 +50,20 @@ use windows_sys::Win32::{
50
50
RIM_TYPEKEYBOARD , RIM_TYPEMOUSE ,
51
51
} ,
52
52
WindowsAndMessaging :: {
53
- CreateWindowExW , DefWindowProcW , DestroyWindow , DispatchMessageW , GetClientRect ,
54
- GetCursorPos , GetMessageW , GetWindowLongW , LoadCursorW , MsgWaitForMultipleObjectsEx ,
55
- PeekMessageW , PostMessageW , PostThreadMessageW , RegisterClassExW ,
56
- RegisterWindowMessageA , SetCursor , SetWindowPos , TranslateMessage , CREATESTRUCTW ,
57
- GIDC_ARRIVAL , GIDC_REMOVAL , GWL_EXSTYLE , GWL_STYLE , GWL_USERDATA , HTCAPTION , HTCLIENT ,
58
- MAPVK_VK_TO_VSC , MINMAXINFO , MSG , MWMO_INPUTAVAILABLE , PM_NOREMOVE , PM_QS_PAINT ,
59
- PM_REMOVE , PT_PEN , PT_TOUCH , QS_ALLEVENTS , RI_KEY_E0 , RI_KEY_E1 , RI_MOUSE_WHEEL ,
60
- SC_MINIMIZE , SC_RESTORE , SIZE_MAXIMIZED , SWP_NOACTIVATE , SWP_NOMOVE , SWP_NOSIZE ,
61
- SWP_NOZORDER , WHEEL_DELTA , WINDOWPOS , WM_CAPTURECHANGED , WM_CHAR , WM_CLOSE , WM_CREATE ,
62
- WM_DESTROY , WM_DPICHANGED , WM_DROPFILES , WM_ENTERSIZEMOVE , WM_EXITSIZEMOVE ,
63
- WM_GETMINMAXINFO , WM_IME_COMPOSITION , WM_IME_ENDCOMPOSITION , WM_IME_SETCONTEXT ,
64
- WM_IME_STARTCOMPOSITION , WM_INPUT , WM_INPUT_DEVICE_CHANGE , WM_KEYDOWN , WM_KEYUP ,
65
- WM_KILLFOCUS , WM_LBUTTONDOWN , WM_LBUTTONUP , WM_MBUTTONDOWN , WM_MBUTTONUP ,
66
- WM_MOUSEHWHEEL , WM_MOUSEMOVE , WM_MOUSEWHEEL , WM_NCACTIVATE , WM_NCCREATE , WM_NCDESTROY ,
53
+ CreateWindowExW , DefWindowProcW , DestroyWindow , DispatchMessageW , GetCursorPos ,
54
+ GetMessageW , LoadCursorW , MsgWaitForMultipleObjectsEx , PeekMessageW , PostMessageW ,
55
+ PostThreadMessageW , RegisterClassExW , RegisterWindowMessageA , SetCursor , SetWindowPos ,
56
+ TranslateMessage , CREATESTRUCTW , GIDC_ARRIVAL , GIDC_REMOVAL , GWL_STYLE , GWL_USERDATA ,
57
+ HTCAPTION , HTCLIENT , MAPVK_VK_TO_VSC , MINMAXINFO , MSG , MWMO_INPUTAVAILABLE ,
58
+ NCCALCSIZE_PARAMS , PM_NOREMOVE , PM_QS_PAINT , PM_REMOVE , PT_PEN , PT_TOUCH , QS_ALLEVENTS ,
59
+ RI_KEY_E0 , RI_KEY_E1 , RI_MOUSE_WHEEL , SC_MINIMIZE , SC_RESTORE , SIZE_MAXIMIZED ,
60
+ SWP_NOACTIVATE , SWP_NOMOVE , SWP_NOSIZE , SWP_NOZORDER , WHEEL_DELTA , WINDOWPOS ,
61
+ WM_CAPTURECHANGED , WM_CHAR , WM_CLOSE , WM_CREATE , WM_DESTROY , WM_DPICHANGED ,
62
+ WM_DROPFILES , WM_ENTERSIZEMOVE , WM_EXITSIZEMOVE , WM_GETMINMAXINFO , WM_IME_COMPOSITION ,
63
+ WM_IME_ENDCOMPOSITION , WM_IME_SETCONTEXT , WM_IME_STARTCOMPOSITION , WM_INPUT ,
64
+ WM_INPUT_DEVICE_CHANGE , WM_KEYDOWN , WM_KEYUP , WM_KILLFOCUS , WM_LBUTTONDOWN ,
65
+ WM_LBUTTONUP , WM_MBUTTONDOWN , WM_MBUTTONUP , WM_MOUSEHWHEEL , WM_MOUSEMOVE ,
66
+ WM_MOUSEWHEEL , WM_NCACTIVATE , WM_NCCALCSIZE , WM_NCCREATE , WM_NCDESTROY ,
67
67
WM_NCLBUTTONDOWN , WM_PAINT , WM_POINTERDOWN , WM_POINTERUP , WM_POINTERUPDATE ,
68
68
WM_RBUTTONDOWN , WM_RBUTTONUP , WM_SETCURSOR , WM_SETFOCUS , WM_SETTINGCHANGE , WM_SIZE ,
69
69
WM_SYSCHAR , WM_SYSCOMMAND , WM_SYSKEYDOWN , WM_SYSKEYUP , WM_TOUCH , WM_WINDOWPOSCHANGED ,
@@ -633,10 +633,12 @@ pub static TASKBAR_CREATED: Lazy<u32> =
633
633
Lazy :: new ( || unsafe { RegisterWindowMessageA ( "TaskbarCreated\0 " . as_ptr ( ) ) } ) ;
634
634
635
635
fn create_event_target_window < T : ' static > ( ) -> HWND {
636
+ use windows_sys:: Win32 :: UI :: WindowsAndMessaging :: CS_HREDRAW ;
637
+ use windows_sys:: Win32 :: UI :: WindowsAndMessaging :: CS_VREDRAW ;
636
638
unsafe {
637
639
let class = WNDCLASSEXW {
638
640
cbSize : mem:: size_of :: < WNDCLASSEXW > ( ) as u32 ,
639
- style : 0 ,
641
+ style : CS_HREDRAW | CS_VREDRAW ,
640
642
lpfnWndProc : Some ( thread_event_target_callback :: < T > ) ,
641
643
cbClsExtra : 0 ,
642
644
cbWndExtra : 0 ,
@@ -968,6 +970,32 @@ unsafe fn public_window_callback_inner<T: 'static>(
968
970
// the closure to catch_unwind directly so that the match body indendation wouldn't change and
969
971
// the git blame and history would be preserved.
970
972
let callback = || match msg {
973
+ WM_NCCALCSIZE => {
974
+ let window_flags = userdata. window_state . lock ( ) . window_flags ;
975
+ if wparam == 0 || window_flags. contains ( WindowFlags :: MARKER_DECORATIONS ) {
976
+ return DefWindowProcW ( window, msg, wparam, lparam) ;
977
+ }
978
+
979
+ // Extend the client area to cover the whole non-client area.
980
+ // https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-nccalcsize#remarks
981
+ //
982
+ // HACK(msiglreith): To add the drop shadow we slightly tweak the non-client area.
983
+ // This leads to a small black 1px border on the top. Adding a margin manually
984
+ // on all 4 borders would result in the caption getting drawn by the DWM.
985
+ //
986
+ // Another option would be to allow the DWM to paint inside the client area.
987
+ // Unfortunately this results in janky resize behavior, where the compositor is
988
+ // ahead of the window surface. Currently, there seems no option to achieve this
989
+ // with the Windows API.
990
+ if window_flags. contains ( WindowFlags :: MARKER_UNDECORATED_SHADOW ) {
991
+ let params = & mut * ( lparam as * mut NCCALCSIZE_PARAMS ) ;
992
+ params. rgrc [ 0 ] . top += 1 ;
993
+ params. rgrc [ 0 ] . bottom += 1 ;
994
+ }
995
+
996
+ 0
997
+ }
998
+
971
999
WM_ENTERSIZEMOVE => {
972
1000
userdata
973
1001
. window_state
@@ -1049,7 +1077,7 @@ unsafe fn public_window_callback_inner<T: 'static>(
1049
1077
const NOMOVE_OR_NOSIZE : u32 = SWP_NOMOVE | SWP_NOSIZE ;
1050
1078
1051
1079
let new_rect = if window_pos. flags & NOMOVE_OR_NOSIZE != 0 {
1052
- let cur_rect = util:: get_window_rect ( window)
1080
+ let cur_rect = util:: WindowArea :: Outer . get_rect ( window)
1053
1081
. expect ( "Unexpected GetWindowRect failure; please report this error to https://github.com/rust-windowing/winit" ) ;
1054
1082
1055
1083
match window_pos. flags & NOMOVE_OR_NOSIZE {
@@ -1921,19 +1949,22 @@ unsafe fn public_window_callback_inner<T: 'static>(
1921
1949
let mmi = lparam as * mut MINMAXINFO ;
1922
1950
1923
1951
let window_state = userdata. window_state . lock ( ) ;
1952
+ let window_flags = window_state. window_flags ;
1924
1953
1925
1954
if window_state. min_size . is_some ( ) || window_state. max_size . is_some ( ) {
1926
1955
if let Some ( min_size) = window_state. min_size {
1927
1956
let min_size = min_size. to_physical ( window_state. scale_factor ) ;
1928
- let ( width, height) : ( u32 , u32 ) = util:: adjust_size ( window, min_size) . into ( ) ;
1957
+ let ( width, height) : ( u32 , u32 ) =
1958
+ window_flags. adjust_size ( window, min_size) . into ( ) ;
1929
1959
( * mmi) . ptMinTrackSize = POINT {
1930
1960
x : width as i32 ,
1931
1961
y : height as i32 ,
1932
1962
} ;
1933
1963
}
1934
1964
if let Some ( max_size) = window_state. max_size {
1935
1965
let max_size = max_size. to_physical ( window_state. scale_factor ) ;
1936
- let ( width, height) : ( u32 , u32 ) = util:: adjust_size ( window, max_size) . into ( ) ;
1966
+ let ( width, height) : ( u32 , u32 ) =
1967
+ window_flags. adjust_size ( window, max_size) . into ( ) ;
1937
1968
( * mmi) . ptMaxTrackSize = POINT {
1938
1969
x : width as i32 ,
1939
1970
y : height as i32 ,
@@ -1957,7 +1988,7 @@ unsafe fn public_window_callback_inner<T: 'static>(
1957
1988
let new_scale_factor = dpi_to_scale_factor ( new_dpi_x) ;
1958
1989
let old_scale_factor: f64 ;
1959
1990
1960
- let allow_resize = {
1991
+ let ( allow_resize, window_flags ) = {
1961
1992
let mut window_state = userdata. window_state . lock ( ) ;
1962
1993
old_scale_factor = window_state. scale_factor ;
1963
1994
window_state. scale_factor = new_scale_factor;
@@ -1966,12 +1997,11 @@ unsafe fn public_window_callback_inner<T: 'static>(
1966
1997
return 0 ;
1967
1998
}
1968
1999
1969
- window_state. fullscreen . is_none ( )
1970
- && !window_state. window_flags ( ) . contains ( WindowFlags :: MAXIMIZED )
1971
- } ;
2000
+ let allow_resize = window_state. fullscreen . is_none ( )
2001
+ && !window_state. window_flags ( ) . contains ( WindowFlags :: MAXIMIZED ) ;
1972
2002
1973
- let style = GetWindowLongW ( window , GWL_STYLE ) as u32 ;
1974
- let style_ex = GetWindowLongW ( window , GWL_EXSTYLE ) as u32 ;
2003
+ ( allow_resize , window_state . window_flags )
2004
+ } ;
1975
2005
1976
2006
// New size as suggested by Windows.
1977
2007
let suggested_rect = * ( lparam as * const RECT ) ;
@@ -1985,28 +2015,18 @@ unsafe fn public_window_callback_inner<T: 'static>(
1985
2015
// let margin_right: i32;
1986
2016
// let margin_bottom: i32;
1987
2017
{
1988
- let adjusted_rect =
1989
- util :: adjust_window_rect_with_styles ( window, style , style_ex , suggested_rect)
1990
- . unwrap_or ( suggested_rect) ;
2018
+ let adjusted_rect = window_flags
2019
+ . adjust_rect ( window, suggested_rect)
2020
+ . unwrap_or ( suggested_rect) ;
1991
2021
margin_left = suggested_rect. left - adjusted_rect. left ;
1992
2022
margin_top = suggested_rect. top - adjusted_rect. top ;
1993
2023
// margin_right = adjusted_rect.right - suggested_rect.right;
1994
2024
// margin_bottom = adjusted_rect.bottom - suggested_rect.bottom;
1995
2025
}
1996
2026
1997
- let old_physical_inner_rect = {
1998
- let mut old_physical_inner_rect = mem:: zeroed ( ) ;
1999
- GetClientRect ( window, & mut old_physical_inner_rect) ;
2000
- let mut origin = mem:: zeroed ( ) ;
2001
- ClientToScreen ( window, & mut origin) ;
2002
-
2003
- old_physical_inner_rect. left += origin. x ;
2004
- old_physical_inner_rect. right += origin. x ;
2005
- old_physical_inner_rect. top += origin. y ;
2006
- old_physical_inner_rect. bottom += origin. y ;
2007
-
2008
- old_physical_inner_rect
2009
- } ;
2027
+ let old_physical_inner_rect = util:: WindowArea :: Inner
2028
+ . get_rect ( window)
2029
+ . expect ( "failed to query (old) inner window area" ) ;
2010
2030
let old_physical_inner_size = PhysicalSize :: new (
2011
2031
( old_physical_inner_rect. right - old_physical_inner_rect. left ) as u32 ,
2012
2032
( old_physical_inner_rect. bottom - old_physical_inner_rect. top ) as u32 ,
@@ -2060,13 +2080,9 @@ unsafe fn public_window_callback_inner<T: 'static>(
2060
2080
bottom : suggested_ul. 1 + new_physical_inner_size. height as i32 ,
2061
2081
} ;
2062
2082
2063
- conservative_rect = util:: adjust_window_rect_with_styles (
2064
- window,
2065
- style,
2066
- style_ex,
2067
- conservative_rect,
2068
- )
2069
- . unwrap_or ( conservative_rect) ;
2083
+ conservative_rect = window_flags
2084
+ . adjust_rect ( window, conservative_rect)
2085
+ . unwrap_or ( conservative_rect) ;
2070
2086
2071
2087
// If we're dragging the window, offset the window so that the cursor's
2072
2088
// relative horizontal position in the title bar is preserved.
0 commit comments