Skip to content

Commit

Permalink
win32: switch from winapi to windows-sys
Browse files Browse the repository at this point in the history
  • Loading branch information
micahrj committed Sep 14, 2023
1 parent 63e9b0d commit 47dfd5d
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 194 deletions.
11 changes: 10 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,18 @@ publish = false
[dependencies]

[target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3.8", features = ["std", "winuser", "windef", "minwindef", "errhandlingapi", "winnt", "ntdef", "wingdi", "windowsx"] }
getrandom = "0.2.10"

[target.'cfg(target_os = "windows")'.dependencies.windows-sys]
version = "0.48.0"
features = [
"Win32_Foundation",
"Win32_UI_WindowsAndMessaging",
"Win32_UI_Input_KeyboardAndMouse",
"Win32_Graphics_Gdi",
"Win32_System_SystemServices",
]

[target.'cfg(target_os = "macos")'.dependencies]
objc2 = { version = "0.4.1", features = ["catch-all"] }
objc-sys = "0.3.1"
Expand Down
46 changes: 25 additions & 21 deletions src/backend/win32/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,28 @@ use std::rc::Rc;
use std::time::Duration;
use std::{mem, ptr, result};

use winapi::{shared::minwindef, shared::ntdef, um::errhandlingapi, um::winuser};
use windows_sys::core::PCWSTR;
use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::UI::WindowsAndMessaging::{
self as msg, DispatchMessageW, GetMessageW, LoadCursorW, PeekMessageW, PostQuitMessage,
RegisterClassW, TranslateMessage, UnregisterClassW, MSG, WNDCLASSW,
};

use super::timer::{TimerHandleInner, Timers};
use super::window::wnd_proc;
use super::{class_name, hinstance, to_wstring, OsError};
use crate::{App, AppContext, AppOptions, Error, IntoInnerError, Result};

pub struct AppState {
pub class: minwindef::ATOM,
pub class: u16,
pub timers: Timers,
pub data: RefCell<Option<Box<dyn Any>>>,
}

impl Drop for AppState {
fn drop(&mut self) {
unsafe {
winuser::UnregisterClassW(self.class as *const ntdef::WCHAR, hinstance());
UnregisterClassW(self.class as PCWSTR, hinstance());
}
}
}
Expand All @@ -40,23 +45,23 @@ impl<T: 'static> AppInner<T> {
let class_name = to_wstring(&class_name("window-"));

let class = unsafe {
let wnd_class = winuser::WNDCLASSW {
style: winuser::CS_HREDRAW | winuser::CS_VREDRAW | winuser::CS_OWNDC,
let wnd_class = WNDCLASSW {
style: msg::CS_HREDRAW | msg::CS_VREDRAW | msg::CS_OWNDC,
lpfnWndProc: Some(wnd_proc),
cbClsExtra: 0,
cbWndExtra: 0,
hInstance: hinstance(),
hIcon: ptr::null_mut(),
hCursor: winuser::LoadCursorW(ptr::null_mut(), winuser::IDC_ARROW),
hbrBackground: ptr::null_mut(),
hIcon: 0,
hCursor: LoadCursorW(0, msg::IDC_ARROW),
hbrBackground: 0,
lpszMenuName: ptr::null(),
lpszClassName: class_name.as_ptr(),
};

let class = winuser::RegisterClassW(&wnd_class);
let class = RegisterClassW(&wnd_class);
if class == 0 {
return Err(Error::Os(OsError {
code: errhandlingapi::GetLastError(),
code: GetLastError(),
}));
}

Expand Down Expand Up @@ -94,19 +99,19 @@ impl<T: 'static> AppInner<T> {

loop {
unsafe {
let mut msg: winuser::MSG = mem::zeroed();
let mut msg: MSG = mem::zeroed();

let result = winuser::GetMessageW(&mut msg, ptr::null_mut(), 0, 0);
let result = GetMessageW(&mut msg, 0, 0, 0);
if result < 0 {
return Err(Error::Os(OsError {
code: errhandlingapi::GetLastError(),
code: GetLastError(),
}));
} else if result == 0 {
return Ok(());
}

winuser::TranslateMessage(&msg);
winuser::DispatchMessageW(&msg);
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
}
Expand All @@ -118,16 +123,15 @@ impl<T: 'static> AppInner<T> {

loop {
unsafe {
let mut msg: winuser::MSG = mem::zeroed();
let mut msg: MSG = mem::zeroed();

let result =
winuser::PeekMessageW(&mut msg, ptr::null_mut(), 0, 0, winuser::PM_REMOVE);
let result = PeekMessageW(&mut msg, 0, 0, 0, msg::PM_REMOVE);
if result == 0 {
return Ok(());
}

winuser::TranslateMessage(&msg);
winuser::DispatchMessageW(&msg);
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
}
Expand Down Expand Up @@ -177,7 +181,7 @@ impl<'a, T: 'static> AppContextInner<'a, T> {

pub fn exit(&self) {
unsafe {
winuser::PostQuitMessage(0);
PostQuitMessage(0);
}
}
}
15 changes: 8 additions & 7 deletions src/backend/win32/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use std::ffi::OsStr;
use std::fmt;
use std::os::windows::ffi::OsStrExt;

use winapi::{shared::minwindef, shared::ntdef, um::winnt};
use windows_sys::Win32::Foundation::{HMODULE, WIN32_ERROR};
use windows_sys::Win32::System::SystemServices::IMAGE_DOS_HEADER;

mod app;
mod timer;
Expand All @@ -12,16 +13,16 @@ pub use app::{AppContextInner, AppInner};
pub use timer::TimerHandleInner;
pub use window::WindowInner;

fn hinstance() -> minwindef::HINSTANCE {
fn hinstance() -> HMODULE {
extern "C" {
static __ImageBase: winnt::IMAGE_DOS_HEADER;
static __ImageBase: IMAGE_DOS_HEADER;
}

unsafe { &__ImageBase as *const winnt::IMAGE_DOS_HEADER as minwindef::HINSTANCE }
unsafe { &__ImageBase as *const IMAGE_DOS_HEADER as HMODULE }
}

fn to_wstring<S: AsRef<OsStr> + ?Sized>(str: &S) -> Vec<ntdef::WCHAR> {
let mut wstr: Vec<ntdef::WCHAR> = str.as_ref().encode_wide().collect();
fn to_wstring<S: AsRef<OsStr> + ?Sized>(str: &S) -> Vec<u16> {
let mut wstr: Vec<u16> = str.as_ref().encode_wide().collect();
wstr.push(0);
wstr
}
Expand All @@ -42,7 +43,7 @@ fn class_name(prefix: &str) -> String {

#[derive(Debug)]
pub struct OsError {
code: minwindef::DWORD,
code: WIN32_ERROR,
}

impl fmt::Display for OsError {
Expand Down
80 changes: 41 additions & 39 deletions src/backend/win32/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ use std::ptr;
use std::rc::{Rc, Weak};
use std::time::Duration;

use winapi::{
shared::basetsd, shared::minwindef, shared::ntdef, shared::windef, um::errhandlingapi,
um::winuser,
use windows_sys::core::PCWSTR;
use windows_sys::Win32::Foundation::{GetLastError, HWND, LPARAM, LRESULT, WPARAM};
use windows_sys::Win32::UI::WindowsAndMessaging::{
self as msg, CreateWindowExW, DefWindowProcW, DestroyWindow, GetWindowLongPtrW, KillTimer,
RegisterClassW, SetTimer, SetWindowLongPtrW, UnregisterClassW, WNDCLASSW,
};

use super::app::{AppContextInner, AppState};
Expand All @@ -16,19 +18,19 @@ use crate::AppContext;
use crate::{Error, Result};

pub unsafe extern "system" fn wnd_proc(
hwnd: windef::HWND,
msg: minwindef::UINT,
wparam: minwindef::WPARAM,
lparam: minwindef::LPARAM,
) -> minwindef::LRESULT {
let app_state_ptr = winuser::GetWindowLongPtrW(hwnd, winuser::GWLP_USERDATA) as *mut AppState;
hwnd: HWND,
msg: u32,
wparam: WPARAM,
lparam: LPARAM,
) -> LRESULT {
let app_state_ptr = GetWindowLongPtrW(hwnd, msg::GWLP_USERDATA) as *mut AppState;
if !app_state_ptr.is_null() {
let app_state_weak = Weak::from_raw(app_state_ptr);
let app_state = app_state_weak.clone();
let _ = app_state_weak.into_raw();

match msg {
winuser::WM_TIMER => {
msg::WM_TIMER => {
if let Some(app_state) = app_state.upgrade() {
let timer_state = app_state.timers.timers.borrow().get(&wparam).cloned();
if let Some(timer_state) = timer_state {
Expand All @@ -40,71 +42,71 @@ pub unsafe extern "system" fn wnd_proc(
}
}
}
winuser::WM_DESTROY => {
msg::WM_DESTROY => {
drop(Weak::from_raw(app_state_ptr));
winuser::SetWindowLongPtrW(hwnd, winuser::GWLP_USERDATA, 0);
SetWindowLongPtrW(hwnd, msg::GWLP_USERDATA, 0);
}
_ => {}
}
}

winuser::DefWindowProcW(hwnd, msg, wparam, lparam)
DefWindowProcW(hwnd, msg, wparam, lparam)
}

struct TimerState {
handler: RefCell<Box<dyn FnMut(&mut dyn Any, &Rc<AppState>)>>,
}

pub struct Timers {
class: minwindef::ATOM,
hwnd: windef::HWND,
next_id: Cell<basetsd::UINT_PTR>,
timers: RefCell<HashMap<basetsd::UINT_PTR, Rc<TimerState>>>,
class: u16,
hwnd: HWND,
next_id: Cell<usize>,
timers: RefCell<HashMap<usize, Rc<TimerState>>>,
}

impl Timers {
pub fn new() -> Result<Timers> {
let class_name = to_wstring(&class_name("timers-"));

let wnd_class = winuser::WNDCLASSW {
let wnd_class = WNDCLASSW {
style: 0,
lpfnWndProc: Some(wnd_proc),
cbClsExtra: 0,
cbWndExtra: 0,
hInstance: hinstance(),
hIcon: ptr::null_mut(),
hCursor: ptr::null_mut(),
hbrBackground: ptr::null_mut(),
hIcon: 0,
hCursor: 0,
hbrBackground: 0,
lpszMenuName: ptr::null(),
lpszClassName: class_name.as_ptr(),
};

let class = unsafe { winuser::RegisterClassW(&wnd_class) };
let class = unsafe { RegisterClassW(&wnd_class) };
if class == 0 {
return Err(Error::Os(OsError {
code: unsafe { errhandlingapi::GetLastError() },
code: unsafe { GetLastError() },
}));
}

let hwnd = unsafe {
winuser::CreateWindowExW(
CreateWindowExW(
0,
class as *const ntdef::WCHAR,
class as PCWSTR,
ptr::null_mut(),
0,
winuser::CW_USEDEFAULT,
winuser::CW_USEDEFAULT,
msg::CW_USEDEFAULT,
msg::CW_USEDEFAULT,
0,
0,
0,
0,
ptr::null_mut(),
ptr::null_mut(),
hinstance(),
ptr::null_mut(),
)
};
if hwnd.is_null() {
if hwnd == 0 {
return Err(Error::Os(OsError {
code: unsafe { errhandlingapi::GetLastError() },
code: unsafe { GetLastError() },
}));
}

Expand All @@ -120,7 +122,7 @@ impl Timers {
pub fn set_app_state(&self, app_state: &Rc<AppState>) {
let state_ptr = Weak::into_raw(Rc::downgrade(app_state));
unsafe {
winuser::SetWindowLongPtrW(self.hwnd, winuser::GWLP_USERDATA, state_ptr as isize);
SetWindowLongPtrW(self.hwnd, msg::GWLP_USERDATA, state_ptr as isize);
}
}

Expand Down Expand Up @@ -153,8 +155,8 @@ impl Timers {
);

unsafe {
let millis = duration.as_millis() as minwindef::UINT;
winuser::SetTimer(self.hwnd, timer_id, millis, None);
let millis = duration.as_millis() as u32;
SetTimer(self.hwnd, timer_id, millis, None);
}

TimerHandleInner {
Expand All @@ -168,28 +170,28 @@ impl Drop for Timers {
fn drop(&mut self) {
for (timer_id, _timer) in self.timers.take() {
unsafe {
winuser::KillTimer(self.hwnd, timer_id);
KillTimer(self.hwnd, timer_id);
}
}

unsafe {
winuser::DestroyWindow(self.hwnd);
winuser::UnregisterClassW(self.class as *const ntdef::WCHAR, hinstance());
DestroyWindow(self.hwnd);
UnregisterClassW(self.class as PCWSTR, hinstance());
}
}
}

pub struct TimerHandleInner {
app_state: Weak<AppState>,
timer_id: basetsd::UINT_PTR,
timer_id: usize,
}

impl TimerHandleInner {
pub fn cancel(self) {
if let Some(app_state) = self.app_state.upgrade() {
if let Some(_) = app_state.timers.timers.borrow_mut().remove(&self.timer_id) {
unsafe {
winuser::KillTimer(app_state.timers.hwnd, self.timer_id);
KillTimer(app_state.timers.hwnd, self.timer_id);
}
}
}
Expand Down
Loading

0 comments on commit 47dfd5d

Please sign in to comment.