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

Add RGBA cursor icon support on Windows/macOS/Linux #2117

Closed

Conversation

rofferom
Copy link

@rofferom rofferom commented Dec 28, 2021

This MR aims to be a shorter version of #1617. Note this is currently a draft to discuss if the global approach is valid from the maintainers point of view.

The goal is to have a lower level API (compared to #1617) that only provides a RGBA bitmap, its size, and the cursor hotspot, with empty implementation easy to add for other platforms.

However, I have some remarks about my patch

  • I'm quite noobish in Rust, and it is my first contribution attempt to winit. I'm pretty sure my patch is a mess :)
  • The naming is dirty, but I'm confident we can find something better
  • I can also provide a X11 implementation if requested
  • The Windows implementation is basically a port of SDL2 code
  • The whole CursorRgba content must be confirmed

Checklist

  • Tested on all platforms changed
  • Compilation warnings were addressed
  • cargo fmt has been run on this branch
  • cargo doc builds successfully
  • Added an entry to CHANGELOG.md if knowledge of this change could be valuable to users
  • Updated documentation to reflect any user-facing changes, including notes of platform-specific behavior
  • Created or updated an example program if it would help users understand this functionality
  • Updated feature matrix, if new features were added or implemented

@rofferom rofferom changed the title Add custom cursor icon support on Windows Add RGBA cursor icon support on Windows Dec 28, 2021
Copy link
Member

@msiglreith msiglreith left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the silence! Some first feedback from my side.

}
}

pub fn display(&self) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be moved to CursorHandle, which removes the duplicate logic in WM_SETCURSOR and set_cursor_ api.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -42,9 +48,100 @@ pub struct SavedWindow {
pub placement: winuser::WINDOWPLACEMENT,
}

#[derive(Clone)]
pub struct RgbaHandle {
pub hcursor: AtomicPtr<HICON__>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to reuse the RaiiIcon struct here imo, mirroring WinIcon

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually HICON__ is a raw pointer that can't be sent, I can't use RaiiIcon as is :

error[E0277]: `*mut HICON__` cannot be sent between threads safely
   --> src/platform_impl/windows/window.rs:556:30
    |
556 |         self.thread_executor.execute_in_thread(move || {
    |                              ^^^^^^^^^^^^^^^^^ `*mut HICON__` cannot be sent between threads safely
    |
    = help: within `WindowState`, the trait `Send` is not implemented for `*mut HICON__`

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My remark is outdated because of the switch to windows_sys that uses integer instead of raw pointers. I'll try to update it.

src/window.rs Outdated
@@ -961,6 +966,15 @@ impl Default for CursorIcon {
}
}

#[derive(Clone)]
pub struct CursorRgba {
pub xhot: u16,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extent and offset related parts of the API should use dpi::{PhysicalPosition, PhysicalSize} or dpi::{LogicalPosition, LogicalSize} to make it dpi aware. (I haven't checked so far how scaling logic applies in this case)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@msiglreith msiglreith added the S - api Design and usability label Jan 23, 2022
@rofferom
Copy link
Author

I have worked recently on a macOS implementation too, but it is based on the same old winit version used by this merge request. I'm going to rebase it to update my changes.

The initial version of the pull request is quite old, and I didn't take enough time to improve it, sorry about that.

@rofferom rofferom changed the title Add RGBA cursor icon support on Windows Add RGBA cursor icon support on Windows/macOS/Linux Oct 18, 2022
@rofferom
Copy link
Author

rofferom commented Oct 18, 2022

I have worked recently on a macOS implementation too, but it is based on the same old winit version used by this merge request. I'm going to rebase it to update my changes.

Update pushed with support of Windows, Linux and macOS (the name of the source branche is now wrong 🙈).

Some remarks

  • This is still a draft/proof of concept. I think a lot of things should be improved, like the CursorRgba API
  • Android/iOS/Web build need to be fixed. I will add an initial commit with the public API with empty implementations for all platforms once the public API will be correctly defined
  • Windows : Because windows_sys is now used by winit, some issues I had previously about HICON__ being raw pointer are not valid anymore. It will be easier to make a cleaner version
  • Wayland: Not implemented
  • macOS:
    • I'm not really used to Objective C, I just imported the SDL2 way to setup custom cursors. The integration in the project is dirty in the current version
    • I had a weird issue with the old winit version, I couldn't work on my Vec<> in the callback. I haven't retested it with the new version

Copy link
Member

@madsmtm madsmtm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the macOS code is a bit dirty, but workable, so don't worry much about that.

Perhaps if you made or extended an example it would help to showcase the feature (and to make it easier to test).

A fair warning, I don't think anyone really has the time nor drive to push this feature to completion, so apologies in advance for that!

src/platform_impl/macos/appkit/bitmap_image.rs Outdated Show resolved Hide resolved
Comment on lines 238 to 244
unsafe {
std::ptr::copy_nonoverlapping(
cursor.data.as_ptr() as *const u8,
pixels,
cursor.width as usize * cursor.height as usize * std::mem::size_of::<u32>(),
)
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: It is only safe to modify the pixels pointer derived from an immutable reference to NSBitmapImageRep because it contains UnsafeCell internally.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure to understand what you mean 😶

@@ -1310,6 +1315,15 @@ impl Default for CursorIcon {
}
}

#[derive(Clone)]
pub struct CursorRgba {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have Icon struct, could these perhaps be merged somehow? Unsure how exactly though.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this is a remark on my initial comment: the API is ugly. I wanted to make a basic initial implementation at first to have a something to discuss about.

I think adding a Rgba struct-like entry in Icon could be a good idea too. Maybe the other maintainers have an opinion about this ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think an entry in Icon would be a good idea, that is also basically what's proposed in the original PR

src/platform_impl/macos/window.rs Outdated Show resolved Hide resolved
src/platform_impl/macos/window.rs Outdated Show resolved Hide resolved
Comment on lines +1322 to +1323
pub width: u32,
pub height: u32,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does DPI work wrt. cursors? Would it perhaps make sense to do:

pub hotspot: PhysicalPosition<u32>,
pub size: PhysicalSize<u32>,

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that Windows change the cursor size, depending of the scaling. I should make some tests on various platforms to check the behavior.

pub yhot: u32,
pub width: u32,
pub height: u32,
pub data: Vec<u32>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it may be efficient, I quite dislike the opaqueness of this data. Rather, let's use a struct Rgba { red: u8, green: u8, blue: u8, alpha: u8 } or similar?

Or maybe if we're venturing this far, we should just straight up start using the rgb crate, or integrate with the image crate directly?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this is ugly, I must clean this part.

Use a crate to avoid to redefine a custom struct could be a good idea. I think image is a big one, rgb could be a better choice. However the crate to use should be decided by the maintainers.

@madsmtm madsmtm mentioned this pull request Aug 5, 2023
@daxpedda
Copy link
Member

Closing due to inactivity.

Tracked in #3005.

@daxpedda daxpedda closed this Aug 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DS - windows S - api Design and usability
Development

Successfully merging this pull request may close these issues.

5 participants