git.lucas.co / cce-browser
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 }