asdf-overlay-window 2.0.1

Asdf Overlay window handling and input library
use core::time::Duration;
use std::time::Instant;

use windows::Win32::UI::Input::KeyboardAndMouse::GetDoubleClickTime;

pub struct ClickState {
    inner: Option<Inner>,
}

impl ClickState {
    pub const fn new() -> Self {
        Self { inner: None }
    }

    pub fn get_click_count(&mut self, x: i32, y: i32, button: u32, time: Instant) -> u32 {
        fn is_consecutive(inner: &Inner, x: i32, y: i32, button: u32, time: Instant) -> bool {
            const MAX_DISTANCE: u32 = 4;

            if inner.button != button {
                return false;
            }

            if inner.x.abs_diff(x) > MAX_DISTANCE / 2 || inner.y.abs_diff(y) > MAX_DISTANCE / 2 {
                return false;
            }

            let multi_click_time = Duration::from_millis(unsafe { GetDoubleClickTime() } as _);
            time.duration_since(inner.last_click_time) <= multi_click_time
        }

        match self.inner {
            Some(ref mut inner) if is_consecutive(inner, x, y, button, time) => {
                inner.x = x;
                inner.y = y;
                inner.click_count += 1;
                inner.last_click_time = time;

                inner.click_count
            }

            _ => {
                self.inner = Some(Inner {
                    x,
                    y,
                    button,
                    click_count: 1,
                    last_click_time: time,
                });

                1
            }
        }
    }
}

struct Inner {
    x: i32,
    y: i32,
    button: u32,
    click_count: u32,
    last_click_time: Instant,
}