diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index d7d8eac35..0be934c6c 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -1043,6 +1043,7 @@ mod glow_integration { textures_delta, shapes, mut viewports, + viewport_commands, }; let control_flow; @@ -1077,6 +1078,7 @@ mod glow_integration { textures_delta, shapes, viewports, + viewport_commands, } = integration.update( app.as_mut(), win.window.as_ref().unwrap(), @@ -1235,6 +1237,27 @@ mod glow_integration { active_viewports_ids.push(id); } + /// TODO Make this more efficient + for (id, command) in viewport_commands { + for window in gl_window.windows.iter() { + if window.window_id == id { + if let Some(win) = &window.window { + match command { + egui::window::ViewportCommand::Drag => { + // if this is not checked on x11 the input will be permanently taken until the app is killed! + if let Some(focus) = self.is_focused { + if focus == id { + win.drag_window(); + } + } + } + } + } + break; + } + } + } + gl_window .windows .retain(|w| active_viewports_ids.contains(&w.window_id)); diff --git a/crates/egui/src/containers/window.rs b/crates/egui/src/containers/window.rs index a2df4b4c2..0480d212f 100644 --- a/crates/egui/src/containers/window.rs +++ b/crates/egui/src/containers/window.rs @@ -143,6 +143,12 @@ impl ViewportBuilder { } } +#[derive(Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +pub enum ViewportCommand { + Drag, +} + /// Builder for a floating window which can be dragged, closed, collapsed, resized and scrolled (off by default). /// /// You can customize: diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index e2c58f3e1..b8cf282a6 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use crate::{ animation_manager::AnimationManager, data::output::PlatformOutput, frame_state::FrameState, input_state::*, layers::GraphicLayers, memory::Options, os::OperatingSystem, - output::FullOutput, util::IdTypeMap, TextureHandle, *, + output::FullOutput, util::IdTypeMap, window::ViewportCommand, TextureHandle, *, }; use ahash::HashMap; use epaint::{mutex::*, stats::*, text::Fonts, TessellationOptions, *}; @@ -190,6 +190,8 @@ struct ContextImpl { Arc>, ), >, + viewport_commands: Vec<(u64, ViewportCommand)>, + viewport_counter: u64, current_rendering_viewport: u64, is_desktop: bool, @@ -1353,6 +1355,7 @@ impl Context { textures_delta, shapes, viewports, + viewport_commands: self.write(|ctx| std::mem::take(&mut ctx.viewport_commands)), } } @@ -1975,6 +1978,10 @@ impl Context { self.write(|ctx| ctx.is_desktop = value) } + pub fn viewport_command(&self, id: u64, command: ViewportCommand) { + self.write(|ctx| ctx.viewport_commands.push((id, command))) + } + pub fn create_viewport( &self, window_builder: ViewportBuilder, diff --git a/crates/egui/src/data/output.rs b/crates/egui/src/data/output.rs index 85642a602..c56ca2263 100644 --- a/crates/egui/src/data/output.rs +++ b/crates/egui/src/data/output.rs @@ -2,6 +2,7 @@ use std::sync::Arc; +use crate::window::ViewportCommand; use crate::Context; use crate::{window::ViewportBuilder, WidgetType}; @@ -40,6 +41,8 @@ pub struct FullOutput { ViewportBuilder, Arc>, )>, + + pub viewport_commands: Vec<(u64, ViewportCommand)>, } impl FullOutput { @@ -50,14 +53,16 @@ impl FullOutput { repaint_after, textures_delta, shapes, - viewports: mut windows, + mut viewports, + mut viewport_commands, } = newer; self.platform_output.append(platform_output); self.repaint_after = repaint_after; // if the last frame doesn't need a repaint, then we don't need to repaint self.textures_delta.append(textures_delta); self.shapes = shapes; // Only paint the latest - self.viewports.append(&mut windows); + self.viewports.append(&mut viewports); + self.viewport_commands.append(&mut viewport_commands); } } diff --git a/examples/hello_world_simple/src/main.rs b/examples/hello_world_simple/src/main.rs index 57a540705..b06c0477d 100644 --- a/examples/hello_world_simple/src/main.rs +++ b/examples/hello_world_simple/src/main.rs @@ -53,15 +53,18 @@ fn main() -> Result<(), eframe::Error> { "Current rendering window: {}", ctx.current_rendering_viewport() )); + if ui.button("Drag").is_pointer_button_down_on() { + ctx.viewport_command(id, egui::window::ViewportCommand::Drag) + } }, ); }); let clone = window2_embedded.clone(); let embedded = *window2_embedded.read().unwrap(); egui::CollapsingHeader::new("Shout Test2").show(ui, |ui| { - egui::Window::new("Test2") - .embedded(embedded) - .show(ctx, move |ui, _, parent_id| { + egui::Window::new("Test2").embedded(embedded).show( + ctx, + move |ui, id, parent_id| { if ui .checkbox(&mut *clone.write().unwrap(), "Should embedd?") .clicked() @@ -73,7 +76,12 @@ fn main() -> Result<(), eframe::Error> { "Current rendering window: {}", ctx.current_rendering_viewport() )); - }); + + if ui.button("Drag").is_pointer_button_down_on() { + ctx.viewport_command(id, egui::window::ViewportCommand::Drag) + } + }, + ); }); }); })