From 19d1fecb99e0bd186d5c3162243efc9ab712366e Mon Sep 17 00:00:00 2001 From: Konkitoman Date: Tue, 25 Jul 2023 11:53:10 +0300 Subject: [PATCH] Now we can drag any viewport but only the viewport that is focused will be draged because if not on x11 the input will be taken until the application is killed --- crates/eframe/src/native/run.rs | 23 +++++++++++++++++++++++ crates/egui/src/containers/window.rs | 6 ++++++ crates/egui/src/context.rs | 9 ++++++++- crates/egui/src/data/output.rs | 9 +++++++-- examples/hello_world_simple/src/main.rs | 16 ++++++++++++---- 5 files changed, 56 insertions(+), 7 deletions(-) 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) + } + }, + ); }); }); })