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   end@ mouse
99