Add Window::set_window_level API
This adds `Window::set_window_level` to control the preferred z level of the window. Co-authored-by: Markus Siglreithmaier <m.siglreith@gmail.com> Co-authored-by: Kirill Chibisov <contact@kchibisov.com> Co-authored-by: Mads Marquart <mads@marquart.dk>
This commit is contained in:
parent
ba4bf03675
commit
101ac8908c
12 changed files with 142 additions and 82 deletions
|
|
@ -71,7 +71,7 @@ use crate::{
|
|||
window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState},
|
||||
Fullscreen, Parent, PlatformSpecificWindowBuilderAttributes, WindowId,
|
||||
},
|
||||
window::{CursorGrabMode, CursorIcon, Theme, UserAttentionType, WindowAttributes},
|
||||
window::{CursorGrabMode, CursorIcon, Theme, UserAttentionType, WindowAttributes, WindowLevel},
|
||||
};
|
||||
|
||||
/// The Win32 implementation of the main `Window` object.
|
||||
|
|
@ -605,14 +605,21 @@ impl Window {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_always_on_top(&self, always_on_top: bool) {
|
||||
pub fn set_window_level(&self, level: WindowLevel) {
|
||||
let window = self.window.clone();
|
||||
let window_state = Arc::clone(&self.window_state);
|
||||
|
||||
self.thread_executor.execute_in_thread(move || {
|
||||
let _ = &window;
|
||||
WindowState::set_window_flags(window_state.lock().unwrap(), window.0, |f| {
|
||||
f.set(WindowFlags::ALWAYS_ON_TOP, always_on_top)
|
||||
f.set(
|
||||
WindowFlags::ALWAYS_ON_TOP,
|
||||
level == WindowLevel::AlwaysOnTop,
|
||||
);
|
||||
f.set(
|
||||
WindowFlags::ALWAYS_ON_BOTTOM,
|
||||
level == WindowLevel::AlwaysOnBottom,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -985,7 +992,14 @@ where
|
|||
WindowFlags::MARKER_UNDECORATED_SHADOW,
|
||||
pl_attribs.decoration_shadow,
|
||||
);
|
||||
window_flags.set(WindowFlags::ALWAYS_ON_TOP, attributes.always_on_top);
|
||||
window_flags.set(
|
||||
WindowFlags::ALWAYS_ON_TOP,
|
||||
attributes.window_level == WindowLevel::AlwaysOnTop,
|
||||
);
|
||||
window_flags.set(
|
||||
WindowFlags::ALWAYS_ON_BOTTOM,
|
||||
attributes.window_level == WindowLevel::AlwaysOnBottom,
|
||||
);
|
||||
window_flags.set(
|
||||
WindowFlags::NO_BACK_BUFFER,
|
||||
pl_attribs.no_redirection_bitmap,
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@ use windows_sys::Win32::{
|
|||
Graphics::Gdi::InvalidateRgn,
|
||||
UI::WindowsAndMessaging::{
|
||||
AdjustWindowRectEx, GetMenu, GetWindowLongW, SendMessageW, SetWindowLongW, SetWindowPos,
|
||||
ShowWindow, GWL_EXSTYLE, GWL_STYLE, HWND_NOTOPMOST, HWND_TOPMOST, SWP_ASYNCWINDOWPOS,
|
||||
SWP_FRAMECHANGED, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOREPOSITION, SWP_NOSIZE, SWP_NOZORDER,
|
||||
SW_HIDE, SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, SW_SHOW, WINDOWPLACEMENT, WINDOW_EX_STYLE,
|
||||
WINDOW_STYLE, WS_BORDER, WS_CAPTION, WS_CHILD, WS_CLIPCHILDREN, WS_CLIPSIBLINGS,
|
||||
WS_EX_ACCEPTFILES, WS_EX_APPWINDOW, WS_EX_LAYERED, WS_EX_NOREDIRECTIONBITMAP,
|
||||
WS_EX_TOPMOST, WS_EX_TRANSPARENT, WS_EX_WINDOWEDGE, WS_MAXIMIZE, WS_MAXIMIZEBOX,
|
||||
WS_MINIMIZE, WS_MINIMIZEBOX, WS_OVERLAPPEDWINDOW, WS_POPUP, WS_SIZEBOX, WS_SYSMENU,
|
||||
WS_VISIBLE,
|
||||
ShowWindow, GWL_EXSTYLE, GWL_STYLE, HWND_BOTTOM, HWND_NOTOPMOST, HWND_TOPMOST,
|
||||
SWP_ASYNCWINDOWPOS, SWP_FRAMECHANGED, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOREPOSITION,
|
||||
SWP_NOSIZE, SWP_NOZORDER, SW_HIDE, SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, SW_SHOW,
|
||||
WINDOWPLACEMENT, WINDOW_EX_STYLE, WINDOW_STYLE, WS_BORDER, WS_CAPTION, WS_CHILD,
|
||||
WS_CLIPCHILDREN, WS_CLIPSIBLINGS, WS_EX_ACCEPTFILES, WS_EX_APPWINDOW, WS_EX_LAYERED,
|
||||
WS_EX_NOREDIRECTIONBITMAP, WS_EX_TOPMOST, WS_EX_TRANSPARENT, WS_EX_WINDOWEDGE, WS_MAXIMIZE,
|
||||
WS_MAXIMIZEBOX, WS_MINIMIZE, WS_MINIMIZEBOX, WS_OVERLAPPEDWINDOW, WS_POPUP, WS_SIZEBOX,
|
||||
WS_SYSMENU, WS_VISIBLE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -76,38 +76,39 @@ bitflags! {
|
|||
}
|
||||
bitflags! {
|
||||
pub struct WindowFlags: u32 {
|
||||
const RESIZABLE = 1 << 0;
|
||||
const VISIBLE = 1 << 1;
|
||||
const ON_TASKBAR = 1 << 2;
|
||||
const ALWAYS_ON_TOP = 1 << 3;
|
||||
const NO_BACK_BUFFER = 1 << 4;
|
||||
const TRANSPARENT = 1 << 5;
|
||||
const CHILD = 1 << 6;
|
||||
const MAXIMIZED = 1 << 7;
|
||||
const POPUP = 1 << 8;
|
||||
const RESIZABLE = 1 << 0;
|
||||
const VISIBLE = 1 << 1;
|
||||
const ON_TASKBAR = 1 << 2;
|
||||
const ALWAYS_ON_TOP = 1 << 3;
|
||||
const ALWAYS_ON_BOTTOM = 1 << 4;
|
||||
const NO_BACK_BUFFER = 1 << 5;
|
||||
const TRANSPARENT = 1 << 6;
|
||||
const CHILD = 1 << 7;
|
||||
const MAXIMIZED = 1 << 8;
|
||||
const POPUP = 1 << 9;
|
||||
|
||||
/// Marker flag for fullscreen. Should always match `WindowState::fullscreen`, but is
|
||||
/// included here to make masking easier.
|
||||
const MARKER_EXCLUSIVE_FULLSCREEN = 1 << 9;
|
||||
const MARKER_BORDERLESS_FULLSCREEN = 1 << 10;
|
||||
const MARKER_EXCLUSIVE_FULLSCREEN = 1 << 10;
|
||||
const MARKER_BORDERLESS_FULLSCREEN = 1 << 11;
|
||||
|
||||
/// The `WM_SIZE` event contains some parameters that can effect the state of `WindowFlags`.
|
||||
/// In most cases, it's okay to let those parameters change the state. However, when we're
|
||||
/// running the `WindowFlags::apply_diff` function, we *don't* want those parameters to
|
||||
/// effect our stored state, because the purpose of `apply_diff` is to update the actual
|
||||
/// window's state to match our stored state. This controls whether to accept those changes.
|
||||
const MARKER_RETAIN_STATE_ON_SIZE = 1 << 11;
|
||||
const MARKER_RETAIN_STATE_ON_SIZE = 1 << 12;
|
||||
|
||||
const MARKER_IN_SIZE_MOVE = 1 << 12;
|
||||
const MARKER_IN_SIZE_MOVE = 1 << 13;
|
||||
|
||||
const MINIMIZED = 1 << 13;
|
||||
const MINIMIZED = 1 << 14;
|
||||
|
||||
const IGNORE_CURSOR_EVENT = 1 << 14;
|
||||
const IGNORE_CURSOR_EVENT = 1 << 15;
|
||||
|
||||
/// Fully decorated window (incl. caption, border and drop shadow).
|
||||
const MARKER_DECORATIONS = 1 << 15;
|
||||
const MARKER_DECORATIONS = 1 << 16;
|
||||
/// Drop shadow for undecorated windows.
|
||||
const MARKER_UNDECORATED_SHADOW = 1 << 16;
|
||||
const MARKER_UNDECORATED_SHADOW = 1 << 17;
|
||||
|
||||
const EXCLUSIVE_FULLSCREEN_OR_MASK = WindowFlags::ALWAYS_ON_TOP.bits;
|
||||
}
|
||||
|
|
@ -301,13 +302,18 @@ impl WindowFlags {
|
|||
}
|
||||
}
|
||||
|
||||
if diff.contains(WindowFlags::ALWAYS_ON_TOP) {
|
||||
if diff.intersects(WindowFlags::ALWAYS_ON_TOP | WindowFlags::ALWAYS_ON_BOTTOM) {
|
||||
unsafe {
|
||||
SetWindowPos(
|
||||
window,
|
||||
match new.contains(WindowFlags::ALWAYS_ON_TOP) {
|
||||
true => HWND_TOPMOST,
|
||||
false => HWND_NOTOPMOST,
|
||||
match (
|
||||
new.contains(WindowFlags::ALWAYS_ON_TOP),
|
||||
new.contains(WindowFlags::ALWAYS_ON_BOTTOM),
|
||||
) {
|
||||
(true, false) => HWND_TOPMOST,
|
||||
(false, false) => HWND_NOTOPMOST,
|
||||
(false, true) => HWND_BOTTOM,
|
||||
(true, true) => unreachable!(),
|
||||
},
|
||||
0,
|
||||
0,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue