mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-26 03:36:32 +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
5 changed files with 80 additions and 11 deletions
|
@ -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 `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.
|
- Added `Window::drag_window`. Implemented on Windows, macOS, X11 and Wayland.
|
||||||
- On X11, bump `mio` to 0.7.
|
- 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.
|
- On macOS, emit `RedrawRequested` events immediately while the window is being resized.
|
||||||
|
|
||||||
# 0.24.0 (2020-12-09)
|
# 0.24.0 (2020-12-09)
|
||||||
|
|
|
@ -12,7 +12,7 @@ use crate::{
|
||||||
event::DeviceId,
|
event::DeviceId,
|
||||||
event_loop::EventLoop,
|
event_loop::EventLoop,
|
||||||
monitor::MonitorHandle,
|
monitor::MonitorHandle,
|
||||||
platform_impl::{EventLoop as WindowsEventLoop, WinIcon},
|
platform_impl::{EventLoop as WindowsEventLoop, Parent, WinIcon},
|
||||||
window::{BadIcon, Icon, Theme, Window, WindowBuilder},
|
window::{BadIcon, Icon, Theme, Window, WindowBuilder},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,6 +78,21 @@ pub trait WindowExtWindows {
|
||||||
/// The pointer will become invalid when the native window was destroyed.
|
/// The pointer will become invalid when the native window was destroyed.
|
||||||
fn hwnd(&self) -> *mut libc::c_void;
|
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.
|
/// This sets `ICON_BIG`. A good ceiling here is 256x256.
|
||||||
fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>);
|
fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>);
|
||||||
|
|
||||||
|
@ -96,6 +111,13 @@ impl WindowExtWindows for Window {
|
||||||
self.window.hwnd() as *mut _
|
self.window.hwnd() as *mut _
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn set_enable(&self, enabled: bool) {
|
||||||
|
unsafe {
|
||||||
|
winapi::um::winuser::EnableWindow(self.hwnd() as _, enabled as _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>) {
|
fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>) {
|
||||||
self.window.set_taskbar_icon(taskbar_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.
|
/// Additional methods on `WindowBuilder` that are specific to Windows.
|
||||||
pub trait WindowBuilderExtWindows {
|
pub trait WindowBuilderExtWindows {
|
||||||
/// Sets a parent to the window to be created.
|
/// 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;
|
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.
|
/// Sets a menu on the window to be created.
|
||||||
///
|
///
|
||||||
/// Parent and menu are mutually exclusive; a child window cannot have a menu!
|
/// Parent and menu are mutually exclusive; a child window cannot have a menu!
|
||||||
|
@ -143,7 +181,13 @@ pub trait WindowBuilderExtWindows {
|
||||||
impl WindowBuilderExtWindows for WindowBuilder {
|
impl WindowBuilderExtWindows for WindowBuilder {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_parent_window(mut self, parent: HWND) -> WindowBuilder {
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,16 @@ use crate::event::DeviceId as RootDeviceId;
|
||||||
use crate::icon::Icon;
|
use crate::icon::Icon;
|
||||||
use crate::window::Theme;
|
use crate::window::Theme;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum Parent {
|
||||||
|
None,
|
||||||
|
ChildOf(HWND),
|
||||||
|
OwnedBy(HWND),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PlatformSpecificWindowBuilderAttributes {
|
pub struct PlatformSpecificWindowBuilderAttributes {
|
||||||
pub parent: Option<HWND>,
|
pub parent: Parent,
|
||||||
pub menu: Option<HMENU>,
|
pub menu: Option<HMENU>,
|
||||||
pub taskbar_icon: Option<Icon>,
|
pub taskbar_icon: Option<Icon>,
|
||||||
pub no_redirection_bitmap: bool,
|
pub no_redirection_bitmap: bool,
|
||||||
|
@ -28,7 +35,7 @@ pub struct PlatformSpecificWindowBuilderAttributes {
|
||||||
impl Default for PlatformSpecificWindowBuilderAttributes {
|
impl Default for PlatformSpecificWindowBuilderAttributes {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
parent: None,
|
parent: Parent::None,
|
||||||
menu: None,
|
menu: None,
|
||||||
taskbar_icon: None,
|
taskbar_icon: None,
|
||||||
no_redirection_bitmap: false,
|
no_redirection_bitmap: false,
|
||||||
|
|
|
@ -44,7 +44,7 @@ use crate::{
|
||||||
icon::{self, IconType},
|
icon::{self, IconType},
|
||||||
monitor, util,
|
monitor, util,
|
||||||
window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState},
|
window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState},
|
||||||
PlatformSpecificWindowBuilderAttributes, WindowId,
|
Parent, PlatformSpecificWindowBuilderAttributes, WindowId,
|
||||||
},
|
},
|
||||||
window::{CursorIcon, Fullscreen, Theme, UserAttentionType, WindowAttributes},
|
window::{CursorIcon, Fullscreen, Theme, UserAttentionType, WindowAttributes},
|
||||||
};
|
};
|
||||||
|
@ -733,12 +733,24 @@ unsafe fn init<T: 'static>(
|
||||||
window_flags.set(WindowFlags::TRANSPARENT, attributes.transparent);
|
window_flags.set(WindowFlags::TRANSPARENT, attributes.transparent);
|
||||||
// WindowFlags::VISIBLE and MAXIMIZED are set down below after the window has been configured.
|
// 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::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() {
|
let parent = match pl_attribs.parent {
|
||||||
warn!("Setting a menu on windows that have a parent is unsupported");
|
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`
|
// creating the real window this time, by using the functions in `extra_functions`
|
||||||
let real_window = {
|
let real_window = {
|
||||||
|
@ -752,7 +764,7 @@ unsafe fn init<T: 'static>(
|
||||||
winuser::CW_USEDEFAULT,
|
winuser::CW_USEDEFAULT,
|
||||||
winuser::CW_USEDEFAULT,
|
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()),
|
pl_attribs.menu.unwrap_or(ptr::null_mut()),
|
||||||
libloaderapi::GetModuleHandleW(ptr::null()),
|
libloaderapi::GetModuleHandleW(ptr::null()),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
|
|
|
@ -68,6 +68,7 @@ bitflags! {
|
||||||
const TRANSPARENT = 1 << 6;
|
const TRANSPARENT = 1 << 6;
|
||||||
const CHILD = 1 << 7;
|
const CHILD = 1 << 7;
|
||||||
const MAXIMIZED = 1 << 8;
|
const MAXIMIZED = 1 << 8;
|
||||||
|
const POPUP = 1 << 14;
|
||||||
|
|
||||||
/// Marker flag for fullscreen. Should always match `WindowState::fullscreen`, but is
|
/// Marker flag for fullscreen. Should always match `WindowState::fullscreen`, but is
|
||||||
/// included here to make masking easier.
|
/// included here to make masking easier.
|
||||||
|
@ -213,6 +214,9 @@ impl WindowFlags {
|
||||||
if self.contains(WindowFlags::CHILD) {
|
if self.contains(WindowFlags::CHILD) {
|
||||||
style |= WS_CHILD; // This is incompatible with WS_POPUP if that gets added eventually.
|
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) {
|
if self.contains(WindowFlags::MINIMIZED) {
|
||||||
style |= WS_MINIMIZE;
|
style |= WS_MINIMIZE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue