1pub mod event;
15pub mod object;
16
17use crate::{
18 common::{attach_thread_input, get_desktop_window, get_foreground_window, Result},
19 input::get_focus,
20 msaa::{
21 event::{WinEventHook, WinEventSource},
22 object::AccessibleObject,
23 },
24 threading::{get_current_thread_id, get_window_thread_process_id},
25};
26use std::sync::RwLock;
27use windows::Win32::UI::WindowsAndMessaging::{
28 EVENT_OBJECT_ACCELERATORCHANGE, EVENT_OBJECT_CLOAKED, EVENT_OBJECT_CONTENTSCROLLED,
29 EVENT_OBJECT_CREATE, EVENT_OBJECT_DEFACTIONCHANGE, EVENT_OBJECT_DESCRIPTIONCHANGE,
30 EVENT_OBJECT_DESTROY, EVENT_OBJECT_DRAGCANCEL, EVENT_OBJECT_DRAGCOMPLETE,
31 EVENT_OBJECT_DRAGDROPPED, EVENT_OBJECT_DRAGENTER, EVENT_OBJECT_DRAGLEAVE,
32 EVENT_OBJECT_DRAGSTART, EVENT_OBJECT_END, EVENT_OBJECT_FOCUS, EVENT_OBJECT_HELPCHANGE,
33 EVENT_OBJECT_HIDE, EVENT_OBJECT_HOSTEDOBJECTSINVALIDATED, EVENT_OBJECT_IME_CHANGE,
34 EVENT_OBJECT_IME_HIDE, EVENT_OBJECT_IME_SHOW, EVENT_OBJECT_INVOKED,
35 EVENT_OBJECT_LIVEREGIONCHANGED, EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_NAMECHANGE,
36 EVENT_OBJECT_PARENTCHANGE, EVENT_OBJECT_REORDER, EVENT_OBJECT_SELECTION,
37 EVENT_OBJECT_SELECTIONADD, EVENT_OBJECT_SELECTIONREMOVE, EVENT_OBJECT_SELECTIONWITHIN,
38 EVENT_OBJECT_SHOW, EVENT_OBJECT_STATECHANGE, EVENT_OBJECT_TEXTEDIT_CONVERSIONTARGETCHANGED,
39 EVENT_OBJECT_TEXTSELECTIONCHANGED, EVENT_OBJECT_UNCLOAKED, EVENT_OBJECT_VALUECHANGE,
40 EVENT_OEM_DEFINED_END, EVENT_OEM_DEFINED_START, EVENT_SYSTEM_ALERT,
41 EVENT_SYSTEM_ARRANGMENTPREVIEW, EVENT_SYSTEM_CAPTUREEND, EVENT_SYSTEM_CAPTURESTART,
42 EVENT_SYSTEM_CONTEXTHELPEND, EVENT_SYSTEM_CONTEXTHELPSTART, EVENT_SYSTEM_DESKTOPSWITCH,
43 EVENT_SYSTEM_DIALOGEND, EVENT_SYSTEM_DIALOGSTART, EVENT_SYSTEM_DRAGDROPEND,
44 EVENT_SYSTEM_DRAGDROPSTART, EVENT_SYSTEM_END, EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_MENUEND,
45 EVENT_SYSTEM_MENUPOPUPEND, EVENT_SYSTEM_MENUPOPUPSTART, EVENT_SYSTEM_MENUSTART,
46 EVENT_SYSTEM_MINIMIZEEND, EVENT_SYSTEM_MINIMIZESTART, EVENT_SYSTEM_MOVESIZEEND,
47 EVENT_SYSTEM_MOVESIZESTART, EVENT_SYSTEM_SCROLLINGEND, EVENT_SYSTEM_SCROLLINGSTART,
48 EVENT_SYSTEM_SOUND, EVENT_SYSTEM_SWITCHEND, EVENT_SYSTEM_SWITCHSTART,
49};
50
51#[derive(Debug)]
52pub struct Msaa {
53 events: RwLock<Vec<WinEventHook>>,
54}
55
56impl Msaa {
57 pub fn new() -> Self {
61 Self {
62 events: vec![].into(),
63 }
64 }
65
66 pub fn get_desktop_object(&self) -> Result<AccessibleObject> {
70 AccessibleObject::from_window(get_desktop_window())
71 }
72
73 pub fn get_focus_object(&self) -> Result<AccessibleObject> {
77 let current_thread_id = get_current_thread_id();
78 let h_foreground = get_foreground_window();
79 let (remote_thread_id, _) = get_window_thread_process_id(h_foreground);
80 attach_thread_input(current_thread_id, remote_thread_id, true);
81 let obj = AccessibleObject::from_window(get_focus());
82 attach_thread_input(current_thread_id, remote_thread_id, false);
83 obj
84 }
85
86 pub fn add_on_object_accelerator_change_listener(
91 &self,
92 func: impl Fn(WinEventSource) + Sync + Send + 'static,
93 ) {
94 self.events
95 .write()
96 .unwrap()
97 .push(WinEventHook::new(EVENT_OBJECT_ACCELERATORCHANGE, func));
98 }
99
100 pub fn add_on_object_cloaked_listener(
105 &self,
106 func: impl Fn(WinEventSource) + Sync + Send + 'static,
107 ) {
108 self.events
109 .write()
110 .unwrap()
111 .push(WinEventHook::new(EVENT_OBJECT_CLOAKED, func));
112 }
113
114 pub fn add_on_object_content_scrolled_listener(
121 &self,
122 func: impl Fn(WinEventSource) + Sync + Send + 'static,
123 ) {
124 self.events
125 .write()
126 .unwrap()
127 .push(WinEventHook::new(EVENT_OBJECT_CONTENTSCROLLED, func));
128 }
129
130 pub fn add_on_object_create_listener(
137 &self,
138 func: impl Fn(WinEventSource) + Sync + Send + 'static,
139 ) {
140 self.events
141 .write()
142 .unwrap()
143 .push(WinEventHook::new(EVENT_OBJECT_CREATE, func));
144 }
145
146 pub fn add_on_object_default_action_change_listener(
151 &self,
152 func: impl Fn(WinEventSource) + Sync + Send + 'static,
153 ) {
154 self.events
155 .write()
156 .unwrap()
157 .push(WinEventHook::new(EVENT_OBJECT_DEFACTIONCHANGE, func));
158 }
159
160 pub fn add_on_object_description_change_listener(
165 &self,
166 func: impl Fn(WinEventSource) + Sync + Send + 'static,
167 ) {
168 self.events
169 .write()
170 .unwrap()
171 .push(WinEventHook::new(EVENT_OBJECT_DESCRIPTIONCHANGE, func));
172 }
173
174 pub fn add_on_object_destroy_listener(
181 &self,
182 func: impl Fn(WinEventSource) + Sync + Send + 'static,
183 ) {
184 self.events
185 .write()
186 .unwrap()
187 .push(WinEventHook::new(EVENT_OBJECT_DESTROY, func));
188 }
189
190 pub fn add_on_object_drag_start_listener(
195 &self,
196 func: impl Fn(WinEventSource) + Sync + Send + 'static,
197 ) {
198 self.events
199 .write()
200 .unwrap()
201 .push(WinEventHook::new(EVENT_OBJECT_DRAGSTART, func));
202 }
203
204 pub fn add_on_object_drag_cancel_listener(
209 &self,
210 func: impl Fn(WinEventSource) + Sync + Send + 'static,
211 ) {
212 self.events
213 .write()
214 .unwrap()
215 .push(WinEventHook::new(EVENT_OBJECT_DRAGCANCEL, func));
216 }
217
218 pub fn add_on_object_drag_complete_listener(
223 &self,
224 func: impl Fn(WinEventSource) + Sync + Send + 'static,
225 ) {
226 self.events
227 .write()
228 .unwrap()
229 .push(WinEventHook::new(EVENT_OBJECT_DRAGCOMPLETE, func));
230 }
231
232 pub fn add_on_object_drag_enter_listener(
237 &self,
238 func: impl Fn(WinEventSource) + Sync + Send + 'static,
239 ) {
240 self.events
241 .write()
242 .unwrap()
243 .push(WinEventHook::new(EVENT_OBJECT_DRAGENTER, func));
244 }
245
246 pub fn add_on_object_drag_leave_listener(
251 &self,
252 func: impl Fn(WinEventSource) + Sync + Send + 'static,
253 ) {
254 self.events
255 .write()
256 .unwrap()
257 .push(WinEventHook::new(EVENT_OBJECT_DRAGLEAVE, func));
258 }
259
260 pub fn add_on_object_drag_dropped_listener(
265 &self,
266 func: impl Fn(WinEventSource) + Sync + Send + 'static,
267 ) {
268 self.events
269 .write()
270 .unwrap()
271 .push(WinEventHook::new(EVENT_OBJECT_DRAGDROPPED, func));
272 }
273
274 pub fn add_on_object_end_listener(
279 &self,
280 func: impl Fn(WinEventSource) + Sync + Send + 'static,
281 ) {
282 self.events
283 .write()
284 .unwrap()
285 .push(WinEventHook::new(EVENT_OBJECT_END, func));
286 }
287
288 pub fn add_on_object_focus_listener(
294 &self,
295 func: impl Fn(WinEventSource) + Sync + Send + 'static,
296 ) {
297 self.events
298 .write()
299 .unwrap()
300 .push(WinEventHook::new(EVENT_OBJECT_FOCUS, func));
301 }
302
303 pub fn add_on_object_help_change_listener(
308 &self,
309 func: impl Fn(WinEventSource) + Sync + Send + 'static,
310 ) {
311 self.events
312 .write()
313 .unwrap()
314 .push(WinEventHook::new(EVENT_OBJECT_HELPCHANGE, func));
315 }
316
317 pub fn add_on_object_hide_listener(
324 &self,
325 func: impl Fn(WinEventSource) + Sync + Send + 'static,
326 ) {
327 self.events
328 .write()
329 .unwrap()
330 .push(WinEventHook::new(EVENT_OBJECT_HIDE, func));
331 }
332
333 pub fn add_on_object_hosted_objects_invalidated_listener(
339 &self,
340 func: impl Fn(WinEventSource) + Sync + Send + 'static,
341 ) {
342 self.events.write().unwrap().push(WinEventHook::new(
343 EVENT_OBJECT_HOSTEDOBJECTSINVALIDATED,
344 func,
345 ));
346 }
347
348 pub fn add_on_object_ime_hide_listener(
353 &self,
354 func: impl Fn(WinEventSource) + Sync + Send + 'static,
355 ) {
356 self.events
357 .write()
358 .unwrap()
359 .push(WinEventHook::new(EVENT_OBJECT_IME_HIDE, func));
360 }
361
362 pub fn add_on_object_ime_show_listener(
367 &self,
368 func: impl Fn(WinEventSource) + Sync + Send + 'static,
369 ) {
370 self.events
371 .write()
372 .unwrap()
373 .push(WinEventHook::new(EVENT_OBJECT_IME_SHOW, func));
374 }
375
376 pub fn add_on_object_ime_change_listener(
381 &self,
382 func: impl Fn(WinEventSource) + Sync + Send + 'static,
383 ) {
384 self.events
385 .write()
386 .unwrap()
387 .push(WinEventHook::new(EVENT_OBJECT_IME_CHANGE, func));
388 }
389
390 pub fn add_on_object_invoked_listener(
396 &self,
397 func: impl Fn(WinEventSource) + Sync + Send + 'static,
398 ) {
399 self.events
400 .write()
401 .unwrap()
402 .push(WinEventHook::new(EVENT_OBJECT_INVOKED, func));
403 }
404
405 pub fn add_on_object_live_region_changed_listener(
410 &self,
411 func: impl Fn(WinEventSource) + Sync + Send + 'static,
412 ) {
413 self.events
414 .write()
415 .unwrap()
416 .push(WinEventHook::new(EVENT_OBJECT_LIVEREGIONCHANGED, func));
417 }
418
419 pub fn add_on_object_location_change_listener(
428 &self,
429 func: impl Fn(WinEventSource) + Sync + Send + 'static,
430 ) {
431 self.events
432 .write()
433 .unwrap()
434 .push(WinEventHook::new(EVENT_OBJECT_LOCATIONCHANGE, func));
435 }
436
437 pub fn add_on_object_name_change_listener(
442 &self,
443 func: impl Fn(WinEventSource) + Sync + Send + 'static,
444 ) {
445 self.events
446 .write()
447 .unwrap()
448 .push(WinEventHook::new(EVENT_OBJECT_NAMECHANGE, func));
449 }
450
451 pub fn add_on_object_parent_change_listener(
456 &self,
457 func: impl Fn(WinEventSource) + Sync + Send + 'static,
458 ) {
459 self.events
460 .write()
461 .unwrap()
462 .push(WinEventHook::new(EVENT_OBJECT_PARENTCHANGE, func));
463 }
464
465 pub fn add_on_object_reorder_listener(
471 &self,
472 func: impl Fn(WinEventSource) + Sync + Send + 'static,
473 ) {
474 self.events
475 .write()
476 .unwrap()
477 .push(WinEventHook::new(EVENT_OBJECT_REORDER, func));
478 }
479
480 pub fn add_on_object_selection_listener(
488 &self,
489 func: impl Fn(WinEventSource) + Sync + Send + 'static,
490 ) {
491 self.events
492 .write()
493 .unwrap()
494 .push(WinEventHook::new(EVENT_OBJECT_SELECTION, func));
495 }
496
497 pub fn add_on_object_selection_add_listener(
503 &self,
504 func: impl Fn(WinEventSource) + Sync + Send + 'static,
505 ) {
506 self.events
507 .write()
508 .unwrap()
509 .push(WinEventHook::new(EVENT_OBJECT_SELECTIONADD, func));
510 }
511
512 pub fn add_on_object_selection_remove_listener(
519 &self,
520 func: impl Fn(WinEventSource) + Sync + Send + 'static,
521 ) {
522 self.events
523 .write()
524 .unwrap()
525 .push(WinEventHook::new(EVENT_OBJECT_SELECTIONREMOVE, func));
526 }
527
528 pub fn add_on_object_selection_within_listener(
536 &self,
537 func: impl Fn(WinEventSource) + Sync + Send + 'static,
538 ) {
539 self.events
540 .write()
541 .unwrap()
542 .push(WinEventHook::new(EVENT_OBJECT_SELECTIONWITHIN, func));
543 }
544
545 pub fn add_on_object_show_listener(
552 &self,
553 func: impl Fn(WinEventSource) + Sync + Send + 'static,
554 ) {
555 self.events
556 .write()
557 .unwrap()
558 .push(WinEventHook::new(EVENT_OBJECT_SHOW, func));
559 }
560
561 pub fn add_on_object_state_change_listener(
568 &self,
569 func: impl Fn(WinEventSource) + Sync + Send + 'static,
570 ) {
571 self.events
572 .write()
573 .unwrap()
574 .push(WinEventHook::new(EVENT_OBJECT_STATECHANGE, func));
575 }
576
577 pub fn add_on_object_text_edit_conversion_target_changed_listener(
582 &self,
583 func: impl Fn(WinEventSource) + Sync + Send + 'static,
584 ) {
585 self.events.write().unwrap().push(WinEventHook::new(
586 EVENT_OBJECT_TEXTEDIT_CONVERSIONTARGETCHANGED,
587 func,
588 ));
589 }
590
591 pub fn add_on_object_text_selection_changed_listener(
597 &self,
598 func: impl Fn(WinEventSource) + Sync + Send + 'static,
599 ) {
600 self.events
601 .write()
602 .unwrap()
603 .push(WinEventHook::new(EVENT_OBJECT_TEXTSELECTIONCHANGED, func));
604 }
605
606 pub fn add_on_object_uncloaked_listener(
611 &self,
612 func: impl Fn(WinEventSource) + Sync + Send + 'static,
613 ) {
614 self.events
615 .write()
616 .unwrap()
617 .push(WinEventHook::new(EVENT_OBJECT_UNCLOAKED, func));
618 }
619
620 pub fn add_on_object_value_change_listener(
625 &self,
626 func: impl Fn(WinEventSource) + Sync + Send + 'static,
627 ) {
628 self.events
629 .write()
630 .unwrap()
631 .push(WinEventHook::new(EVENT_OBJECT_VALUECHANGE, func));
632 }
633
634 pub fn add_on_oem_defined_start_listener(
639 &self,
640 func: impl Fn(WinEventSource) + Sync + Send + 'static,
641 ) {
642 self.events
643 .write()
644 .unwrap()
645 .push(WinEventHook::new(EVENT_OEM_DEFINED_START, func));
646 }
647
648 pub fn add_on_oem_defined_end_listener(
653 &self,
654 func: impl Fn(WinEventSource) + Sync + Send + 'static,
655 ) {
656 self.events
657 .write()
658 .unwrap()
659 .push(WinEventHook::new(EVENT_OEM_DEFINED_END, func));
660 }
661
662 pub fn add_on_system_alert_listener(
667 &self,
668 func: impl Fn(WinEventSource) + Sync + Send + 'static,
669 ) {
670 self.events
671 .write()
672 .unwrap()
673 .push(WinEventHook::new(EVENT_SYSTEM_ALERT, func));
674 }
675
676 pub fn add_on_system_arrangement_preview_listener(
681 &self,
682 func: impl Fn(WinEventSource) + Sync + Send + 'static,
683 ) {
684 self.events
685 .write()
686 .unwrap()
687 .push(WinEventHook::new(EVENT_SYSTEM_ARRANGMENTPREVIEW, func));
688 }
689
690 pub fn add_on_system_capture_end_listener(
695 &self,
696 func: impl Fn(WinEventSource) + Sync + Send + 'static,
697 ) {
698 self.events
699 .write()
700 .unwrap()
701 .push(WinEventHook::new(EVENT_SYSTEM_CAPTUREEND, func));
702 }
703
704 pub fn add_on_system_capture_start_listener(
709 &self,
710 func: impl Fn(WinEventSource) + Sync + Send + 'static,
711 ) {
712 self.events
713 .write()
714 .unwrap()
715 .push(WinEventHook::new(EVENT_SYSTEM_CAPTURESTART, func));
716 }
717
718 pub fn add_on_system_context_help_end_listener(
723 &self,
724 func: impl Fn(WinEventSource) + Sync + Send + 'static,
725 ) {
726 self.events
727 .write()
728 .unwrap()
729 .push(WinEventHook::new(EVENT_SYSTEM_CONTEXTHELPEND, func));
730 }
731
732 pub fn add_on_system_context_help_start_listener(
737 &self,
738 func: impl Fn(WinEventSource) + Sync + Send + 'static,
739 ) {
740 self.events
741 .write()
742 .unwrap()
743 .push(WinEventHook::new(EVENT_SYSTEM_CONTEXTHELPSTART, func));
744 }
745
746 pub fn add_on_system_desktop_switch_listener(
751 &self,
752 func: impl Fn(WinEventSource) + Sync + Send + 'static,
753 ) {
754 self.events
755 .write()
756 .unwrap()
757 .push(WinEventHook::new(EVENT_SYSTEM_DESKTOPSWITCH, func));
758 }
759
760 pub fn add_on_system_dialog_end_listener(
765 &self,
766 func: impl Fn(WinEventSource) + Sync + Send + 'static,
767 ) {
768 self.events
769 .write()
770 .unwrap()
771 .push(WinEventHook::new(EVENT_SYSTEM_DIALOGEND, func));
772 }
773
774 pub fn add_on_system_dialog_start_listener(
780 &self,
781 func: impl Fn(WinEventSource) + Sync + Send + 'static,
782 ) {
783 self.events
784 .write()
785 .unwrap()
786 .push(WinEventHook::new(EVENT_SYSTEM_DIALOGSTART, func));
787 }
788
789 pub fn add_on_system_drag_drop_end_listener(
794 &self,
795 func: impl Fn(WinEventSource) + Sync + Send + 'static,
796 ) {
797 self.events
798 .write()
799 .unwrap()
800 .push(WinEventHook::new(EVENT_SYSTEM_DRAGDROPEND, func));
801 }
802
803 pub fn add_on_system_drag_drop_start_listener(
808 &self,
809 func: impl Fn(WinEventSource) + Sync + Send + 'static,
810 ) {
811 self.events
812 .write()
813 .unwrap()
814 .push(WinEventHook::new(EVENT_SYSTEM_DRAGDROPSTART, func));
815 }
816
817 pub fn add_on_system_end_listener(
822 &self,
823 func: impl Fn(WinEventSource) + Sync + Send + 'static,
824 ) {
825 self.events
826 .write()
827 .unwrap()
828 .push(WinEventHook::new(EVENT_SYSTEM_END, func));
829 }
830
831 pub fn add_on_system_foreground_listener(
838 &self,
839 func: impl Fn(WinEventSource) + Sync + Send + 'static,
840 ) {
841 self.events
842 .write()
843 .unwrap()
844 .push(WinEventHook::new(EVENT_SYSTEM_FOREGROUND, func));
845 }
846
847 pub fn add_on_system_menu_popup_end_listener(
855 &self,
856 func: impl Fn(WinEventSource) + Sync + Send + 'static,
857 ) {
858 self.events
859 .write()
860 .unwrap()
861 .push(WinEventHook::new(EVENT_SYSTEM_MENUPOPUPEND, func));
862 }
863
864 pub fn add_on_system_menu_popup_start_listener(
870 &self,
871 func: impl Fn(WinEventSource) + Sync + Send + 'static,
872 ) {
873 self.events
874 .write()
875 .unwrap()
876 .push(WinEventHook::new(EVENT_SYSTEM_MENUPOPUPSTART, func));
877 }
878
879 pub fn add_on_system_menu_end_listener(
886 &self,
887 func: impl Fn(WinEventSource) + Sync + Send + 'static,
888 ) {
889 self.events
890 .write()
891 .unwrap()
892 .push(WinEventHook::new(EVENT_SYSTEM_MENUEND, func));
893 }
894
895 pub fn add_on_system_menu_start_listener(
903 &self,
904 func: impl Fn(WinEventSource) + Sync + Send + 'static,
905 ) {
906 self.events
907 .write()
908 .unwrap()
909 .push(WinEventHook::new(EVENT_SYSTEM_MENUSTART, func));
910 }
911
912 pub fn add_on_system_minimize_end_listener(
917 &self,
918 func: impl Fn(WinEventSource) + Sync + Send + 'static,
919 ) {
920 self.events
921 .write()
922 .unwrap()
923 .push(WinEventHook::new(EVENT_SYSTEM_MINIMIZEEND, func));
924 }
925
926 pub fn add_on_system_minimize_start_listener(
931 &self,
932 func: impl Fn(WinEventSource) + Sync + Send + 'static,
933 ) {
934 self.events
935 .write()
936 .unwrap()
937 .push(WinEventHook::new(EVENT_SYSTEM_MINIMIZESTART, func));
938 }
939
940 pub fn add_on_system_move_size_end_listener(
945 &self,
946 func: impl Fn(WinEventSource) + Sync + Send + 'static,
947 ) {
948 self.events
949 .write()
950 .unwrap()
951 .push(WinEventHook::new(EVENT_SYSTEM_MOVESIZEEND, func));
952 }
953
954 pub fn add_on_system_move_size_start_listener(
959 &self,
960 func: impl Fn(WinEventSource) + Sync + Send + 'static,
961 ) {
962 self.events
963 .write()
964 .unwrap()
965 .push(WinEventHook::new(EVENT_SYSTEM_MOVESIZESTART, func));
966 }
967
968 pub fn add_on_system_scrolling_end_listener(
975 &self,
976 func: impl Fn(WinEventSource) + Sync + Send + 'static,
977 ) {
978 self.events
979 .write()
980 .unwrap()
981 .push(WinEventHook::new(EVENT_SYSTEM_SCROLLINGEND, func));
982 }
983
984 pub fn add_on_system_scrolling_start_listener(
991 &self,
992 func: impl Fn(WinEventSource) + Sync + Send + 'static,
993 ) {
994 self.events
995 .write()
996 .unwrap()
997 .push(WinEventHook::new(EVENT_SYSTEM_SCROLLINGSTART, func));
998 }
999
1000 pub fn add_on_system_sound_listener(
1007 &self,
1008 func: impl Fn(WinEventSource) + Sync + Send + 'static,
1009 ) {
1010 self.events
1011 .write()
1012 .unwrap()
1013 .push(WinEventHook::new(EVENT_SYSTEM_SOUND, func));
1014 }
1015
1016 pub fn add_on_system_switch_end_listener(
1023 &self,
1024 func: impl Fn(WinEventSource) + Sync + Send + 'static,
1025 ) {
1026 self.events
1027 .write()
1028 .unwrap()
1029 .push(WinEventHook::new(EVENT_SYSTEM_SWITCHEND, func));
1030 }
1031
1032 pub fn add_on_system_switch_start_listener(
1039 &self,
1040 func: impl Fn(WinEventSource) + Sync + Send + 'static,
1041 ) {
1042 self.events
1043 .write()
1044 .unwrap()
1045 .push(WinEventHook::new(EVENT_SYSTEM_SWITCHSTART, func));
1046 }
1047
1048 pub fn remove_all_listeners(&self) {
1052 let mut lock = self.events.write().unwrap();
1053 for i in lock.iter() {
1054 i.unhook();
1055 }
1056 lock.clear();
1057 }
1058}
1059
1060impl Drop for Msaa {
1061 fn drop(&mut self) {
1062 self.remove_all_listeners()
1063 }
1064}
1065
1066#[cfg(test)]
1067mod test_msaa {
1068 use super::{super::common::get_desktop_window, object::ROLE_SYSTEM_WINDOW, Msaa};
1069
1070 #[test]
1071 fn main() {
1072 let msaa = Msaa::new();
1073 let obj = msaa.get_desktop_object().unwrap();
1074 assert!(obj.get_name(0).contains("桌面"));
1075 assert_eq!(obj.get_description(0), String::new());
1076 assert_eq!(obj.get_help(0), String::new());
1077 assert_eq!(obj.get_keyboard_shortcut(0), String::new());
1078 assert_eq!(obj.get_value(0), String::new());
1079 assert_eq!(obj.get_default_action(0), String::new());
1080 assert_eq!(obj.get_role(0), ROLE_SYSTEM_WINDOW);
1081 assert_eq!(obj.child_count(), 7);
1082 assert_eq!(obj.get_role_text(0), "窗口");
1083 assert_eq!(obj.get_state_text(0), "可设定焦点");
1084 assert_eq!(obj.window(), get_desktop_window());
1085
1086 let location = obj.location(0);
1087 dbg!(location);
1088 msaa.add_on_object_focus_listener(|src| {
1089 dbg!(src.get_object().unwrap());
1090 });
1091 std::thread::sleep(std::time::Duration::from_millis(5000));
1092 dbg!(msaa);
1093 }
1094}