Skip to content
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
4 changes: 4 additions & 0 deletions crates/drag/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ unsafe impl objc::Encode for DragMode {
pub struct Options {
pub skip_animatation_on_cancel_or_failure: bool,
pub mode: DragMode,
/// Optional icon size (width, height) in pixels.
/// If set, the drag preview icon will be scaled to this size.
/// If None, the original image size will be used.
pub icon_size: Option<(u32, u32)>,
}

/// An image definition.
Expand Down
17 changes: 13 additions & 4 deletions crates/drag/src/platform_impl/macos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ pub fn start_drag<W: HasWindowHandle, F: Fn(DragResult, CursorPosition) + Send +
let ns_view: id = msg_send![window, contentView];

let mouse_location: NSPoint = msg_send![window, mouseLocationOutsideOfEventStream];
let current_position: NSPoint = msg_send![ns_view, backingAlignedRect: NSRect::new(mouse_location, NSSize::new(0., 0.)) options: NSAlignmentOptions::NSAlignAllEdgesOutward];
let rect: NSRect = msg_send![ns_view, backingAlignedRect: NSRect::new(mouse_location, NSSize::new(0., 0.)) options: NSAlignmentOptions::NSAlignAllEdgesOutward];
let current_position = rect.origin;

let img: id = msg_send![class!(NSImage), alloc];
let img: id = match image {
Expand All @@ -86,7 +87,15 @@ pub fn start_drag<W: HasWindowHandle, F: Fn(DragResult, CursorPosition) + Send +
NSImage::initWithData_(NSImage::alloc(nil), data)
}
};
let image_size: NSSize = img.size();

// Apply icon size if specified in options
let image_size: NSSize = if let Some((width, height)) = options.icon_size {
let new_size = NSSize::new(width as f64, height as f64);
let _: () = msg_send![img, setSize: new_size];
new_size
} else {
img.size()
};
let image_rect = NSRect::new(
NSPoint::new(
current_position.x - image_size.width / 2.,
Expand Down Expand Up @@ -261,15 +270,15 @@ pub fn start_drag<W: HasWindowHandle, F: Fn(DragResult, CursorPosition) + Send +

let callback_closure =
&*(*callback as *mut Box<dyn Fn(DragResult, CursorPosition)>);

if operation == 0 {
// NSDragOperationNone
callback_closure(DragResult::Cancel, mouse_location);
} else {
callback_closure(DragResult::Dropped, mouse_location);
}

drop(Box::from_raw(*callback as *mut Box<dyn Fn(DragResult)>));
drop(Box::from_raw(*callback as *mut Box<dyn Fn(DragResult, CursorPosition)>));
}
}

Expand Down
11 changes: 7 additions & 4 deletions crates/drag/src/platform_impl/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ pub fn start_drag<W: HasWindowHandle, F: Fn(DragResult, CursorPosition) + Send +
let drop_source: IDropSource = DropSource::new().into();

unsafe {
if let Some(drag_image) = get_drag_image(image) {
if let Some(drag_image) = get_drag_image(image, options.icon_size) {
if let Ok(helper) =
create_instance::<IDragSourceHelper>(&CLSID_DragDropHelper)
{
Expand Down Expand Up @@ -280,7 +280,7 @@ pub fn start_drag<W: HasWindowHandle, F: Fn(DragResult, CursorPosition) + Send +
let drop_source: IDropSource = DummyDropSource::new().into();

unsafe {
if let Some(drag_image) = get_drag_image(image) {
if let Some(drag_image) = get_drag_image(image, options.icon_size) {
if let Ok(helper) =
create_instance::<IDragSourceHelper>(&CLSID_DragDropHelper)
{
Expand Down Expand Up @@ -312,15 +312,18 @@ pub fn start_drag<W: HasWindowHandle, F: Fn(DragResult, CursorPosition) + Send +
}
}

fn get_drag_image(image: Image) -> Option<SHDRAGIMAGE> {
fn get_drag_image(image: Image, icon_size: Option<(u32, u32)>) -> Option<SHDRAGIMAGE> {
let hbitmap = match image {
Image::Raw(bytes) => image::read_bytes_to_hbitmap(&bytes).ok(),
Image::File(path) => image::read_path_to_hbitmap(&path).ok(),
};
hbitmap.map(|hbitmap| unsafe {
// get image size
let mut bitmap: BITMAP = BITMAP::default();
let (width, height) = if 0
let (width, height) = if let Some((w, h)) = icon_size {
// Use specified icon size
(w as i32, h as i32)
} else if 0
== GetObjectW(
hbitmap,
std::mem::size_of::<BITMAP>() as i32,
Expand Down