@@ -19,14 +19,14 @@ use winapi::{
1919 d3d11:: * ,
2020 d3dcommon:: * ,
2121 winuser:: {
22- self , CallNextHookEx , SetWindowsHookExA , UnhookWindowsHookEx , MSLLHOOKSTRUCT ,
23- WH_MOUSE_LL ,
22+ self , CallNextHookEx , SetWindowLongA , SetWindowPos , SetWindowsHookExA ,
23+ UnhookWindowsHookEx , HWND_TOPMOST , MSLLHOOKSTRUCT , SWP_FRAMECHANGED , SWP_NOACTIVATE ,
24+ SWP_NOMOVE , SWP_NOSIZE , SWP_SHOWWINDOW , WH_MOUSE_LL ,
2425 } ,
2526 } ,
2627 Interface as _,
2728} ;
2829use winit:: platform:: run_on_demand:: EventLoopExtRunOnDemand ;
29- use winit:: window:: WindowLevel ;
3030use winit:: {
3131 event:: { DeviceId , Event , WindowEvent } ,
3232 event_loop:: EventLoop ,
@@ -44,6 +44,9 @@ struct Inner {
4444 imgui : imgui:: Context ,
4545 ctx : Context ,
4646
47+ overlay_mode : bool ,
48+ last_topmost_refresh : Instant ,
49+
4750 renderer : imgui_dx11_renderer:: Renderer ,
4851 context : ComPtr < ID3D11DeviceContext > ,
4952 main_rtv : ComPtr < ID3D11RenderTargetView > ,
@@ -78,7 +81,6 @@ impl D3D11Renderer {
7881 pub fn new ( settings : & Settings ) -> Self {
7982 let event_loop = EventLoop :: new ( ) . unwrap ( ) ;
8083
81- // let on_top = settings.on_top || settings.overlay_mode;
8284 let maximized = settings. overlay_mode ;
8385 let decorations = !settings. overlay_mode ;
8486 let fullscreen = if settings. overlay_mode {
@@ -92,18 +94,14 @@ impl D3D11Renderer {
9294 . with_transparent ( true )
9395 . with_maximized ( maximized)
9496 . with_decorations ( decorations)
95- // we set this later, or else we segfault ¯\_(ツ)_/¯
96- // .with_window_level(if on_top {
97- // WindowLevel::AlwaysOnTop
98- // } else {
99- // WindowLevel::Normal
100- // })
10197 . with_fullscreen ( fullscreen)
10298 . build ( & event_loop)
10399 . unwrap ( ) ;
104100
105101 if settings. overlay_mode {
106102 window. set_cursor_hittest ( false ) . unwrap ( ) ;
103+ // Don't set this here, or else we segfault
104+ // window.set_window_level(WindowLevel::AlwaysOnTop);
107105 }
108106
109107 let hwnd = match window. raw_window_handle ( ) {
@@ -128,10 +126,10 @@ impl D3D11Renderer {
128126 unsafe { imgui_dx11_renderer:: Renderer :: new ( & mut imgui, device. clone ( ) ) . unwrap ( ) } ;
129127
130128 let mut low_level_mouse_proc: Option < HHOOK > = None ;
131- // let mut winit_wnd_proc: winuser::WNDPROC = None;
132129 if settings. overlay_mode {
133- // this has to be after renderer is created or else we segfault
134- window. set_window_level ( WindowLevel :: AlwaysOnTop ) ;
130+ // best-effort: keep window above borderless fullscreen
131+ unsafe { apply_overlay_topmost ( hwnd) } ;
132+ // register low level mouse proc for hittesting abuse
135133 unsafe {
136134 low_level_mouse_proc. replace ( SetWindowsHookExA (
137135 WH_MOUSE_LL ,
@@ -140,6 +138,7 @@ impl D3D11Renderer {
140138 0 ,
141139 ) ) ;
142140
141+ // let mut winit_wnd_proc: winuser::WNDPROC = None;
143142 // let orig_wnd_proc = SetWindowLongPtrA(
144143 // hwnd as HWND,
145144 // winuser::GWL_WNDPROC as i32,
@@ -156,6 +155,8 @@ impl D3D11Renderer {
156155 platform,
157156 imgui,
158157 ctx,
158+ overlay_mode : settings. overlay_mode ,
159+ last_topmost_refresh : Instant :: now ( ) ,
159160 renderer,
160161 context,
161162 main_rtv,
@@ -185,6 +186,8 @@ impl Renderer for D3D11Renderer {
185186 platform,
186187 imgui,
187188 ctx,
189+ overlay_mode,
190+ last_topmost_refresh,
188191 renderer,
189192 context,
190193 main_rtv,
@@ -211,6 +214,18 @@ impl Renderer for D3D11Renderer {
211214 event : winit:: event:: WindowEvent :: RedrawRequested ,
212215 ..
213216 } => {
217+ // force the window to the top on a best-effort basis, all other approaches have failed
218+ if * overlay_mode
219+ && last_topmost_refresh. elapsed ( )
220+ >= std:: time:: Duration :: from_millis ( 250 )
221+ {
222+ let hwnd = match window. raw_window_handle ( ) {
223+ RawWindowHandle :: Win32 ( handle) => handle. hwnd as HWND ,
224+ _ => unreachable ! ( ) ,
225+ } ;
226+ unsafe { apply_overlay_topmost ( hwnd) } ;
227+ * last_topmost_refresh = Instant :: now ( ) ;
228+ }
214229 unsafe {
215230 context. OMSetRenderTargets ( 1 , & main_rtv. as_raw ( ) , ptr:: null_mut ( ) ) ;
216231 context. ClearRenderTargetView ( main_rtv. as_raw ( ) , & clear_color) ;
@@ -362,6 +377,22 @@ unsafe fn create_render_target(
362377 ComPtr :: from_raw ( main_rtv)
363378}
364379
380+ unsafe fn apply_overlay_topmost ( hwnd : HWND ) {
381+ let style = winuser:: GetWindowLongA ( hwnd, winuser:: GWL_EXSTYLE ) ;
382+ let mut ex_style = style as u32 ;
383+ ex_style |= winuser:: WS_EX_TOPMOST | winuser:: WS_EX_LAYERED | winuser:: WS_EX_TOOLWINDOW ;
384+ SetWindowLongA ( hwnd, winuser:: GWL_EXSTYLE , ex_style as i32 ) ;
385+ SetWindowPos (
386+ hwnd,
387+ HWND_TOPMOST ,
388+ 0 ,
389+ 0 ,
390+ 0 ,
391+ 0 ,
392+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_FRAMECHANGED ,
393+ ) ;
394+ }
395+
365396thread_local ! {
366397 static SYSTEM : RefCell <WeakD3D11Renderer > = RefCell :: new( WeakD3D11Renderer :: new( ) ) ;
367398}
0 commit comments