1     object Mouse =
2         def create (os_window : OsWindow
3                     popups : List<Control>
4                     controls : List<Control>
5                     focus : mut Atom<Option<Control>>) =
6             let position_to_control : u32 * u32 * (Control -> bool) -> Option<Control> =
7                 { x y f ->
8                       case get_control popups x y |> or_else { get_control controls x y } of
9                           None -> None
10                          Some u -> find_control u x y f }
11    
12            let mouse = Mouse =position_to_control
13            let mouse_button = Atom MouseAction/Release
14    
15            os_window.mouse_positions.subscribe { x, y ->
16                mouse.position = (x, y)
17                if mouse_button.value == MouseAction/Release && mouse.capture.is_some then
18                    let control = mouse.capture.unwrap.control
19                    val event = MouseEvent/EndMove =x =y
20                    control.push event
21                    mouse.capture = None
22    
23                if mouse.capture ? Some c then
24                    let event = MouseEvent/Move x y c.x c.y c.relative_x c.relative_y
25                    c.control.push event }
26            |> mouse.tokens.add
27    
28            os_window.mouse_scrolls.subscribe { offset_x, offset_y ->
29                let (x, y) = os_window.get_mouse_position
30                let maybe_control = position_to_control x y { _.is_scrollable }
31                if maybe_control ? Some control then
32                    val event = MouseEvent/Scroll offset_x offset_y
33                    control.push event }
34            |> mouse.tokens.add
35    
36            os_window.mouse_buttons.subscribe { button, action, _ -> case button of
37                MouseButton/Left ->
38                    mouse_button.set action
39                    let (x, y) = os_window.window.mouse_position
40                    if action == MouseAction/Press then
41                        let maybe_control = position_to_control x y { true }
42                        let maybe_window = maybe_control.flat_map { try_window _ }
43                        if maybe_window ? Some window then
44                            bring_to_front window
45    
46                    let maybe_control = position_to_control
47                        x y { control -> control.is_focusable
48                                         || control.is_clickable
49                                         || control.is_receive_mouse_move
50                                         || control.command.is_some
51                                         || (try_link control x y).is_some }
52    
53                    case maybe_control
54                    of   None ->
55                        if action == MouseAction/Press then
56                            focus.set None
57    
58                    else Some control ->
59                        let v = control.global_position
60                        if action == MouseAction/Press then
61                            let maybe_focusable = find_focusable control
62                            if maybe_focusable.is_some then
63                                focus.set maybe_focusable
64    
65                            let capture = Capture
66                                =x =y
67                                relative_x = x as f32 - v.x |> as<u32>
68                                relative_y = y as f32 - v.y |> as<u32>
69                                =control
70    
71                            mouse.capture = capture
72    
73                        if control.command.is_some then
74                            mouse.presses.push (action, control)
75    
76                        else if not control.is_clickable then
77                            let maybe_link = try_link control x y
78                            if maybe_link ? Some link then
79                                mouse.link_presses.push (action, control, link)
80                        else
81                            val event = MouseEvent/Button
82                                =action
83                                x = x as f32 - v.x |> as<u32>
84                                y = y as f32 - v.y |> as<u32>
85    
86                            control.push event
87    
88                        if action == MouseAction/Press then
89                            let event = MouseEvent/BeginMove =x =y
90                            control.push event
91    
92                    if action == MouseAction/Release then
93                        mouse.capture = None
94    
95                else -> () } |> mouse.tokens.add
96    
97            mouse
98    
99    end@ mouse
100