web browser (Servo)
git clone https://git.lucas.co/cce-browser.git
examples/wpe_options.rs (4.4K)
1 //! A `<select>` opens a list the chrome can draw and answer, end to end.
2 //!
3 //! WPE has no popup of its own, so a select only opens if the embedder
4 //! handles `show-option-menu`. Against the real engine, at output scale 2:
5 //!
6 //! * a click on the select hands over its options — labels, the optgroup
7 //! heading and child flags, the disabled one, the current value — and its
8 //! box in *logical* pixels, the chrome's own;
9 //! * a pick changes the value and fires `change`, and closes the list;
10 //! * closing without a pick leaves the value alone and fires nothing;
11 //! * a navigation while the list is open closes it from the page's side.
12 //!
13 //! `cce-shadow --instance <n> run ./target/release/examples/wpe_options`
14
15 #[cfg(not(feature = "wpe"))]
16 fn main() {
17 eprintln!("build with --features wpe");
18 }
19
20 #[cfg(feature = "wpe")]
21 #[derive(Debug, Clone, Copy)]
22 pub enum EditingCommand { Copy, Cut, Paste }
23
24 #[cfg(feature = "wpe")]
25 #[path = "../src/pages.rs"]
26 mod pages;
27 #[cfg(feature = "wpe")]
28 #[path = "../src/downloads.rs"]
29 mod downloads;
30 #[cfg(feature = "wpe")]
31 // The host's vi channel and scripts.
32 #[path = "../src/vi.rs"]
33 #[allow(dead_code)]
34 mod vi;
35
36 #[path = "../src/wpe/mod.rs"]
37 mod wpe;
38
39 #[cfg(feature = "wpe")]
40 fn main() {
41 use cce_ui::widget::MouseButton;
42 let page = "data:text/html,<!doctype html><title>start</title>\
43 <style>body{margin:0}select{position:absolute;left:100px;top:200px;width:150px;height:30px}</style>\
44 <select id=q onchange=\"document.title='change:'+this.value\">\
45 <option>1</option><option selected>2</option><option disabled>3</option>\
46 <optgroup label=More><option>4</option><option>5</option></optgroup></select>";
47 let mut host = wpe::WebKitHost::new(url::Url::parse(page).unwrap(), (2400, 1600));
48 host.resize(2400, 1600, 2.0);
49 let settle = |h: &mut wpe::WebKitHost, n: u32| {
50 for _ in 0..n {
51 h.pump(); h.frame_drawn();
52 std::thread::sleep(std::time::Duration::from_millis(50));
53 }
54 };
55 // Physical pixels, as main.rs hands them over: the select's middle is
56 // (175, 215) logical.
57 let click = |h: &mut wpe::WebKitHost| {
58 let (x, y) = (175.0 * 2.0, 215.0 * 2.0);
59 h.mouse_move(x, y);
60 h.mouse_button_ui(MouseButton::Left, true, x, y);
61 h.mouse_button_ui(MouseButton::Left, false, x, y);
62 };
63 settle(&mut host, 30);
64 println!("loaded: {:?}", host.title());
65 let mut ok = true;
66 let mut check = |name: &str, pass: bool| {
67 println!(" {name:<40} {}", if pass { "OK" } else { "FAIL" });
68 ok &= pass;
69 };
70
71 click(&mut host);
72 settle(&mut host, 10);
73 let menu = host.take_option_menu();
74 println!("menu: {menu:#?}");
75 check("click opens the list", menu.is_some() && host.option_menu_open());
76 if let Some(m) = &menu {
77 let labels: Vec<_> = m.items.iter().map(|i| i.label.as_str()).collect();
78 check(" labels in order", labels == ["1", "2", "3", "More", "4", "5"]);
79 check(" current value marked", m.items[1].selected && !m.items[0].selected);
80 check(" disabled option marked", !m.items[2].enabled);
81 check(" optgroup heading marked", m.items[3].group_label);
82 check(" group children marked", m.items[4].group_child && m.items[5].group_child);
83 let (x, y, w, h) = m.anchor;
84 check(
85 " anchor in logical pixels",
86 (x - 100.0).abs() <= 1.0 && (y - 200.0).abs() <= 1.0 && (w - 150.0).abs() <= 1.0 && (h - 30.0).abs() <= 1.0,
87 );
88 }
89
90 host.pick_option(4);
91 settle(&mut host, 10);
92 println!("after pick: {:?}", host.title());
93 check("pick changes the value", host.title().as_deref() == Some("change:4"));
94 check(" and closes the list", !host.option_menu_open());
95
96 click(&mut host);
97 settle(&mut host, 10);
98 check("opens again", host.take_option_menu().is_some());
99 host.close_option_menu();
100 settle(&mut host, 10);
101 check("close leaves the value", host.title().as_deref() == Some("change:4"));
102 check(" and closes the list", !host.option_menu_open());
103
104 click(&mut host);
105 settle(&mut host, 10);
106 check("opens a third time", host.take_option_menu().is_some());
107 host.load(url::Url::parse("data:text/html,<title>away</title>").unwrap());
108 settle(&mut host, 20);
109 println!("after navigation: {:?}", host.title());
110 check("navigation closes it from the page", !host.option_menu_open());
111
112 println!("\n{}", if ok { "OK" } else { "FAILED" });
113 std::process::exit(if ok { 0 } else { 1 });
114 }