mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-11 13:31:29 +11:00
On Windows, allow the creation of popup window (#1895)
Add with_owner_window to WindowBuilderExtWindows. Add set_enable to WindowExtWindows.
This commit is contained in:
parent
629cd86c7c
commit
dabcb1834d
|
@ -20,6 +20,8 @@
|
|||
- Added `WindowBuilder::with_position` to allow setting the position of a `Window` on creation. Supported on Windows, macOS and X11.
|
||||
- Added `Window::drag_window`. Implemented on Windows, macOS, X11 and Wayland.
|
||||
- On X11, bump `mio` to 0.7.
|
||||
- On Windows, added `WindowBuilderExtWindows::with_owner_window` to allow creating popup windows.
|
||||
- On Windows, added `WindowExtWindows::set_enable` to allow creating modal popup windows.
|
||||
- On macOS, emit `RedrawRequested` events immediately while the window is being resized.
|
||||
|
||||
# 0.24.0 (2020-12-09)
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::{
|
|||
event::DeviceId,
|
||||
event_loop::EventLoop,
|
||||
monitor::MonitorHandle,
|
||||
platform_impl::{EventLoop as WindowsEventLoop, WinIcon},
|
||||
platform_impl::{EventLoop as WindowsEventLoop, Parent, WinIcon},
|
||||
window::{BadIcon, Icon, Theme, Window, WindowBuilder},
|
||||
};
|
||||
|
||||
|
@ -78,6 +78,21 @@ pub trait WindowExtWindows {
|
|||
/// The pointer will become invalid when the native window was destroyed.
|
||||
fn hwnd(&self) -> *mut libc::c_void;
|
||||
|
||||
/// Enables or disables mouse and keyboard input to the specified window.
|
||||
///
|
||||
/// A window must be enabled before it can be activated.
|
||||
/// If an application has create a modal dialog box by disabling its owner window
|
||||
/// (as described in [`WindowBuilderExtWindows::with_owner_window`]), the application must enable
|
||||
/// the owner window before destroying the dialog box.
|
||||
/// Otherwise, another window will receive the keyboard focus and be activated.
|
||||
///
|
||||
/// If a child window is disabled, it is ignored when the system tries to determine which
|
||||
/// window should receive mouse messages.
|
||||
///
|
||||
/// For more information, see <https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enablewindow#remarks>
|
||||
/// and <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#disabled-windows>
|
||||
fn set_enable(&self, enabled: bool);
|
||||
|
||||
/// This sets `ICON_BIG`. A good ceiling here is 256x256.
|
||||
fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>);
|
||||
|
||||
|
@ -96,6 +111,13 @@ impl WindowExtWindows for Window {
|
|||
self.window.hwnd() as *mut _
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_enable(&self, enabled: bool) {
|
||||
unsafe {
|
||||
winapi::um::winuser::EnableWindow(self.hwnd() as _, enabled as _);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>) {
|
||||
self.window.set_taskbar_icon(taskbar_icon)
|
||||
|
@ -110,8 +132,24 @@ impl WindowExtWindows for Window {
|
|||
/// Additional methods on `WindowBuilder` that are specific to Windows.
|
||||
pub trait WindowBuilderExtWindows {
|
||||
/// Sets a parent to the window to be created.
|
||||
///
|
||||
/// A child window has the WS_CHILD style and is confined to the client area of its parent window.
|
||||
///
|
||||
/// For more information, see <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#child-windows>
|
||||
fn with_parent_window(self, parent: HWND) -> WindowBuilder;
|
||||
|
||||
/// Set an owner to the window to be created. Can be used to create a dialog box, for example.
|
||||
/// Can be used in combination with [`WindowExtWindows::set_enable(false)`](WindowExtWindows::set_enable)
|
||||
/// on the owner window to create a modal dialog box.
|
||||
///
|
||||
/// From MSDN:
|
||||
/// - An owned window is always above its owner in the z-order.
|
||||
/// - The system automatically destroys an owned window when its owner is destroyed.
|
||||
/// - An owned window is hidden when its owner is minimized.
|
||||
///
|
||||
/// For more information, see <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#owned-windows>
|
||||
fn with_owner_window(self, parent: HWND) -> WindowBuilder;
|
||||
|
||||
/// Sets a menu on the window to be created.
|
||||
///
|
||||
/// Parent and menu are mutually exclusive; a child window cannot have a menu!
|
||||
|
@ -143,7 +181,13 @@ pub trait WindowBuilderExtWindows {
|
|||
impl WindowBuilderExtWindows for WindowBuilder {
|
||||
#[inline]
|
||||
fn with_parent_window(mut self, parent: HWND) -> WindowBuilder {
|
||||
self.platform_specific.parent = Some(parent);
|
||||
self.platform_specific.parent = Parent::ChildOf(parent);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn with_owner_window(mut self, parent: HWND) -> WindowBuilder {
|
||||
self.platform_specific.parent = Parent::OwnedBy(parent);
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -15,9 +15,16 @@ use crate::event::DeviceId as RootDeviceId;
|
|||
use crate::icon::Icon;
|
||||
use crate::window::Theme;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Parent {
|
||||
None,
|
||||
ChildOf(HWND),
|
||||
OwnedBy(HWND),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PlatformSpecificWindowBuilderAttributes {
|
||||
pub parent: Option<HWND>,
|
||||
pub parent: Parent,
|
||||
pub menu: Option<HMENU>,
|
||||
pub taskbar_icon: Option<Icon>,
|
||||
pub no_redirection_bitmap: bool,
|
||||
|
@ -28,7 +35,7 @@ pub struct PlatformSpecificWindowBuilderAttributes {
|
|||
impl Default for PlatformSpecificWindowBuilderAttributes {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
parent: None,
|
||||
parent: Parent::None,
|
||||
menu: None,
|
||||
taskbar_icon: None,
|
||||
no_redirection_bitmap: false,
|
||||
|
|
|
@ -44,7 +44,7 @@ use crate::{
|
|||
icon::{self, IconType},
|
||||
monitor, util,
|
||||
window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState},
|
||||
PlatformSpecificWindowBuilderAttributes, WindowId,
|
||||
Parent, PlatformSpecificWindowBuilderAttributes, WindowId,
|
||||
},
|
||||
window::{CursorIcon, Fullscreen, Theme, UserAttentionType, WindowAttributes},
|
||||
};
|
||||
|
@ -733,12 +733,24 @@ unsafe fn init<T: 'static>(
|
|||
window_flags.set(WindowFlags::TRANSPARENT, attributes.transparent);
|
||||
// WindowFlags::VISIBLE and MAXIMIZED are set down below after the window has been configured.
|
||||
window_flags.set(WindowFlags::RESIZABLE, attributes.resizable);
|
||||
window_flags.set(WindowFlags::CHILD, pl_attribs.parent.is_some());
|
||||
window_flags.set(WindowFlags::ON_TASKBAR, true);
|
||||
|
||||
if pl_attribs.parent.is_some() && pl_attribs.menu.is_some() {
|
||||
warn!("Setting a menu on windows that have a parent is unsupported");
|
||||
let parent = match pl_attribs.parent {
|
||||
Parent::ChildOf(parent) => {
|
||||
window_flags.set(WindowFlags::CHILD, true);
|
||||
if pl_attribs.menu.is_some() {
|
||||
warn!("Setting a menu on a child window is unsupported");
|
||||
}
|
||||
Some(parent)
|
||||
}
|
||||
Parent::OwnedBy(parent) => {
|
||||
window_flags.set(WindowFlags::POPUP, true);
|
||||
Some(parent)
|
||||
}
|
||||
Parent::None => {
|
||||
window_flags.set(WindowFlags::ON_TASKBAR, true);
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
// creating the real window this time, by using the functions in `extra_functions`
|
||||
let real_window = {
|
||||
|
@ -752,7 +764,7 @@ unsafe fn init<T: 'static>(
|
|||
winuser::CW_USEDEFAULT,
|
||||
winuser::CW_USEDEFAULT,
|
||||
winuser::CW_USEDEFAULT,
|
||||
pl_attribs.parent.unwrap_or(ptr::null_mut()),
|
||||
parent.unwrap_or(ptr::null_mut()),
|
||||
pl_attribs.menu.unwrap_or(ptr::null_mut()),
|
||||
libloaderapi::GetModuleHandleW(ptr::null()),
|
||||
ptr::null_mut(),
|
||||
|
|
|
@ -68,6 +68,7 @@ bitflags! {
|
|||
const TRANSPARENT = 1 << 6;
|
||||
const CHILD = 1 << 7;
|
||||
const MAXIMIZED = 1 << 8;
|
||||
const POPUP = 1 << 14;
|
||||
|
||||
/// Marker flag for fullscreen. Should always match `WindowState::fullscreen`, but is
|
||||
/// included here to make masking easier.
|
||||
|
@ -213,6 +214,9 @@ impl WindowFlags {
|
|||
if self.contains(WindowFlags::CHILD) {
|
||||
style |= WS_CHILD; // This is incompatible with WS_POPUP if that gets added eventually.
|
||||
}
|
||||
if self.contains(WindowFlags::POPUP) {
|
||||
style |= WS_POPUP;
|
||||
}
|
||||
if self.contains(WindowFlags::MINIMIZED) {
|
||||
style |= WS_MINIMIZE;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue