diff --git a/src/api/window.rs b/src/api/window.rs index 7cd608d..f47b32b 100644 --- a/src/api/window.rs +++ b/src/api/window.rs @@ -194,45 +194,26 @@ impl window_service_server::WindowService for WindowService { return Err(Status::invalid_argument("unspecified set or toggle")); } + let maximized = match set_or_toggle { + SetOrToggle::Set => Some(true), + SetOrToggle::Unset => Some(false), + SetOrToggle::Toggle => None, + SetOrToggle::Unspecified => unreachable!(), + }; + run_unary_no_response(&self.sender, move |state| { - let pinnacle = &mut state.pinnacle; - let Some(window) = window_id.window(pinnacle) else { + let Some(window) = window_id.window(&state.pinnacle) else { return; }; - let snapshots = window.output(pinnacle).map(|output| { - state.backend.with_renderer(|renderer| { - capture_snapshots_on_output(pinnacle, renderer, &output) - }) - }); - - match set_or_toggle { - SetOrToggle::Set => { - if !window.with_state(|state| state.fullscreen_or_maximized.is_maximized()) { - window.toggle_maximized(); - } + match maximized { + Some(maximized) => state.set_window_maximized(&window, maximized), + None => { + let is_maximized = window + .with_state(|win_state| win_state.fullscreen_or_maximized.is_maximized()); + state.set_window_maximized(&window, !is_maximized); } - SetOrToggle::Unset => { - if window.with_state(|state| state.fullscreen_or_maximized.is_maximized()) { - window.toggle_maximized(); - } - } - SetOrToggle::Toggle => window.toggle_maximized(), - SetOrToggle::Unspecified => unreachable!(), } - - let Some(output) = window.output(pinnacle) else { - return; - }; - - if let Some(snapshots) = snapshots { - output.with_state_mut(|op_state| { - op_state.new_wait_layout_transaction(pinnacle.loop_handle.clone(), snapshots) - }); - } - - pinnacle.request_layout(&output); - state.schedule_render(&output); }) .await } @@ -255,45 +236,26 @@ impl window_service_server::WindowService for WindowService { return Err(Status::invalid_argument("unspecified set or toggle")); } + let fullscreen = match set_or_toggle { + SetOrToggle::Set => Some(true), + SetOrToggle::Unset => Some(false), + SetOrToggle::Toggle => None, + SetOrToggle::Unspecified => unreachable!(), + }; + run_unary_no_response(&self.sender, move |state| { - let pinnacle = &mut state.pinnacle; - let Some(window) = window_id.window(pinnacle) else { + let Some(window) = window_id.window(&state.pinnacle) else { return; }; - let snapshots = window.output(pinnacle).map(|output| { - state.backend.with_renderer(|renderer| { - capture_snapshots_on_output(pinnacle, renderer, &output) - }) - }); - - match set_or_toggle { - SetOrToggle::Set => { - if !window.with_state(|state| state.floating_or_tiled.is_floating()) { - window.toggle_floating(); - } + match fullscreen { + Some(fullscreen) => state.set_window_fullscreen(&window, fullscreen), + None => { + let is_fullscreen = window + .with_state(|win_state| win_state.fullscreen_or_maximized.is_fullscreen()); + state.set_window_fullscreen(&window, !is_fullscreen); } - SetOrToggle::Unset => { - if window.with_state(|state| state.floating_or_tiled.is_floating()) { - window.toggle_floating(); - } - } - SetOrToggle::Toggle => window.toggle_floating(), - SetOrToggle::Unspecified => unreachable!(), } - - let Some(output) = window.output(pinnacle) else { - return; - }; - - if let Some(snapshots) = snapshots { - output.with_state_mut(|op_state| { - op_state.new_wait_layout_transaction(pinnacle.loop_handle.clone(), snapshots) - }); - } - - pinnacle.request_layout(&output); - state.schedule_render(&output); }) .await } diff --git a/src/handlers/window.rs b/src/handlers/window.rs index 8b13789..b8dd03d 100644 --- a/src/handlers/window.rs +++ b/src/handlers/window.rs @@ -1 +1,63 @@ +use crate::{ + render::util::snapshot::capture_snapshots_on_output, + state::{State, WithState}, + window::WindowElement, +}; +impl State { + pub fn set_window_maximized(&mut self, window: &WindowElement, maximized: bool) { + let snapshots = window.output(&self.pinnacle).map(|output| { + self.backend.with_renderer(|renderer| { + capture_snapshots_on_output(&mut self.pinnacle, renderer, &output) + }) + }); + + if maximized { + if !window.with_state(|state| state.fullscreen_or_maximized.is_maximized()) { + window.toggle_maximized(); + } + } else if window.with_state(|state| state.fullscreen_or_maximized.is_maximized()) { + window.toggle_maximized(); + } + + if let Some(output) = window.output(&self.pinnacle) { + if let Some(snapshots) = snapshots { + output.with_state_mut(|op_state| { + op_state + .new_wait_layout_transaction(self.pinnacle.loop_handle.clone(), snapshots) + }); + } + + self.pinnacle.request_layout(&output); + self.schedule_render(&output); + } + } + + pub fn set_window_fullscreen(&mut self, window: &WindowElement, fullscreen: bool) { + let snapshots = window.output(&self.pinnacle).map(|output| { + self.backend.with_renderer(|renderer| { + capture_snapshots_on_output(&mut self.pinnacle, renderer, &output) + }) + }); + + if fullscreen { + if !window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) { + window.toggle_fullscreen(); + } + } else if window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) { + window.toggle_fullscreen(); + } + + if let Some(output) = window.output(&self.pinnacle) { + if let Some(snapshots) = snapshots { + output.with_state_mut(|op_state| { + op_state + .new_wait_layout_transaction(self.pinnacle.loop_handle.clone(), snapshots) + }); + } + + self.pinnacle.request_layout(&output); + self.schedule_render(&output); + } + } +} diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs index 742dc85..98f1981 100644 --- a/src/handlers/xdg_shell.rs +++ b/src/handlers/xdg_shell.rs @@ -235,53 +235,30 @@ impl XdgShellHandler for State { } surface.with_pending_state(|state| { - state.states.set(xdg_toplevel::State::Fullscreen); state.size = Some(geometry.size); state.fullscreen_output = wl_output; }); let Some(window) = self.pinnacle.window_for_surface(wl_surface) else { - tracing::error!("wl_surface had no window"); return; }; - if !window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) { - window.toggle_fullscreen(); - self.pinnacle.request_layout(&output); - } + self.set_window_fullscreen(&window, true); } surface.send_configure(); } fn unfullscreen_request(&mut self, surface: ToplevelSurface) { - if !surface - .current_state() - .states - .contains(xdg_toplevel::State::Fullscreen) - { - return; - } - surface.with_pending_state(|state| { - state.states.unset(xdg_toplevel::State::Fullscreen); - state.size = None; state.fullscreen_output.take(); }); - surface.send_pending_configure(); - let Some(window) = self.pinnacle.window_for_surface(surface.wl_surface()) else { - tracing::error!("wl_surface had no window"); return; }; - if window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) { - window.toggle_fullscreen(); - if let Some(output) = window.output(&self.pinnacle) { - self.pinnacle.request_layout(&output); - } - } + self.set_window_fullscreen(&window, false); } fn maximize_request(&mut self, surface: ToplevelSurface) { @@ -289,14 +266,7 @@ impl XdgShellHandler for State { return; }; - if !window.with_state(|state| state.fullscreen_or_maximized.is_maximized()) { - window.toggle_maximized(); - } - - let Some(output) = window.output(&self.pinnacle) else { - return; - }; - self.pinnacle.request_layout(&output); + self.set_window_maximized(&window, true); } fn unmaximize_request(&mut self, surface: ToplevelSurface) { @@ -304,14 +274,7 @@ impl XdgShellHandler for State { return; }; - if window.with_state(|state| state.fullscreen_or_maximized.is_maximized()) { - window.toggle_maximized(); - } - - let Some(output) = window.output(&self.pinnacle) else { - return; - }; - self.pinnacle.request_layout(&output); + self.set_window_maximized(&window, false); } fn minimize_request(&mut self, _surface: ToplevelSurface) { diff --git a/src/handlers/xwayland.rs b/src/handlers/xwayland.rs index 1fe30c1..9ae2a48 100644 --- a/src/handlers/xwayland.rs +++ b/src/handlers/xwayland.rs @@ -49,14 +49,7 @@ impl XwmHandler for State { } let window = WindowElement::new(Window::new_x11_window(surface)); - self.pinnacle - .space - .map_element(window.clone(), (0, 0), true); - let bbox = self - .pinnacle - .space - .element_bbox(&window) - .expect("called element_bbox on an unmapped window"); + let bbox = window.bbox(); let output_size = self .pinnacle @@ -84,16 +77,13 @@ impl XwmHandler for State { unreachable!() }; - self.pinnacle.space.map_element(window.clone(), loc, true); surface.set_mapped(true).expect("failed to map x11 window"); let bbox = Rectangle::from_loc_and_size(loc, bbox.size); - debug!("map_window_request, configuring with bbox {bbox:?}"); surface .configure(bbox) .expect("failed to configure x11 window"); - // TODO: ssd if let Some(output) = self.pinnacle.focused_output() { window.place_on_output(output); @@ -103,22 +93,40 @@ impl XwmHandler for State { window.with_state_mut(|state| { state.floating_or_tiled = FloatingOrTiled::Floating(bbox); }); + self.pinnacle.space.map_element(window.clone(), loc, true); } // TODO: do snapshot and transaction here BUT ONLY IF TILED AND ON ACTIVE TAG + let snapshots = if let Some(output) = window.output(&self.pinnacle) { + Some(self.backend.with_renderer(|renderer| { + capture_snapshots_on_output(&mut self.pinnacle, renderer, &output) + })) + } else { + None + }; + self.pinnacle.windows.push(window.clone()); self.pinnacle.raise_window(window.clone(), true); self.pinnacle.apply_window_rules(&window); - if let Some(output) = window.output(&self.pinnacle) { - output.with_state_mut(|state| state.focus_stack.set_focus(window.clone())); - self.pinnacle.request_layout(&output); + if window.is_on_active_tag() { + if let Some(output) = window.output(&self.pinnacle) { + output.with_state_mut(|state| state.focus_stack.set_focus(window.clone())); + self.update_keyboard_focus(&output); - self.pinnacle.loop_handle.insert_idle(move |state| { - state.update_keyboard_focus(&output); - }); + if let Some(snapshots) = snapshots { + output.with_state_mut(|state| { + state.new_wait_layout_transaction( + self.pinnacle.loop_handle.clone(), + snapshots, + ) + }); + } + + self.pinnacle.request_layout(&output); + } } } @@ -240,10 +248,6 @@ impl XwmHandler for State { } fn maximize_request(&mut self, _xwm: XwmId, window: X11Surface) { - window - .set_maximized(true) - .expect("failed to set x11 win to maximized"); - let Some(window) = window .wl_surface() .and_then(|surf| self.pinnacle.window_for_surface(&surf)) @@ -251,16 +255,10 @@ impl XwmHandler for State { return; }; - if !window.with_state(|state| state.fullscreen_or_maximized.is_maximized()) { - window.toggle_maximized(); - } + self.set_window_maximized(&window, true); } fn unmaximize_request(&mut self, _xwm: XwmId, window: X11Surface) { - window - .set_maximized(false) - .expect("failed to set x11 win to maximized"); - let Some(window) = window .wl_surface() .and_then(|surf| self.pinnacle.window_for_surface(&surf)) @@ -268,16 +266,10 @@ impl XwmHandler for State { return; }; - if window.with_state(|state| state.fullscreen_or_maximized.is_maximized()) { - window.toggle_maximized(); - } + self.set_window_maximized(&window, false); } fn fullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) { - window - .set_fullscreen(true) - .expect("failed to set x11 win to fullscreen"); - let Some(window) = window .wl_surface() .and_then(|surf| self.pinnacle.window_for_surface(&surf)) @@ -285,19 +277,10 @@ impl XwmHandler for State { return; }; - if !window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) { - window.toggle_fullscreen(); - if let Some(output) = window.output(&self.pinnacle) { - self.pinnacle.request_layout(&output); - } - } + self.set_window_fullscreen(&window, true); } fn unfullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) { - window - .set_fullscreen(false) - .expect("failed to set x11 win to unfullscreen"); - let Some(window) = window .wl_surface() .and_then(|surf| self.pinnacle.window_for_surface(&surf)) @@ -305,12 +288,7 @@ impl XwmHandler for State { return; }; - if window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) { - window.toggle_fullscreen(); - if let Some(output) = window.output(&self.pinnacle) { - self.pinnacle.request_layout(&output); - } - } + self.set_window_fullscreen(&window, true); } fn resize_request( diff --git a/src/layout/transaction.rs b/src/layout/transaction.rs index f6bcc86..566a1ae 100644 --- a/src/layout/transaction.rs +++ b/src/layout/transaction.rs @@ -121,11 +121,11 @@ impl LayoutTransaction { /// reached. pub fn ready(&self) -> bool { Instant::now().duration_since(self.start_time) >= TIMEOUT - // || (!self.wait - // && self - // .pending_windows - // .iter() - // .all(|(win, serial)| win.is_serial_committed(*serial))) + || (!self.wait + && self + .pending_windows + .iter() + .all(|(win, serial)| win.is_serial_committed(*serial))) } }