Repository: servo/servo
File: components/webdriver_server/lib.rs (Rust)

Code before:
                self.add_load_status_sender()?;

                self.perform_element_click(element_id)?;

                // Step 11. Try to wait for navigation to complete with session.
                // Check if there is a navigation with script
                let res = self.wait_for_navigation()?;

                // Clear the load status sender
                self.clear_load_status_sender()?;

                Ok(res)
            },
            // Step 13
            None => Ok(WebDriverResponse::Void),
        }
    }

    /// <https://w3c.github.io/webdriver/#element-click>
    /// Step 8 for elements other than <option>
    fn perform_element_click(&mut self, element: String) -> WebDriverResult<WebDriverResponse> {
        // Step 8.1 - 8.4: Create UUID, create input source "pointer".
        let id = Uuid::new_v4().to_string();

        let pointer_ids = self.session()?.pointer_ids();
        self.session_mut()?.input_state_table.insert(
            id.clone(),
            InputSourceState::Pointer(PointerInputState::new(PointerType::Mouse, pointer_ids)),
        );

        // Step 8.7. Construct a pointer move action.
        // Step 8.8. Set a property x to 0 on pointer move action.
        // Step 8.9. Set a property y to 0 on pointer move action.
        // Step 8.10. Set a property origin to element on pointer move action.
        let pointer_move_action = PointerMoveAction {
            duration: None,
            origin: PointerOrigin::Element(WebElement(element)),
            x: 0.0,
            y: 0.0,
            ..Default::default()
        };

        // Step 8.11. Construct pointer down action.
        // Step 8.12. Set a property button to 0 on pointer down action.
        let pointer_down_action = PointerDownAction {
            button: i16::from(MouseButton::Left) as u64,
            ..Default::default()
        };

        // Step 8.13. Construct pointer up action.
        // Step 8.14. Set a property button to 0 on pointer up action.

Review comment (suggestion):
I would prefer if we did a runtime check for device type, since ohos / android devices can be run in desktop mode.
I don't think we need ot change this now, would just prefer if we didn't add to many cfgs like this when it shouldn't be a compiletime option.

Code after:
                // Load status sender should be set up before we dispatch actions
                // to ensure webdriver can capture any navigation events.
                self.add_load_status_sender()?;

                self.perform_element_click(element_id)?;

                // Step 11. Try to wait for navigation to complete with session.
                // Check if there is a navigation with script
                let res = self.wait_for_navigation()?;

                // Clear the load status sender
                self.clear_load_status_sender()?;

                Ok(res)
            },
            // Step 13
            None => Ok(WebDriverResponse::Void),
        }
    }

    /// <https://w3c.github.io/webdriver/#element-click>
    /// Step 8 for elements other than <option>
    /// There is currently no spec for touchscreen webdriver support.
    /// There is an ongoing discussion in W3C:
    /// <https://github.com/w3c/webdriver/issues/1925>
    #[cfg(any(target_env = "ohos", target_os = "android"))]
    fn perform_element_click(&mut self, element: String) -> WebDriverResult<WebDriverResponse> {
        // Step 8.1 - 8.4: Create UUID, create input source "pointer".
        let id = Uuid::new_v4().to_string();

        let pointer_ids = self.session()?.pointer_ids();
        let (x, y) = self
            .get_origin_relative_coordinates(
                &PointerOrigin::Element(WebElement(element.clone())),
                0.0,
                0.0,
                &id,
            )
            .map_err(|err| WebDriverError::new(err, ""))?;

        // Difference with Desktop: Create an input source with coordinates directly at the
        // element centre.
        self.session_mut()?.input_state_table.insert(
            id.clone(),
            InputSourceState::Pointer(PointerInputState::new(
                PointerType::Touch,
                pointer_ids,
                x,
                y,
            )),
        );