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