Commit 406db966344c
tarball3 files changed+52-25
@@ -647,6 +647,14 @@ impl Layout {
647647
merged648648
}649649
650
+ /// Whether a tiled window is extended over others sharing its container.651
+ pub fn grouped(&self, w: WindowId) -> bool {652
+ let Some(o) = self.windows.get(w).and_then(|w| w.output) else {653
+ return false;654
+ };655
+ self.outputs[o].tree.grouped(w, self.vis_on(o))656
+ }657
+650658
/// Whether another window is extended over the tiled window `w`, which651659
/// leaves it no room and takes it out of reach of focus.652660
pub fn eclipsed(&self, w: WindowId) -> bool {@@ -193,11 +193,24 @@ pub fn build(
193193
deco.unfocused.0194194
};195195
let alpha = effect.map_or(1.0, |e| e.progress) * opacity;196
- let borders = &mut state.borders;197
- let first = out.len();198
- border_elements(&mut out, borders, r, deco, color, alpha, scale);199
- if let Some(clip) = clip {200
- ring_borders(&mut out, first, clip, border_width(deco, scale));196
+ let b = border_width(deco, scale);197
+ let radius = deco.radius.0.into_iter().max().unwrap_or(0);198
+ let radius = (f64::from(radius) * scale).round() as i32;199
+ let rings = if layout.grouped(id) { 2 } else { 1 };200
+ let Some((at, size)) = pixels(r, scale) else {201
+ continue;202
+ };203
+ let window = Rectangle::new(at.into(), size.into());204
+ for (k, borders) in state.borders.iter_mut().take(rings).enumerate() {205
+ let by = 2 * b * k as i32;206
+ let frame = outset_rect(window, by);207
+ let reach = if radius > 0 { radius + by } else { 0 };208
+ let reach = reach.min(frame.size.w / 2).min(frame.size.h / 2);209
+ let first = out.len();210
+ border_elements(&mut out, borders, frame, b, reach, color, alpha);211
+ if let Some(clip) = clip {212
+ ring_borders(&mut out, first, outset(clip, by), b);213
+ }201214
}202215
}203216
}@@ -342,24 +355,19 @@ fn window_elements(
342355
);343356
}344357
345
-/// Four strips just outside `r`, in the gap, so the client keeps its size.346
-/// With rounded corners they reach in by the largest radius, to cover the347
-/// band the ring curves through inside the window's corners.358
+/// Four strips `b` wide just outside `frame`, in the gap, so the client keeps359
+/// its size. With rounded corners they `reach` in by the largest radius, to360
+/// cover the band the ring curves through inside the frame's corners.348361
fn border_elements(349362
out: &mut Vec<Draw>,350363
borders: &mut Option<[SolidColorBuffer; 4]>,351
- r: Rect,352
- deco: &Decoration,364
+ frame: Rectangle<i32, Physical>,365
+ b: i32,366
+ reach: i32,353367
color: [f32; 4],354368
alpha: f32,355
- scale: f64,356369
) {357
- let Some(((x, y), (w, h))) = pixels(r, scale) else {358
- return;359
- };360
- let b = border_width(deco, scale);361
- let reach = (f64::from(deco.radius.0.into_iter().max().unwrap_or(0)) * scale).round() as i32;362
- let reach = reach.min(w / 2).min(h / 2);370
+ let (x, y, w, h) = (frame.loc.x, frame.loc.y, frame.size.w, frame.size.h);363371
let strips = [364372
((x - b, y - b), (w + 2 * b, b + reach)),365373
((x - b, y + h - reach), (w + 2 * b, b + reach)),@@ -662,20 +670,31 @@ fn clip_window(out: &mut [Draw], first: usize, clip: Clip) {
662670
/// Turns the border strips from `first` on into a ring around the window's663671
/// rounded outline.664672
fn ring_borders(out: &mut [Draw], first: usize, window: Clip, b: i32) {665
- let grow = |r: f32| if r > 0.0 { r + b as f32 } else { 0.0 };666673
let ring = Clip {667
- rect: Rectangle::new(668
- window.rect.loc - Point::from((b, b)),669
- window.rect.size + Size::from((2 * b, 2 * b)),670
- ),671
- radii: window.radii.map(grow),672674
ring: b as f32,675
+ ..outset(window, b)673676
};674677
for draw in &mut out[first..] {675678
wrap(draw, ring);676679
}677680
}678681
682
+fn outset(clip: Clip, by: i32) -> Clip {683
+ let grow = |r: f32| if r > 0.0 { r + by as f32 } else { 0.0 };684
+ Clip {685
+ rect: outset_rect(clip.rect, by),686
+ radii: clip.radii.map(grow),687
+ ring: clip.ring,688
+ }689
+}690
+691
+fn outset_rect(r: Rectangle<i32, Physical>, by: i32) -> Rectangle<i32, Physical> {692
+ Rectangle::new(693
+ r.loc - Point::from((by, by)),694
+ r.size + Size::from((2 * by, 2 * by)),695
+ )696
+}697
+679698
fn wrap(draw: &mut Draw, clip: Clip) {680699
let inner = std::mem::replace(draw, Draw::Clipped(ClipElement::empty()));681700
*draw = Draw::Clipped(ClipElement::new(inner, clip));@@ -99,7 +99,7 @@ pub struct WindowState {
9999
/// A rule sent it somewhere, so activation tokens leave it alone.100100
pub placed_by_rule: bool,101101
pub list_handle: Option<ForeignToplevelHandle>,102
- pub borders: Option<[SolidColorBuffer; 4]>,102
+ pub borders: [Option<[SolidColorBuffer; 4]>; 2],103103
pub app_id: String,104104
pub title: String,105105
/// The title it mapped with, which `initial_title` rules match.@@ -172,7 +172,7 @@ impl Wm {
172172
reclassify: false,173173
placed_by_rule,174174
list_handle: None,175
- borders: None,175
+ borders: [None, None],176176
app_id,177177
initial_title: title.clone(),178178
title,