1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use super::{WindowHandle, WindowState};
use crate::bindings::*;

pub trait AsAny: 'static {
    fn as_any(&self) -> &dyn std::any::Any;
    fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
}

impl<T: Sized + 'static> AsAny for T {
    fn as_any(&self) -> &dyn std::any::Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
        self
    }
}

pub trait WindowDelegate: AsAny {
    fn on_message(
        &mut self,
        window: WindowHandle,
        msg: UINT,
        wparam: WPARAM,
        lparam: LPARAM,
    ) -> (bool, LRESULT) {
        let _ = window;
        let _ = msg;
        let _ = wparam;
        let _ = lparam;

        (false, Default::default())
    }
}

impl<F> WindowDelegate for F
where
    F: Fn(WindowHandle, UINT, WPARAM, LPARAM) -> (bool, LRESULT) + AsAny,
{
    fn on_message(
        &mut self,
        window: WindowHandle,
        msg: UINT,
        wparam: WPARAM,
        lparam: LPARAM,
    ) -> (bool, LRESULT) {
        self(window, msg, wparam, lparam)
    }
}

pub(super) unsafe extern "C" fn window_delegate_thunk(
    hwnd: HWND,
    msg: UINT,
    wparam: WPARAM,
    lparam: LPARAM,
    dparam: LPVOID,
    handled: *mut SBOOL,
) -> LRESULT {
    if !dparam.is_null() {
        let state_ptr = dparam as *mut WindowState;
        if let Some(delegate) = (*state_ptr).delegate() {
            let window = WindowHandle::from(hwnd);
            let (x_handled, res) = delegate.on_message(window, msg, wparam, lparam);

            if !handled.is_null() && x_handled {
                *handled = 1;
            }

            return res;
        }
    }

    Default::default()
}