Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build(deps): Replace winapi by windows-sys #5038

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1200,7 +1200,6 @@ dependencies = [
"web-sys",
"web-time",
"wgpu",
"winapi",
"windows-sys 0.52.0",
"winit",
]
Expand Down
9 changes: 7 additions & 2 deletions crates/eframe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,13 @@ objc2-app-kit = { version = "0.2.0", features = [

# windows:
[target.'cfg(any(target_os = "windows"))'.dependencies]
winapi = { version = "0.3.9", features = ["winuser"] }
windows-sys = { workspace = true, features = ["Win32_Foundation", "Win32_UI_Shell", "Win32_System_Com"] }
windows-sys = { workspace = true, features = [
"Win32_Foundation",
"Win32_System_Com",
"Win32_UI_Input_KeyboardAndMouse",
"Win32_UI_Shell",
"Win32_UI_WindowsAndMessaging",
] }

# -------------------------------------------
# web:
Expand Down
53 changes: 28 additions & 25 deletions crates/eframe/src/native/app_icon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ fn set_title_and_icon(_title: &str, _icon_data: Option<&IconData>) -> AppIconSta
#[allow(unsafe_code)]
fn set_app_icon_windows(icon_data: &IconData) -> AppIconStatus {
use crate::icon_data::IconDataExt as _;
use winapi::um::winuser;
use windows_sys::Win32::UI::Input::KeyboardAndMouse;
use windows_sys::Win32::UI::WindowsAndMessaging;

// We would get fairly far already with winit's `set_window_icon` (which is exposed to eframe) actually!
// However, it only sets ICON_SMALL, i.e. doesn't allow us to set a higher resolution icon for the task bar.
Expand All @@ -91,25 +92,25 @@ fn set_app_icon_windows(icon_data: &IconData) -> AppIconStatus {
// * Querying for an owning window and setting icon there (there doesn't seem to be an owning window)
// * using undocumented SetConsoleIcon method (successfully queried via GetProcAddress)

// SAFETY: WinApi function without side-effects.
let window_handle = unsafe { winuser::GetActiveWindow() };
if window_handle.is_null() {
// SAFETY: Windows API function without side-effects.
let window_handle = unsafe { KeyboardAndMouse::GetActiveWindow() };
if window_handle == 0 {
// The Window isn't available yet. Try again later!
return AppIconStatus::NotSetTryAgain;
}

fn create_hicon_with_scale(
unscaled_image: &image::RgbaImage,
target_size: i32,
) -> winapi::shared::windef::HICON {
) -> WindowsAndMessaging::HICON {
let image_scaled = image::imageops::resize(
unscaled_image,
target_size as _,
target_size as _,
image::imageops::Lanczos3,
);

// Creating transparent icons with WinApi is a huge mess.
// Creating transparent icons with Windows API is a huge mess.
// We'd need to go through CreateIconIndirect's ICONINFO struct which then
// takes a mask HBITMAP and a color HBITMAP and creating each of these is pain.
// Instead we workaround this by creating a png which CreateIconFromResourceEx magically understands.
Expand All @@ -122,19 +123,19 @@ fn set_app_icon_windows(icon_data: &IconData) -> AppIconStatus {
)
.is_err()
{
return std::ptr::null_mut();
return 0;
}

// SAFETY: Creating an HICON which should be readonly on our data.
unsafe {
winuser::CreateIconFromResourceEx(
WindowsAndMessaging::CreateIconFromResourceEx(
image_scaled_bytes.as_mut_ptr(),
image_scaled_bytes.len() as u32,
1, // Means this is an icon, not a cursor.
0x00030000, // Version number of the HICON
target_size, // Note that this method can scale, but it does so *very* poorly. So let's avoid that!
target_size,
winuser::LR_DEFAULTCOLOR,
WindowsAndMessaging::LR_DEFAULTCOLOR,
)
}
}
Expand All @@ -154,39 +155,41 @@ fn set_app_icon_windows(icon_data: &IconData) -> AppIconStatus {
//
// Note that ICON_SMALL may be used even if we don't render a title bar as it may be used in alt+tab!
{
// SAFETY: WinAPI getter function with no known side effects.
let icon_size_big = unsafe { winuser::GetSystemMetrics(winuser::SM_CXICON) };
// SAFETY: Windows API getter function with no known side effects.
let icon_size_big =
unsafe { WindowsAndMessaging::GetSystemMetrics(WindowsAndMessaging::SM_CXICON) };
let icon_big = create_hicon_with_scale(&unscaled_image, icon_size_big);
if icon_big.is_null() {
if icon_big == 0 {
log::warn!("Failed to create HICON (for big icon) from embedded png data.");
return AppIconStatus::NotSetIgnored; // We could try independently with the small icon but what's the point, it would look bad!
} else {
// SAFETY: Unsafe WinApi function, takes objects previously created with WinAPI, all checked for null prior.
// SAFETY: Unsafe Windows API function, takes objects previously created with Windows API, all checked for null prior.
unsafe {
winuser::SendMessageW(
WindowsAndMessaging::SendMessageW(
window_handle,
winuser::WM_SETICON,
winuser::ICON_BIG as usize,
icon_big as isize,
WindowsAndMessaging::WM_SETICON,
WindowsAndMessaging::ICON_BIG as usize,
icon_big,
);
}
}
}
{
// SAFETY: WinAPI getter function with no known side effects.
let icon_size_small = unsafe { winuser::GetSystemMetrics(winuser::SM_CXSMICON) };
// SAFETY: Windows API getter function with no known side effects.
let icon_size_small =
unsafe { WindowsAndMessaging::GetSystemMetrics(WindowsAndMessaging::SM_CXSMICON) };
let icon_small = create_hicon_with_scale(&unscaled_image, icon_size_small);
if icon_small.is_null() {
if icon_small == 0 {
log::warn!("Failed to create HICON (for small icon) from embedded png data.");
return AppIconStatus::NotSetIgnored;
} else {
// SAFETY: Unsafe WinApi function, takes objects previously created with WinAPI, all checked for null prior.
// SAFETY: Unsafe Windows API function, takes objects previously created with Windows API, all checked for null prior.
unsafe {
winuser::SendMessageW(
WindowsAndMessaging::SendMessageW(
window_handle,
winuser::WM_SETICON,
winuser::ICON_SMALL as usize,
icon_small as isize,
WindowsAndMessaging::WM_SETICON,
WindowsAndMessaging::ICON_SMALL as usize,
icon_small,
);
}
}
Expand Down
Loading