Make x11 popups float, fix x11 windows not reappearing

Popups currently appear behind all other windows and apps like Steam show up as black on the winit backend, but stuff like Discord should work.
This commit is contained in:
Ottatop 2023-07-26 16:01:53 -05:00
parent c2190f2e0c
commit fe2a08c704
6 changed files with 176 additions and 76 deletions

View file

@ -121,6 +121,12 @@ impl<B: Backend> CompositorHandler for State<B> {
window.with_state(|state| { window.with_state(|state| {
if let WindowResizeState::Acknowledged(new_pos) = state.resize_state { if let WindowResizeState::Acknowledged(new_pos) = state.resize_state {
state.resize_state = WindowResizeState::Idle; state.resize_state = WindowResizeState::Idle;
if let WindowElement::X11(surface) = &window {
tracing::debug!("setting x11 win to mapped");
if !surface.is_override_redirect() {
surface.set_mapped(true).expect("failed to map x11 win");
}
}
self.space.map_element(window.clone(), new_pos, false); self.space.map_element(window.clone(), new_pos, false);
} }
}); });
@ -296,7 +302,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
first_tag.layout().layout( first_tag.layout().layout(
self.windows.clone(), self.windows.clone(),
state.focused_tags().cloned().collect(), state.focused_tags().cloned().collect(),
&self.space, self,
&focused_output, &focused_output,
); );
} }
@ -350,15 +356,15 @@ impl<B: Backend> XdgShellHandler for State<B> {
.wl_surface() .wl_surface()
.is_some_and(|surf| &surf != surface.wl_surface()) .is_some_and(|surf| &surf != surface.wl_surface())
}); });
if let Some(focused_output) = self.focus_state.focused_output.as_ref() { if let Some(focused_output) = self.focus_state.focused_output.as_ref().cloned() {
focused_output.with_state(|state| { focused_output.with_state(|state| {
let first_tag = state.focused_tags().next(); let first_tag = state.focused_tags().next();
if let Some(first_tag) = first_tag { if let Some(first_tag) = first_tag {
first_tag.layout().layout( first_tag.layout().layout(
self.windows.clone(), self.windows.clone(),
state.focused_tags().cloned().collect(), state.focused_tags().cloned().collect(),
&self.space, self,
focused_output, &focused_output,
); );
} }
}); });

View file

@ -4,8 +4,10 @@
// //
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use std::time::Duration;
use smithay::{ use smithay::{
desktop::space::SpaceElement, desktop::{space::SpaceElement, utils::surface_primary_scanout_output},
input::pointer::Focus, input::pointer::Focus,
reexports::wayland_server::Resource, reexports::wayland_server::Resource,
utils::{Logical, Rectangle, SERIAL_COUNTER}, utils::{Logical, Rectangle, SERIAL_COUNTER},
@ -20,7 +22,7 @@ use crate::{
backend::Backend, backend::Backend,
grab::resize_grab::{ResizeSurfaceGrab, ResizeSurfaceState}, grab::resize_grab::{ResizeSurfaceGrab, ResizeSurfaceState},
state::{CalloopData, WithState}, state::{CalloopData, WithState},
window::{WindowBlocker, WindowElement, BLOCKER_COUNTER}, window::{WindowBlocker, WindowElement, BLOCKER_COUNTER, window_state::Float},
}; };
impl<B: Backend> XwmHandler for CalloopData<B> { impl<B: Backend> XwmHandler for CalloopData<B> {
@ -34,16 +36,15 @@ impl<B: Backend> XwmHandler for CalloopData<B> {
fn map_window_request(&mut self, xwm: XwmId, window: X11Surface) { fn map_window_request(&mut self, xwm: XwmId, window: X11Surface) {
tracing::debug!("new x11 window from map_window_request"); tracing::debug!("new x11 window from map_window_request");
tracing::debug!("window popup is {}", window.is_popup());
window.set_mapped(true).expect("failed to map x11 window"); window.set_mapped(true).expect("failed to map x11 window");
let window = WindowElement::X11(window); let window = WindowElement::X11(window);
// TODO: place the window in the space
self.state.space.map_element(window.clone(), (0, 0), true); self.state.space.map_element(window.clone(), (0, 0), true);
let bbox = self // let geo = window.geometry();
.state
.space
.element_bbox(&window)
.expect("failed to get x11 bbox");
let WindowElement::X11(surface) = &window else { unreachable!() }; let WindowElement::X11(surface) = &window else { unreachable!() };
let bbox = self.state.space.element_bbox(&window).unwrap();
tracing::debug!("map_window_request, configuring with bbox {bbox:?}");
surface surface
.configure(Some(bbox)) .configure(Some(bbox))
.expect("failed to configure x11 window"); .expect("failed to configure x11 window");
@ -73,6 +74,21 @@ impl<B: Backend> XwmHandler for CalloopData<B> {
tracing::debug!("new window, tags are {:?}", state.tags); tracing::debug!("new window, tags are {:?}", state.tags);
}); });
window.with_state(|state| {
let WindowElement::X11(surface) = &window else { unreachable!() };
let is_popup = surface.window_type().is_some_and(|typ| !matches!(typ, smithay::xwayland::xwm::WmWindowType::Normal));
if surface.is_popup() || is_popup || surface.min_size() == surface.max_size() {
state.floating = Float::Floating;
}
});
// self.state.space.map_element(window.clone(), (0, 0), true);
// self.state.space.raise_element(&window, true);
// let WindowElement::X11(surface) = &window else { unreachable!() };
// self.state.xwm.as_mut().unwrap().raise_window(surface).unwrap();
let windows_on_output = self let windows_on_output = self
.state .state
.windows .windows
@ -96,7 +112,6 @@ impl<B: Backend> XwmHandler for CalloopData<B> {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
self.state.windows.push(window.clone()); self.state.windows.push(window.clone());
// self.space.map_element(window.clone(), (0, 0), true);
if let Some(focused_output) = self.state.focus_state.focused_output.clone() { if let Some(focused_output) = self.state.focus_state.focused_output.clone() {
focused_output.with_state(|state| { focused_output.with_state(|state| {
let first_tag = state.focused_tags().next(); let first_tag = state.focused_tags().next();
@ -104,7 +119,7 @@ impl<B: Backend> XwmHandler for CalloopData<B> {
first_tag.layout().layout( first_tag.layout().layout(
self.state.windows.clone(), self.state.windows.clone(),
state.focused_tags().cloned().collect(), state.focused_tags().cloned().collect(),
&self.state.space, &mut self.state,
&focused_output, &focused_output,
); );
} }
@ -120,8 +135,8 @@ impl<B: Backend> XwmHandler for CalloopData<B> {
} }
} }
let clone = window.clone(); let clone = window.clone();
self.state.loop_handle.insert_idle(|data| { self.state.loop_handle.insert_idle(move |data| {
crate::state::schedule_on_commit(data, vec![clone], move |data| { crate::state::schedule_on_commit(data, vec![clone.clone()], move |data| {
BLOCKER_COUNTER.store(0, std::sync::atomic::Ordering::SeqCst); BLOCKER_COUNTER.store(0, std::sync::atomic::Ordering::SeqCst);
tracing::debug!( tracing::debug!(
"blocker {}", "blocker {}",
@ -135,6 +150,20 @@ impl<B: Backend> XwmHandler for CalloopData<B> {
.client_compositor_state(&client) .client_compositor_state(&client)
.blocker_cleared(&mut data.state, &data.display.handle()) .blocker_cleared(&mut data.state, &data.display.handle())
} }
// data.state.loop_handle.insert_idle(move |dt| {
//
// let WindowElement::X11(surface) = &clone else { unreachable!() };
// let is_popup = surface.window_type().is_some_and(|typ| !matches!(typ, smithay::xwayland::xwm::WmWindowType::Normal));
// if surface.is_popup() || is_popup || surface.min_size() == surface.max_size() {
// if let Some(xwm) = dt.state.xwm.as_mut() {
// tracing::debug!("raising x11 modal");
// xwm.raise_window(surface).expect("failed to raise x11 win");
// dt.state.space.raise_element(&clone, true);
// }
// }
// });
}) })
}); });
} }
@ -152,28 +181,36 @@ impl<B: Backend> XwmHandler for CalloopData<B> {
} }
} }
fn mapped_override_redirect_window(&mut self, xwm: XwmId, window: X11Surface) { // fn map_window_notify(&mut self, xwm: XwmId, window: X11Surface) {
// //
// }
fn mapped_override_redirect_window(&mut self, _xwm: XwmId, window: X11Surface) {
let loc = window.geometry().loc; let loc = window.geometry().loc;
let window = WindowElement::X11(window); let window = WindowElement::X11(window);
tracing::debug!("mapped_override_redirect_window to loc {loc:?}");
self.state.space.map_element(window, loc, true); self.state.space.map_element(window, loc, true);
} }
fn unmapped_window(&mut self, xwm: XwmId, window: X11Surface) { fn unmapped_window(&mut self, _xwm: XwmId, window: X11Surface) {
tracing::debug!("unmapped x11 window"); tracing::debug!("unmapped x11 window");
let win = self let win = self
.state .state
.space .space
.elements() .elements()
.find(|elem| matches!(elem, WindowElement::X11(surface) if surface == &window)) .find(|elem| {
matches!(elem,
WindowElement::X11(surface) if surface == &window)
})
.cloned(); .cloned();
if let Some(win) = win { if let Some(win) = win {
self.state.space.unmap_elem(&win); self.state.space.unmap_elem(&win);
// self.state.windows.retain(|elem| &win != elem); // self.state.windows.retain(|elem| &win != elem);
if win.with_state(|state| state.floating.is_tiled()) { // if win.with_state(|state| state.floating.is_tiled()) {
if let Some(output) = win.output(&self.state) { // if let Some(output) = win.output(&self.state) {
self.state.re_layout(&output); // self.state.re_layout(&output);
} // }
} // }
} }
if !window.is_override_redirect() { if !window.is_override_redirect() {
window.set_mapped(false).expect("failed to unmap x11 win"); window.set_mapped(false).expect("failed to unmap x11 win");
@ -232,6 +269,7 @@ impl<B: Backend> XwmHandler for CalloopData<B> {
geometry: Rectangle<i32, Logical>, geometry: Rectangle<i32, Logical>,
above: Option<smithay::reexports::x11rb::protocol::xproto::Window>, above: Option<smithay::reexports::x11rb::protocol::xproto::Window>,
) { ) {
tracing::debug!("x11 configure_notify");
let Some(win) = self let Some(win) = self
.state .state
.space .space
@ -241,7 +279,11 @@ impl<B: Backend> XwmHandler for CalloopData<B> {
else { else {
return; return;
}; };
tracing::debug!("geo: {geometry:?}");
self.state.space.map_element(win, geometry.loc, false); self.state.space.map_element(win, geometry.loc, false);
// for output in self.state.space.outputs_for_element(&win) {
// win.send_frame(&output, self.state.clock.now(), Some(Duration::ZERO), surface_primary_scanout_output);
// }
// TODO: anvil has a TODO here // TODO: anvil has a TODO here
} }
@ -249,13 +291,16 @@ impl<B: Backend> XwmHandler for CalloopData<B> {
// TODO: unmaximize request // TODO: unmaximize request
// TODO: fullscreen request fn fullscreen_request(&mut self, xwm: XwmId, window: X11Surface) {
// TODO:
window.set_fullscreen(true).unwrap();
}
// TODO: unfullscreen request // TODO: unfullscreen request
fn resize_request( fn resize_request(
&mut self, &mut self,
xwm: XwmId, _xwm: XwmId,
window: X11Surface, window: X11Surface,
button: u32, button: u32,
resize_edge: smithay::xwayland::xwm::ResizeEdge, resize_edge: smithay::xwayland::xwm::ResizeEdge,
@ -296,7 +341,7 @@ impl<B: Backend> XwmHandler for CalloopData<B> {
win.clone(), win.clone(),
resize_edge.into(), resize_edge.into(),
Rectangle::from_loc_and_size(initial_window_location, initial_window_size), Rectangle::from_loc_and_size(initial_window_location, initial_window_size),
0x110, // BUTTON_LEFT button, // BUTTON_LEFT
); );
if let Some(grab) = grab { if let Some(grab) = grab {

View file

@ -2,7 +2,6 @@
use itertools::{Either, Itertools}; use itertools::{Either, Itertools};
use smithay::{ use smithay::{
desktop::Space,
output::Output, output::Output,
utils::{Logical, Size}, utils::{Logical, Size},
}; };
@ -27,35 +26,30 @@ pub enum Layout {
} }
impl Layout { impl Layout {
pub fn layout( pub fn layout<B: Backend>(
&self, &self,
windows: Vec<WindowElement>, windows: Vec<WindowElement>,
tags: Vec<Tag>, tags: Vec<Tag>,
space: &Space<WindowElement>, state: &mut State<B>,
output: &Output, output: &Output,
) { ) {
let windows = filter_windows(&windows, tags); let windows = filter_windows(&windows, tags);
let Some(output_geo) = space.output_geometry(output) else {
tracing::error!("could not get output geometry");
return;
};
let output_loc = output.current_location();
match self { match self {
Layout::MasterStack => master_stack(windows, space, output), Layout::MasterStack => master_stack(windows, state, output),
Layout::Dwindle => dwindle(windows, space, output), Layout::Dwindle => dwindle(windows, state, output),
Layout::Spiral => spiral(windows, space, output), Layout::Spiral => spiral(windows, state, output),
layout @ (Layout::CornerTopLeft layout @ (Layout::CornerTopLeft
| Layout::CornerTopRight | Layout::CornerTopRight
| Layout::CornerBottomLeft | Layout::CornerBottomLeft
| Layout::CornerBottomRight) => corner(layout, windows, space, output), | Layout::CornerBottomRight) => corner(layout, windows, state, output),
} }
} }
} }
fn master_stack(windows: Vec<WindowElement>, space: &Space<WindowElement>, output: &Output) { fn master_stack<B: Backend>(windows: Vec<WindowElement>, state: &mut State<B>, output: &Output) {
let space = &mut state.space;
let Some(output_geo) = space.output_geometry(output) else { let Some(output_geo) = space.output_geometry(output) else {
tracing::error!("could not get output geometry"); tracing::error!("could not get output geometry");
return; return;
@ -72,11 +66,11 @@ fn master_stack(windows: Vec<WindowElement>, space: &Space<WindowElement>, outpu
if stack_count == 0 { if stack_count == 0 {
// one window // one window
master.request_size_change(output_loc, output_geo.size); master.request_size_change(state, output_loc, output_geo.size);
} else { } else {
let loc = (output_loc.x, output_loc.y).into(); let loc = (output_loc.x, output_loc.y).into();
let new_master_size: Size<i32, Logical> = (output_geo.size.w / 2, output_geo.size.h).into(); let new_master_size: Size<i32, Logical> = (output_geo.size.w / 2, output_geo.size.h).into();
master.request_size_change(loc, new_master_size); master.request_size_change(state, loc, new_master_size);
let stack_count = stack_count; let stack_count = stack_count;
@ -93,6 +87,7 @@ fn master_stack(windows: Vec<WindowElement>, space: &Space<WindowElement>, outpu
for (i, win) in stack.enumerate() { for (i, win) in stack.enumerate() {
win.request_size_change( win.request_size_change(
state,
(output_geo.size.w / 2 + output_loc.x, y_s[i] + output_loc.y).into(), (output_geo.size.w / 2 + output_loc.x, y_s[i] + output_loc.y).into(),
(output_geo.size.w / 2, i32::max(heights[i], 40)).into(), (output_geo.size.w / 2, i32::max(heights[i], 40)).into(),
); );
@ -100,7 +95,9 @@ fn master_stack(windows: Vec<WindowElement>, space: &Space<WindowElement>, outpu
} }
} }
fn dwindle(windows: Vec<WindowElement>, space: &Space<WindowElement>, output: &Output) { fn dwindle<B: Backend>(windows: Vec<WindowElement>, state: &mut State<B>, output: &Output) {
let space = &state.space;
let Some(output_geo) = space.output_geometry(output) else { let Some(output_geo) = space.output_geometry(output) else {
tracing::error!("could not get output geometry"); tracing::error!("could not get output geometry");
return; return;
@ -112,7 +109,7 @@ fn dwindle(windows: Vec<WindowElement>, space: &Space<WindowElement>, output: &O
if iter.peek().is_none() { if iter.peek().is_none() {
if let Some(window) = windows.first() { if let Some(window) = windows.first() {
window.request_size_change(output_loc, output_geo.size); window.request_size_change(state, output_loc, output_geo.size);
} }
} else { } else {
let mut win1_size = output_geo.size; let mut win1_size = output_geo.size;
@ -137,6 +134,7 @@ fn dwindle(windows: Vec<WindowElement>, space: &Space<WindowElement>, output: &O
let width_partition = win1_size.w / 2; let width_partition = win1_size.w / 2;
win1.request_size_change( win1.request_size_change(
state,
win1_loc, win1_loc,
(win1_size.w - width_partition, i32::max(win1_size.h, 40)).into(), (win1_size.w - width_partition, i32::max(win1_size.h, 40)).into(),
); );
@ -144,12 +142,13 @@ fn dwindle(windows: Vec<WindowElement>, space: &Space<WindowElement>, output: &O
win1_loc = (win1_loc.x + (win1_size.w - width_partition), win1_loc.y).into(); win1_loc = (win1_loc.x + (win1_size.w - width_partition), win1_loc.y).into();
win1_size = (width_partition, i32::max(win1_size.h, 40)).into(); win1_size = (width_partition, i32::max(win1_size.h, 40)).into();
win2.request_size_change(win1_loc, win1_size); win2.request_size_change(state, win1_loc, win1_size);
} }
Slice::Below => { Slice::Below => {
let height_partition = win1_size.h / 2; let height_partition = win1_size.h / 2;
win1.request_size_change( win1.request_size_change(
state,
win1_loc, win1_loc,
(win1_size.w, i32::max(win1_size.h - height_partition, 40)).into(), (win1_size.w, i32::max(win1_size.h - height_partition, 40)).into(),
); );
@ -157,14 +156,15 @@ fn dwindle(windows: Vec<WindowElement>, space: &Space<WindowElement>, output: &O
win1_loc = (win1_loc.x, win1_loc.y + (win1_size.h - height_partition)).into(); win1_loc = (win1_loc.x, win1_loc.y + (win1_size.h - height_partition)).into();
win1_size = (win1_size.w, i32::max(height_partition, 40)).into(); win1_size = (win1_size.w, i32::max(height_partition, 40)).into();
win2.request_size_change(win1_loc, win1_size); win2.request_size_change(state, win1_loc, win1_size);
} }
} }
} }
} }
} }
fn spiral(windows: Vec<WindowElement>, space: &Space<WindowElement>, output: &Output) { fn spiral<B: Backend>(windows: Vec<WindowElement>, state: &mut State<B>, output: &Output) {
let space = &state.space;
let Some(output_geo) = space.output_geometry(output) else { let Some(output_geo) = space.output_geometry(output) else {
tracing::error!("could not get output geometry"); tracing::error!("could not get output geometry");
return; return;
@ -176,7 +176,7 @@ fn spiral(windows: Vec<WindowElement>, space: &Space<WindowElement>, output: &Ou
if iter.peek().is_none() { if iter.peek().is_none() {
if let Some(window) = windows.first() { if let Some(window) = windows.first() {
window.request_size_change(output_loc, output_geo.size); window.request_size_change(state, output_loc, output_geo.size);
} }
} else { } else {
let mut win1_loc = output_loc; let mut win1_loc = output_loc;
@ -206,59 +206,64 @@ fn spiral(windows: Vec<WindowElement>, space: &Space<WindowElement>, output: &Ou
let height_partition = win1_size.h / 2; let height_partition = win1_size.h / 2;
win1.request_size_change( win1.request_size_change(
state,
(win1_loc.x, win1_loc.y + height_partition).into(), (win1_loc.x, win1_loc.y + height_partition).into(),
(win1_size.w, i32::max(win1_size.h - height_partition, 40)).into(), (win1_size.w, i32::max(win1_size.h - height_partition, 40)).into(),
); );
win1_size = (win1_size.w, i32::max(height_partition, 40)).into(); win1_size = (win1_size.w, i32::max(height_partition, 40)).into();
win2.request_size_change(win1_loc, win1_size); win2.request_size_change(state, win1_loc, win1_size);
} }
Slice::Below => { Slice::Below => {
let height_partition = win1_size.h / 2; let height_partition = win1_size.h / 2;
win1.request_size_change( win1.request_size_change(
state,
win1_loc, win1_loc,
(win1_size.w, win1_size.h - i32::max(height_partition, 40)).into(), (win1_size.w, win1_size.h - i32::max(height_partition, 40)).into(),
); );
win1_loc = (win1_loc.x, win1_loc.y + (win1_size.h - height_partition)).into(); win1_loc = (win1_loc.x, win1_loc.y + (win1_size.h - height_partition)).into();
win1_size = (win1_size.w, i32::max(height_partition, 40)).into(); win1_size = (win1_size.w, i32::max(height_partition, 40)).into();
win2.request_size_change(win1_loc, win1_size); win2.request_size_change(state, win1_loc, win1_size);
} }
Slice::Left => { Slice::Left => {
let width_partition = win1_size.w / 2; let width_partition = win1_size.w / 2;
win1.request_size_change( win1.request_size_change(
state,
(win1_loc.x + width_partition, win1_loc.y).into(), (win1_loc.x + width_partition, win1_loc.y).into(),
(win1_size.w - width_partition, i32::max(win1_size.h, 40)).into(), (win1_size.w - width_partition, i32::max(win1_size.h, 40)).into(),
); );
win1_size = (width_partition, i32::max(win1_size.h, 40)).into(); win1_size = (width_partition, i32::max(win1_size.h, 40)).into();
win2.request_size_change(win1_loc, win1_size); win2.request_size_change(state, win1_loc, win1_size);
} }
Slice::Right => { Slice::Right => {
let width_partition = win1_size.w / 2; let width_partition = win1_size.w / 2;
win1.request_size_change( win1.request_size_change(
state,
win1_loc, win1_loc,
(win1_size.w - width_partition, i32::max(win1_size.h, 40)).into(), (win1_size.w - width_partition, i32::max(win1_size.h, 40)).into(),
); );
win1_loc = (win1_loc.x + (win1_size.w - width_partition), win1_loc.y).into(); win1_loc = (win1_loc.x + (win1_size.w - width_partition), win1_loc.y).into();
win1_size = (width_partition, i32::max(win1_size.h, 40)).into(); win1_size = (width_partition, i32::max(win1_size.h, 40)).into();
win2.request_size_change(win1_loc, win1_size); win2.request_size_change(state, win1_loc, win1_size);
} }
} }
} }
} }
} }
fn corner( fn corner<B: Backend>(
layout: &Layout, layout: &Layout,
windows: Vec<WindowElement>, windows: Vec<WindowElement>,
space: &Space<WindowElement>, state: &mut State<B>,
output: &Output, output: &Output,
) { ) {
let space = &state.space;
let Some(output_geo) = space.output_geometry(output) else { let Some(output_geo) = space.output_geometry(output) else {
tracing::error!("could not get output geometry"); tracing::error!("could not get output geometry");
return; return;
@ -268,15 +273,17 @@ fn corner(
match windows.len() { match windows.len() {
0 => (), 0 => (),
1 => { 1 => {
windows[0].request_size_change(output_loc, output_geo.size); windows[0].request_size_change(state, output_loc, output_geo.size);
} }
2 => { 2 => {
windows[0].request_size_change( windows[0].request_size_change(
state,
output_loc, output_loc,
(output_geo.size.w / 2, output_geo.size.h).into(), (output_geo.size.w / 2, output_geo.size.h).into(),
); );
windows[1].request_size_change( windows[1].request_size_change(
state,
(output_loc.x + output_geo.size.w / 2, output_loc.y).into(), (output_loc.x + output_geo.size.w / 2, output_loc.y).into(),
(output_geo.size.w / 2, output_geo.size.h).into(), (output_geo.size.w / 2, output_geo.size.h).into(),
); );
@ -296,6 +303,7 @@ fn corner(
let div_factor = 2; let div_factor = 2;
corner.request_size_change( corner.request_size_change(
state,
match layout { match layout {
Layout::CornerTopLeft => (output_loc.x, output_loc.y), Layout::CornerTopLeft => (output_loc.x, output_loc.y),
Layout::CornerTopRight => ( Layout::CornerTopRight => (
@ -335,6 +343,7 @@ fn corner(
for (i, win) in vert_stack.iter().enumerate() { for (i, win) in vert_stack.iter().enumerate() {
win.request_size_change( win.request_size_change(
state,
( (
match layout { match layout {
Layout::CornerTopLeft | Layout::CornerBottomLeft => { Layout::CornerTopLeft | Layout::CornerBottomLeft => {
@ -367,6 +376,7 @@ fn corner(
for (i, win) in horiz_stack.iter().enumerate() { for (i, win) in horiz_stack.iter().enumerate() {
win.request_size_change( win.request_size_change(
state,
match layout { match layout {
Layout::CornerTopLeft => { Layout::CornerTopLeft => {
(x_s[i] + output_loc.x, output_loc.y + output_geo.size.h / 2) (x_s[i] + output_loc.x, output_loc.y + output_geo.size.h / 2)
@ -392,16 +402,15 @@ fn corner(
fn filter_windows(windows: &[WindowElement], tags: Vec<Tag>) -> Vec<WindowElement> { fn filter_windows(windows: &[WindowElement], tags: Vec<Tag>) -> Vec<WindowElement> {
windows windows
.iter() .iter()
.filter(|window| window.with_state(|state| state.floating.is_tiled()))
.filter(|window| { .filter(|window| {
window.with_state(|state| { window.with_state(|state| {
state.floating.is_tiled() && {
for tag in state.tags.iter() { for tag in state.tags.iter() {
if tags.iter().any(|tg| tg == tag) { if tags.iter().any(|tg| tg == tag) {
return true; return true;
} }
} }
false false
}
}) })
}) })
.cloned() .cloned()

View file

@ -8,7 +8,7 @@
//! While Pinnacle is not a library, this documentation serves to guide those who want to //! While Pinnacle is not a library, this documentation serves to guide those who want to
//! contribute or learn how building something like this works. //! contribute or learn how building something like this works.
#![deny(unused_imports)] // gonna force myself to keep stuff clean // #![deny(unused_imports)] // gonna force myself to keep stuff clean
#![warn(clippy::unwrap_used)] #![warn(clippy::unwrap_used)]
mod api; mod api;

View file

@ -159,7 +159,7 @@ impl<B: Backend> State<B> {
.element_location(&window) .element_location(&window)
.unwrap_or((0, 0).into()); .unwrap_or((0, 0).into());
let window_size = window.geometry().size; let window_size = window.geometry().size;
window.request_size_change(window_loc, window_size); window.request_size_change(self, window_loc, window_size);
} }
Msg::MoveWindowToTag { window_id, tag_id } => { Msg::MoveWindowToTag { window_id, tag_id } => {
let Some(window) = window_id.window(self) else { return }; let Some(window) = window_id.window(self) else { return };
@ -623,11 +623,6 @@ impl<B: Backend> State<B> {
.any(|tag| tag.output(self).is_some_and(|op| &op == output)) .any(|tag| tag.output(self).is_some_and(|op| &op == output))
}) })
}) })
.filter(|win| match win {
WindowElement::Wayland(win) => !win.with_state(|state| state.minimized),
WindowElement::X11(surf) => !surf.is_minimized(),
})
.filter(|win| win.alive())
.cloned() .cloned()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let (render, do_not_render) = output.with_state(|state| { let (render, do_not_render) = output.with_state(|state| {
@ -636,7 +631,7 @@ impl<B: Backend> State<B> {
first_tag.layout().layout( first_tag.layout().layout(
self.windows.clone(), self.windows.clone(),
state.focused_tags().cloned().collect(), state.focused_tags().cloned().collect(),
&self.space, self,
output, output,
); );
} }
@ -656,11 +651,22 @@ impl<B: Backend> State<B> {
}) })
}); });
tracing::debug!(
"{} to render, {} to not render",
render.len(),
do_not_render.len()
);
let clone = render.clone(); let clone = render.clone();
self.loop_handle.insert_idle(|data| { self.loop_handle.insert_idle(|data| {
schedule_on_commit(data, clone, |dt| { schedule_on_commit(data, clone, |dt| {
for win in do_not_render { for win in do_not_render {
dt.state.space.unmap_elem(&win); dt.state.space.unmap_elem(&win);
if let WindowElement::X11(surface) = win {
if !surface.is_override_redirect() {
surface.set_mapped(false).expect("failed to unmap x11 win");
}
}
} }
}) })
}); });

View file

@ -181,7 +181,12 @@ impl WindowElement {
} }
/// Request a size and loc change. /// Request a size and loc change.
pub fn request_size_change(&self, new_loc: Point<i32, Logical>, new_size: Size<i32, Logical>) { pub fn request_size_change<B: Backend>(
&self,
state: &mut State<B>,
new_loc: Point<i32, Logical>,
new_size: Size<i32, Logical>,
) {
match self { match self {
WindowElement::Wayland(window) => { WindowElement::Wayland(window) => {
window.toplevel().with_pending_state(|state| { window.toplevel().with_pending_state(|state| {
@ -193,12 +198,25 @@ impl WindowElement {
}); });
} }
WindowElement::X11(surface) => { WindowElement::X11(surface) => {
tracing::debug!("sending size change to x11 win");
surface surface
.configure(Rectangle::from_loc_and_size(new_loc, new_size)) .configure(Rectangle::from_loc_and_size(new_loc, new_size))
.expect("failed to configure x11 win"); .expect("failed to configure x11 win");
self.with_state(|state| { // self.with_state(|state| {
state.resize_state = WindowResizeState::Acknowledged(new_loc); // state.resize_state = WindowResizeState::Acknowledged(new_loc);
}); // });
if !surface.is_override_redirect() {
surface.set_mapped(true).unwrap();
}
state.space.map_element(self.clone(), new_loc, false);
// if let Some(focused_output) = state.focus_state.focused_output.clone() {
// self.send_frame(
// &focused_output,
// state.clock.now(),
// Some(Duration::ZERO),
// surface_primary_scanout_output,
// );
// }
} }
} }
} }
@ -209,6 +227,22 @@ impl WindowElement {
pub fn output<B: Backend>(&self, state: &State<B>) -> Option<Output> { pub fn output<B: Backend>(&self, state: &State<B>) -> Option<Output> {
self.with_state(|st| st.tags.first().and_then(|tag| tag.output(state))) self.with_state(|st| st.tags.first().and_then(|tag| tag.output(state)))
} }
/// Returns `true` if the window element is [`Wayland`].
///
/// [`Wayland`]: WindowElement::Wayland
#[must_use]
pub fn is_wayland(&self) -> bool {
matches!(self, Self::Wayland(..))
}
/// Returns `true` if the window element is [`X11`].
///
/// [`X11`]: WindowElement::X11
#[must_use]
pub fn is_x11(&self) -> bool {
matches!(self, Self::X11(..))
}
} }
impl IsAlive for WindowElement { impl IsAlive for WindowElement {
@ -483,7 +517,7 @@ pub fn toggle_floating<B: Backend>(state: &mut State<B>, window: &WindowElement)
}); });
if let Some((prev_loc, prev_size)) = resize { if let Some((prev_loc, prev_size)) = resize {
window.request_size_change(prev_loc, prev_size); window.request_size_change(state, prev_loc, prev_size);
} }
let output = state.focus_state.focused_output.clone().unwrap(); let output = state.focus_state.focused_output.clone().unwrap();