xwm: More fixes

This commit is contained in:
Victoria Brekenfeld 2023-01-23 18:25:01 +01:00
parent 1d28574088
commit 9b1221edc5
14 changed files with 311 additions and 80 deletions

View file

@ -332,10 +332,10 @@ impl CosmicMapped {
window.is_activated()
}
pub fn set_size(&self, size: Size<i32, Logical>) {
pub fn set_geometry(&self, geo: Rectangle<i32, Logical>) {
match &self.element {
CosmicMappedInternal::Stack(s) => s.set_size(size),
CosmicMappedInternal::Window(w) => w.set_size(size),
CosmicMappedInternal::Stack(s) => s.set_geometry(geo),
CosmicMappedInternal::Window(w) => w.set_geometry(geo),
_ => {}
}
}

View file

@ -150,15 +150,16 @@ impl CosmicStack {
Point::from((0, TAB_HEIGHT))
}
pub fn set_size(&self, size: Size<i32, Logical>) {
pub fn set_geometry(&self, geo: Rectangle<i32, Logical>) {
self.0.with_program(|p| {
let surface_size = (size.w, size.h - TAB_HEIGHT).into();
let loc = (geo.loc.x, geo.loc.y + TAB_HEIGHT);
let size = (geo.size.w, geo.size.h - TAB_HEIGHT);
for window in p.windows.lock().unwrap().iter() {
window.set_size(surface_size);
window.set_geometry(Rectangle::from_loc_and_size(loc, size));
}
});
self.0.resize(Size::from((size.w, TAB_HEIGHT)));
self.0.resize(Size::from((geo.size.w, TAB_HEIGHT)));
}
fn keyboard_leave_if_previous(

View file

@ -102,14 +102,13 @@ impl CosmicSurface {
}
}
pub fn set_size(&self, size: Size<i32, Logical>) {
pub fn set_geometry(&self, geo: Rectangle<i32, Logical>) {
match self {
CosmicSurface::Wayland(window) => window
.toplevel()
.with_pending_state(|state| state.size = Some(size)),
.with_pending_state(|state| state.size = Some(geo.size)),
CosmicSurface::X11(surface) => {
let rect = Rectangle::from_loc_and_size(surface.geometry().loc, size);
let _ = surface.configure(rect);
let _ = surface.configure(geo);
}
_ => {}
}
@ -296,6 +295,13 @@ impl CosmicSurface {
CosmicSurface::X11(surface) => surface.min_size(),
_ => unreachable!(),
}
.map(|size| {
if self.is_decorated() {
size + (0, SSD_HEIGHT).into()
} else {
size
}
})
}
pub fn max_size(&self) -> Option<Size<i32, Logical>> {
@ -315,6 +321,13 @@ impl CosmicSurface {
CosmicSurface::X11(surface) => surface.max_size(),
_ => unreachable!(),
}
.map(|size| {
if self.is_decorated() {
size + (0, SSD_HEIGHT).into()
} else {
size
}
})
}
pub fn send_configure(&self) {

View file

@ -120,12 +120,20 @@ impl CosmicWindow {
))
}
pub fn set_size(&self, size: Size<i32, Logical>) {
pub fn set_geometry(&self, geo: Rectangle<i32, Logical>) {
self.0.with_program(|p| {
let surface_size = (size.w, size.h - if p.has_ssd() { SSD_HEIGHT } else { 0 }).into();
p.window.set_size(surface_size)
let loc = (
geo.loc.x,
geo.loc.y + if p.has_ssd() { SSD_HEIGHT } else { 0 },
);
let size = (
geo.size.w,
geo.size.h - if p.has_ssd() { SSD_HEIGHT } else { 0 },
);
p.window
.set_geometry(Rectangle::from_loc_and_size(loc, size));
});
self.0.resize(Size::from((size.w, SSD_HEIGHT)));
self.0.resize(Size::from((geo.size.w, SSD_HEIGHT)));
}
pub fn surface(&self) -> CosmicSurface {
@ -264,6 +272,7 @@ impl SpaceElement for CosmicWindow {
self.0.with_program(|p| {
let mut bbox = SpaceElement::bbox(&p.window);
if p.has_ssd() {
bbox.loc.y -= SSD_HEIGHT;
bbox.size.h += SSD_HEIGHT;
}
bbox
@ -301,6 +310,7 @@ impl SpaceElement for CosmicWindow {
self.0.with_program(|p| {
let mut geo = SpaceElement::geometry(&p.window);
if p.has_ssd() {
geo.loc.y -= SSD_HEIGHT;
geo.size.h += SSD_HEIGHT;
}
geo

View file

@ -23,7 +23,7 @@ use smithay::{
Seat,
},
output::Output,
utils::{IsAlive, Logical, Point, Serial},
utils::{IsAlive, Logical, Point, Rectangle, Serial},
};
use std::cell::RefCell;
@ -183,6 +183,10 @@ impl MoveSurfaceGrab {
.output_geometry(&output)
.unwrap()
.loc;
grab_state.window.set_geometry(Rectangle::from_loc_and_size(
window_location + offset,
grab_state.window.geometry().size,
));
state
.common
.shell

View file

@ -12,7 +12,7 @@ use smithay::{
AxisFrame, ButtonEvent, GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab,
PointerInnerHandle,
},
utils::{IsAlive, Logical, Point, Size},
utils::{IsAlive, Logical, Point, Rectangle, Size},
};
/// Information about the resize operation.
@ -97,7 +97,10 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
self.last_window_size = (new_window_width, new_window_height).into();
self.window.set_resizing(true);
self.window.set_size(self.last_window_size);
self.window.set_geometry(Rectangle::from_loc_and_size(
self.window.geometry().loc,
self.last_window_size,
));
self.window.configure();
}
@ -118,7 +121,10 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
}
self.window.set_resizing(false);
self.window.set_size(self.last_window_size);
self.window.set_geometry(Rectangle::from_loc_and_size(
self.window.geometry().loc,
self.last_window_size,
));
self.window.configure();
let mut resize_state = self.window.resize_state.lock().unwrap();
@ -220,6 +226,9 @@ impl ResizeSurfaceGrab {
);
}
}
let mut geometry = window.geometry();
geometry.loc = new_location;
let _ = window.set_geometry(geometry);
space
.floating_layer
.space

View file

@ -75,9 +75,7 @@ impl FloatingLayout {
let geometry = layers.non_exclusive_zone();
let last_geometry = mapped.last_geometry.lock().unwrap().clone();
let mut geo_updated = false;
if let Some(size) = last_geometry.map(|g| g.size) {
geo_updated = win_geo.size != size;
win_geo.size = size;
}
{
@ -98,7 +96,6 @@ impl FloatingLayout {
}
// but no matter the supported sizes, don't be larger than our non-exclusive-zone
win_geo.size.w = std::cmp::min(width, geometry.size.w);
geo_updated = true;
}
if win_geo.size.h > geometry.size.h / 3 * 2 {
// try a more reasonable size
@ -113,7 +110,6 @@ impl FloatingLayout {
}
// but no matter the supported sizes, don't be larger than our non-exclusive-zone
win_geo.size.h = std::cmp::min(height, geometry.size.h);
geo_updated = true;
}
}
@ -128,11 +124,8 @@ impl FloatingLayout {
});
mapped.set_tiled(false);
if geo_updated {
mapped.set_size(win_geo.size);
}
mapped.set_geometry(Rectangle::from_loc_and_size(position, win_geo.size));
mapped.configure();
self.space.map_element(mapped, position, false);
}
@ -183,8 +176,8 @@ impl FloatingLayout {
if let Some(mapped) = maybe_mapped {
let last_geometry = mapped.last_geometry.lock().unwrap().clone();
let last_size = last_geometry.map(|g| g.size).expect("No previous size?");
mapped.set_size(last_size);
let last_location = last_geometry.map(|g| g.loc).expect("No previous location?");
mapped.set_geometry(Rectangle::from_loc_and_size(last_location, last_size));
self.space.map_element(mapped, last_location, true);
Some(last_size)
} else {
@ -293,6 +286,7 @@ impl FloatingLayout {
.get(&output)
.copied()
.unwrap_or_else(|| (0, 0).into());
element.set_geometry(elem_geo);
self.space.map_element(element.clone(), elem_geo.loc, false);
}
self.refresh(); //fixup any out of bounds elements

View file

@ -44,6 +44,7 @@ lazy_static::lazy_static! {
r"update-manager",
r"Solaar",
r"Steam",
r"",
r"TelegramDesktop",
r"Zotero",
r"gjs",
@ -77,6 +78,7 @@ lazy_static::lazy_static! {
r"Software Updater",
r".*",
r"^.*?(Guard|Login).*",
r"Steam",
r"Media viewer",
r"Quick Format Citation",
r".*",

View file

@ -1129,14 +1129,17 @@ impl TilingLayout {
data.update_geometry(geo);
}
Data::Mapped { mapped, .. } => {
geo.loc += (inner, inner).into();
if !(mapped.is_fullscreen() || mapped.is_maximized()) {
mapped.set_tiled(true);
mapped.set_size(
(geo.size.w - inner * 2, geo.size.h - inner * 2).into(),
);
mapped.configure();
let size = (geo.size.w - inner * 2, geo.size.h - inner * 2);
let internal_geometry =
Rectangle::from_loc_and_size(geo.loc, size);
if mapped.geometry() != internal_geometry {
mapped.set_geometry(internal_geometry);
mapped.configure();
}
}
geo.loc += (inner, inner).into();
data.update_geometry(geo);
}
}

View file

@ -3,16 +3,14 @@ use std::{cell::RefCell, collections::HashMap};
use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::State as WState;
use smithay::{
backend::renderer::element::Id,
desktop::{layer_map_for_output, LayerSurface, PopupManager, WindowSurfaceType},
input::{
pointer::{Focus, GrabStartData as PointerGrabStartData},
Seat,
},
output::Output,
reexports::{
wayland_server::{protocol::wl_surface::WlSurface, DisplayHandle},
x11rb::protocol::xproto::Window as X11Window,
},
reexports::wayland_server::{protocol::wl_surface::WlSurface, DisplayHandle},
utils::{Logical, Point, Rectangle, Serial, SERIAL_COUNTER},
wayland::{
compositor::with_states,
@ -71,9 +69,17 @@ pub struct Shell {
pub workspace_state: WorkspaceState<State>,
}
#[derive(Debug)]
pub struct OverrideRedirectWindow {
pub surface: X11Surface,
pub above: Option<X11Window>,
pub above: Ordering,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Ordering {
Above,
AboveWindow(Id),
Below,
}
#[derive(Debug)]
@ -837,12 +843,25 @@ impl Shell {
Some(output) => {
Box::new(std::iter::once(output.clone())) as Box<dyn Iterator<Item = Output>>
}
None => Box::new(self.outputs().map(|o| self.active_space(o)).flat_map(|w| {
w.mapped()
.find(|e| e.has_surface(surface, WindowSurfaceType::ALL))
.into_iter()
.flat_map(|e| w.outputs_for_element(e))
})),
None => Box::new(
self.outputs()
.filter(|o| {
self.override_redirect_windows.iter().any(|or| {
if or.surface.wl_surface().as_ref() == Some(surface) {
or.surface.geometry().intersection(o.geometry()).is_some()
} else {
false
}
})
})
.cloned()
.chain(self.outputs().map(|o| self.active_space(o)).flat_map(|w| {
w.mapped()
.find(|e| e.has_surface(surface, WindowSurfaceType::ALL))
.into_iter()
.flat_map(|e| w.outputs_for_element(e))
})),
),
}
}
@ -975,6 +994,9 @@ impl Shell {
map.cleanup();
}
self.override_redirect_windows
.retain(|or| or.surface.alive());
self.toplevel_info_state
.refresh(Some(&self.workspace_state));
}
@ -1019,10 +1041,6 @@ impl Shell {
}
if let CosmicSurface::X11(surface) = window {
let geometry = workspace.element_geometry(&mapped);
if let Err(err) = surface.configure(geometry) {
slog_scope::warn!("Failed to configure X11 surface ({:?}): {}", surface, err);
};
if let Some(xwm) = state
.common
.xwayland_state
@ -1062,7 +1080,7 @@ impl Shell {
.override_redirect_windows
.push(OverrideRedirectWindow {
surface: window,
above: None,
above: Ordering::Above,
});
}

View file

@ -34,7 +34,7 @@ use super::{
element::CosmicMapped,
focus::{FocusStack, FocusStackMut},
grabs::{ResizeEdge, ResizeGrab},
CosmicMappedRenderElement, CosmicSurface,
CosmicMappedRenderElement, CosmicSurface, Ordering,
};
#[derive(Debug)]
@ -232,15 +232,14 @@ impl Workspace {
mapped.set_active(window);
}
window.set_size(
output
.current_mode()
.map(|m| m.size)
.unwrap_or((0, 0).into())
.to_f64()
.to_logical(output.current_scale().fractional_scale())
.to_i32_round(),
);
let size = output
.current_mode()
.map(|m| m.size)
.unwrap_or((0, 0).into())
.to_f64()
.to_logical(output.current_scale().fractional_scale())
.to_i32_round();
window.set_geometry(Rectangle::from_loc_and_size((0, 0), size));
window.send_configure();
self.fullscreen.insert(output.clone(), window.clone());
}
@ -397,6 +396,7 @@ impl Workspace {
&self,
renderer: &mut R,
output: &Output,
override_redirect_windows: &[super::OverrideRedirectWindow],
) -> Result<Vec<WorkspaceRenderElement<R>>, OutputNotMapped>
where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
@ -469,8 +469,33 @@ impl Workspace {
lower
};
let mut window_elements = Vec::new();
// OR windows above all
window_elements.extend(
override_redirect_windows
.iter()
.filter(|or| {
or.above == Ordering::Above
&& or
.surface
.geometry()
.intersection(output.geometry())
.is_some()
})
.flat_map(|or| {
AsRenderElements::<R>::render_elements::<WorkspaceRenderElement<R>>(
&or.surface,
renderer,
(or.surface.geometry().loc - output.geometry().loc)
.to_physical_precise_round(output_scale),
Scale::from(output_scale),
)
}),
);
// floating surfaces
render_elements.extend(
window_elements.extend(
self.floating_layer
.render_output::<R>(renderer, output)?
.into_iter()
@ -478,13 +503,64 @@ impl Workspace {
);
//tiling surfaces
render_elements.extend(
window_elements.extend(
self.tiling_layer
.render_output::<R>(renderer, output)?
.into_iter()
.map(WorkspaceRenderElement::from),
);
// Sort other OR windows in between
for or in override_redirect_windows.iter().filter(|or| {
matches!(or.above, Ordering::AboveWindow(_))
&& or
.surface
.geometry()
.intersection(output.geometry())
.is_some()
}) {
let pos = window_elements
.iter()
.position(|w| Ordering::AboveWindow(w.id().clone()) == or.above)
.unwrap_or(0);
for element in AsRenderElements::<R>::render_elements::<WorkspaceRenderElement<R>>(
&or.surface,
renderer,
(or.surface.geometry().loc - output.geometry().loc)
.to_physical_precise_round(output_scale),
Scale::from(output_scale),
)
.into_iter()
.rev()
{
window_elements.insert(pos, element);
}
}
render_elements.extend(window_elements.into_iter());
// OR windows below all
render_elements.extend(
override_redirect_windows
.iter()
.filter(|or| {
or.above == Ordering::Below
&& or
.surface
.geometry()
.intersection(output.geometry())
.is_some()
})
.flat_map(|or| {
AsRenderElements::<R>::render_elements::<WorkspaceRenderElement<R>>(
&or.surface,
renderer,
(or.surface.geometry().loc - output.geometry().loc)
.to_physical_precise_round(output_scale),
Scale::from(output_scale),
)
}),
);
// bottom and background layer surfaces
{
render_elements.extend(