Skip to content

Commit a084fc1

Browse files
authored
Win32: Various internal implementation improvements (#291)
1 parent 56fbcfc commit a084fc1

6 files changed

Lines changed: 79 additions & 74 deletions

File tree

src/platform/win/drop_target.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ use windows::Win32::System::Com::{IDataObject, DVASPECT_CONTENT, FORMATETC, TYME
1010
use windows::Win32::System::Ole::*;
1111
use windows::Win32::System::SystemServices::MODIFIERKEYS_FLAGS;
1212
use windows_core::Ref;
13-
use windows_sys::Win32::{
14-
Foundation::POINT, Graphics::Gdi::ScreenToClient, UI::Shell::DragQueryFileW,
15-
};
13+
use windows_sys::Win32::UI::Shell::DragQueryFileW;
1614

1715
use super::window_state::WindowState;
16+
use crate::wrappers::win32::window::HWnd;
1817
use crate::{DropData, DropEffect, Event, EventStatus, MouseEvent};
1918

2019
#[implement(IDropTarget)]
2120
pub(crate) struct DropTarget {
21+
hwnd: HWnd,
2222
window_state: Weak<WindowState>,
2323

2424
// These are cached since DragOver and DragLeave callbacks don't provide them,
@@ -28,8 +28,9 @@ pub(crate) struct DropTarget {
2828
}
2929

3030
impl DropTarget {
31-
pub(crate) fn new(window_state: Weak<WindowState>) -> Self {
31+
pub(crate) fn new(window_state: Weak<WindowState>, hwnd: HWnd) -> Self {
3232
Self {
33+
hwnd,
3334
window_state,
3435
drag_position: Cell::new(PhysicalPosition::new(0, 0)),
3536
drop_data: RefCell::new(DropData::None),
@@ -42,29 +43,27 @@ impl DropTarget {
4243
return;
4344
};
4445

45-
unsafe {
46-
let event = Event::Mouse(event);
47-
let event_status = window_state.handle_event(event);
48-
49-
if let Some(pdwEffect) = pdwEffect {
50-
match event_status {
51-
EventStatus::AcceptDrop(DropEffect::Copy) => *pdwEffect = DROPEFFECT_COPY,
52-
EventStatus::AcceptDrop(DropEffect::Move) => *pdwEffect = DROPEFFECT_MOVE,
53-
EventStatus::AcceptDrop(DropEffect::Link) => *pdwEffect = DROPEFFECT_LINK,
54-
EventStatus::AcceptDrop(DropEffect::Scroll) => *pdwEffect = DROPEFFECT_SCROLL,
55-
_ => *pdwEffect = DROPEFFECT_NONE,
56-
}
57-
}
46+
let event = Event::Mouse(event);
47+
let event_status = window_state.handle_event(event);
48+
49+
let effect = match event_status {
50+
EventStatus::AcceptDrop(DropEffect::Copy) => DROPEFFECT_COPY,
51+
EventStatus::AcceptDrop(DropEffect::Move) => DROPEFFECT_MOVE,
52+
EventStatus::AcceptDrop(DropEffect::Link) => DROPEFFECT_LINK,
53+
EventStatus::AcceptDrop(DropEffect::Scroll) => DROPEFFECT_SCROLL,
54+
_ => DROPEFFECT_NONE,
55+
};
56+
57+
if let Some(pdwEffect) = pdwEffect {
58+
unsafe { pdwEffect.write(effect) };
5859
}
5960
}
6061

6162
fn parse_coordinates(&self, pt: POINTL) {
62-
let Some(window_state) = self.window_state.upgrade() else {
63+
let Ok(phy_point) = self.hwnd.screen_to_client(PhysicalPosition::new(pt.x, pt.y)) else {
6364
return;
6465
};
65-
let mut pt = POINT { x: pt.x, y: pt.y };
66-
unsafe { ScreenToClient(window_state.hwnd, &mut pt as *mut POINT) };
67-
let phy_point = PhysicalPosition::new(pt.x, pt.y);
66+
6867
self.drag_position.set(phy_point);
6968
}
7069

src/platform/win/window.rs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@ const WIN_FRAME_TIMER: NonZeroUsize = match NonZeroUsize::new(4242) {
5252
};
5353

5454
pub struct WindowHandle {
55-
hwnd: Cell<Option<HWND>>,
55+
hwnd: Cell<Option<HWnd>>,
5656
is_open: Rc<Cell<bool>>,
5757
}
5858

5959
impl WindowHandle {
6060
pub fn close(&self) {
6161
if let Some(hwnd) = self.hwnd.take() {
6262
unsafe {
63-
PostMessageW(hwnd, BV_WINDOW_MUST_CLOSE, 0, 0);
63+
PostMessageW(hwnd.as_raw(), BV_WINDOW_MUST_CLOSE, 0, 0);
6464
}
6565
}
6666
}
@@ -127,7 +127,7 @@ impl WindowImpl for BaseviewWindow {
127127
}
128128
}
129129

130-
let drop_target = ComObject::new(DropTarget::new(Rc::downgrade(window_state)));
130+
let drop_target = ComObject::new(DropTarget::new(Rc::downgrade(window_state), window));
131131
self._drop_target.set(Some(drop_target.clone()));
132132

133133
ole_initialize()?;
@@ -457,12 +457,8 @@ impl Window {
457457
let extended_user_32 = extended_user_32.clone();
458458

459459
move |hwnd: HWnd| {
460-
let window_state = Rc::new(WindowState::new(
461-
hwnd.as_raw(),
462-
window_size,
463-
options.scale,
464-
extended_user_32,
465-
));
460+
let window_state =
461+
Rc::new(WindowState::new(hwnd, window_size, options.scale, extended_user_32));
466462

467463
BaseviewWindow {
468464
window_state,
@@ -479,13 +475,10 @@ impl Window {
479475
}
480476
};
481477

482-
let hwnd =
478+
let window =
483479
create_window(&title, style, rect.size(), parent as *mut _, &dpi_ctx, initializer)
484480
.unwrap();
485481

486-
// SAFETY: this handle should be safe to use
487-
let window = unsafe { HWnd::from_raw(hwnd) };
488-
489482
// FIXME: this SetTimer call could be in after_create, but for some reason it changes the ordering
490483
// for a parent+child window situation, which results in the parent drawing over the child.
491484
// This timer should be replaced by proper window redrawing/damage/vsync handling, but this
@@ -495,7 +488,7 @@ impl Window {
495488

496489
window.show_and_activate();
497490

498-
WindowHandle { hwnd: Some(hwnd).into(), is_open: Rc::clone(&is_open) }
491+
WindowHandle { hwnd: Some(window).into(), is_open: Rc::clone(&is_open) }
499492
}
500493
}
501494

src/platform/win/window_state.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@ use dpi::{PhysicalSize, Size};
99
use raw_window_handle::{DisplayHandle, Win32WindowHandle};
1010
use std::cell::{Cell, OnceCell, Ref, RefCell};
1111
use std::num::NonZeroIsize;
12-
use windows_sys::Win32::Foundation::HWND;
1312
use windows_sys::Win32::UI::WindowsAndMessaging::PostMessageW;
1413

1514
/// All data associated with the window.
1615
pub(crate) struct WindowState {
1716
/// The HWND belonging to this window.
18-
pub hwnd: HWND,
17+
pub hwnd: HWnd,
1918
pub current_size: Cell<PhysicalSize<u32>>,
2019
pub current_dpi: Cell<Dpi>, // None if in non-system scale policy
2120
pub keyboard_state: RefCell<KeyboardState>,
@@ -34,7 +33,7 @@ pub(crate) struct WindowState {
3433

3534
impl WindowState {
3635
pub fn new(
37-
hwnd: HWND, current_size: PhysicalSize<u32>, scale_policy: WindowScalePolicy,
36+
hwnd: HWnd, current_size: PhysicalSize<u32>, scale_policy: WindowScalePolicy,
3837
user32: ExtendedUser32,
3938
) -> Self {
4039
Self {
@@ -92,21 +91,21 @@ impl WindowState {
9291

9392
pub fn request_close(&self) {
9493
unsafe {
95-
PostMessageW(self.hwnd, crate::platform::win::window::BV_WINDOW_MUST_CLOSE, 0, 0);
94+
PostMessageW(
95+
self.hwnd.as_raw(),
96+
crate::platform::win::window::BV_WINDOW_MUST_CLOSE,
97+
0,
98+
0,
99+
);
96100
}
97101
}
98102

99103
pub fn has_focus(&self) -> bool {
100-
HWnd::get_focused_window() == self.hwnd
104+
HWnd::get_focused_window() == self.hwnd.as_raw()
101105
}
102106

103107
pub fn focus(&self) {
104-
self.hwnd().set_focus().unwrap()
105-
}
106-
107-
fn hwnd(&self) -> HWnd {
108-
// SAFETY: this handle should be safe to use
109-
unsafe { HWnd::from_raw(self.hwnd) }
108+
self.hwnd.set_focus().unwrap()
110109
}
111110

112111
pub fn resize(&self, size: Size) {
@@ -115,7 +114,7 @@ impl WindowState {
115114
let dpi = self.current_dpi.get();
116115
let new_size = size.to_physical(dpi.scale_factor());
117116

118-
self.hwnd().resize_and_activate(new_size, dpi, &self.user32).unwrap();
117+
self.hwnd.resize_and_activate(new_size, dpi, &self.user32).unwrap();
119118
}
120119

121120
pub fn set_mouse_cursor(&self, mouse_cursor: MouseCursor) {
@@ -132,7 +131,7 @@ impl WindowState {
132131
}
133132

134133
pub fn window_handle(&self) -> Option<raw_window_handle::WindowHandle<'_>> {
135-
let Some(hwnd) = NonZeroIsize::new(self.hwnd as _) else { unreachable!() };
134+
let Some(hwnd) = NonZeroIsize::new(self.hwnd.as_raw() as _) else { unreachable!() };
136135
let mut handle = Win32WindowHandle::new(hwnd);
137136
handle.hinstance = Some(HInstance::get_from_dll().addr());
138137

@@ -144,7 +143,7 @@ impl WindowState {
144143
}
145144

146145
pub fn platform_handle(&self) -> PlatformHandle {
147-
let Some(hwnd) = NonZeroIsize::new(self.hwnd as _) else { unreachable!() };
146+
let Some(hwnd) = NonZeroIsize::new(self.hwnd.as_raw() as _) else { unreachable!() };
148147
PlatformHandle { hwnd }
149148
}
150149
}

src/wrappers/win32/window.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use data::WindowData;
77
use dpi::PhysicalSize;
88
pub use handle::HWnd;
99
pub use proc::wnd_proc;
10-
use std::ptr::null_mut;
10+
use std::ptr::{null_mut, NonNull};
1111
use std::rc::Rc;
1212
use window_class::RegisteredClass;
1313
use windows_core::{Error, Result, HSTRING};
@@ -53,7 +53,7 @@ pub trait WindowImpl: 'static {
5353
pub fn create_window<W: WindowImpl>(
5454
title: &HSTRING, style: WindowStyle, nc_size: PhysicalSize<u32>, parent: HWND,
5555
_dpi_ctx: &DpiAwarenessContext, initializer: impl FnOnce(HWnd) -> W + 'static,
56-
) -> Result<HWND> {
56+
) -> Result<HWnd> {
5757
let instance = HInstance::get_from_dll();
5858
let window_class = RegisteredClass::register_new(instance, Some(wnd_proc::<W>))?;
5959

@@ -76,9 +76,9 @@ pub fn create_window<W: WindowImpl>(
7676
)
7777
};
7878

79-
if hwnd.is_null() {
80-
return Err(Error::from_thread());
81-
}
79+
let Some(hwnd) = NonNull::new(hwnd) else { return Err(Error::from_thread()) };
80+
// SAFETY: This Hwnd is valid since it came from CreateWindowExW
81+
let hwnd = unsafe { HWnd::from_raw(hwnd) };
8282

8383
Ok(hwnd)
8484
}

0 commit comments

Comments
 (0)