From b0bbca4e69384e9aa076be95e084fd820b614e73 Mon Sep 17 00:00:00 2001 From: Sven Niederberger <73159570+s-nie@users.noreply.github.com> Date: Thu, 20 Mar 2025 10:51:02 +0100 Subject: [PATCH] Add `OutputCommand::SetPointerPosition` to set mouse position (#5776) This is not supported on the web and not yet on Wayland. ~~I also had to update `ring` and add an exception for `paste` being unmaintained.~~ Has since been updated on master. * [x] I have followed the instructions in the PR template --- crates/eframe/src/web/app_runner.rs | 3 +++ crates/egui-winit/src/lib.rs | 3 +++ crates/egui/src/context.rs | 5 +++++ crates/egui/src/data/output.rs | 3 +++ crates/egui_demo_lib/src/demo/tests/cursor_test.rs | 8 ++++++++ 5 files changed, 22 insertions(+) diff --git a/crates/eframe/src/web/app_runner.rs b/crates/eframe/src/web/app_runner.rs index 76ae1761..835b7f00 100644 --- a/crates/eframe/src/web/app_runner.rs +++ b/crates/eframe/src/web/app_runner.rs @@ -336,6 +336,9 @@ impl AppRunner { egui::OutputCommand::OpenUrl(open_url) => { super::open_url(&open_url.url, open_url.new_tab); } + egui::OutputCommand::SetPointerPosition(_) => { + // Not supported on the web. + } } } diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 147ab718..53e4ad5e 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -850,6 +850,9 @@ impl State { egui::OutputCommand::OpenUrl(open_url) => { open_url_in_browser(&open_url.url); } + egui::OutputCommand::SetPointerPosition(egui::Pos2 { x, y }) => { + let _ = window.set_cursor_position(winit::dpi::LogicalPosition { x, y }); + } } } diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 0953573c..3bdf1507 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -1482,6 +1482,11 @@ impl Context { self.send_cmd(crate::OutputCommand::CopyImage(image)); } + /// Set the mouse cursor position (if the platform supports it). + pub fn set_pointer_position(&self, position: Pos2) { + self.send_cmd(crate::OutputCommand::SetPointerPosition(position)); + } + /// Format the given shortcut in a human-readable way (e.g. `Ctrl+Shift+X`). /// /// Can be used to get the text for [`crate::Button::shortcut_text`]. diff --git a/crates/egui/src/data/output.rs b/crates/egui/src/data/output.rs index 2fdaec1e..dcc03242 100644 --- a/crates/egui/src/data/output.rs +++ b/crates/egui/src/data/output.rs @@ -95,6 +95,9 @@ pub enum OutputCommand { /// Open this url in a browser. OpenUrl(OpenUrl), + + /// Set the mouse cursor position (if the platform supports it). + SetPointerPosition(emath::Pos2), } /// The non-rendering part of what egui emits each frame. diff --git a/crates/egui_demo_lib/src/demo/tests/cursor_test.rs b/crates/egui_demo_lib/src/demo/tests/cursor_test.rs index 78214d5e..6927e1af 100644 --- a/crates/egui_demo_lib/src/demo/tests/cursor_test.rs +++ b/crates/egui_demo_lib/src/demo/tests/cursor_test.rs @@ -16,6 +16,14 @@ impl crate::Demo for CursorTest { impl crate::View for CursorTest { fn ui(&mut self, ui: &mut egui::Ui) { + if ui + .button("Center pointer in window") + .on_hover_text("The platform may not support this.") + .clicked() + { + let position = ui.ctx().available_rect().center(); + ui.ctx().set_pointer_position(position); + } ui.vertical_centered_justified(|ui| { ui.heading("Hover to switch cursor icon:"); for &cursor_icon in &egui::CursorIcon::ALL {