Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,17 @@ impl HitType {
.map(|hit| (tile.window(), hit.offset_win_pos(tile_pos)))
}

/// Like `hit_tile()`, but clipped to the tile's activation region.
pub fn hit_tile_within_activation_region<W: LayoutElement>(
tile: &Tile<W>,
tile_pos: Point<f64, Logical>,
point: Point<f64, Logical>,
) -> Option<(&W, Self)> {
let pos_within_tile = point - tile_pos;
tile.hit_within_activation_region(pos_within_tile)
.map(|hit| (tile.window(), hit.offset_win_pos(tile_pos)))
}

pub fn to_activate(self) -> Self {
match self {
HitType::Input { .. } => HitType::Activate {
Expand Down
25 changes: 25 additions & 0 deletions src/layout/scrolling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2998,6 +2998,31 @@ impl<W: LayoutElement> ScrollingSpace<W> {
// Round to physical pixels.
let tile_pos = tile_pos.to_physical_precise_round(scale).to_logical(scale);

// Prefer hits within the activation region so CSD shadows can't steal
// hits from adjacent tiles (e.g. peeking columns in strut zones).
if let Some(rv) =
HitType::hit_tile_within_activation_region(tile, tile_pos, pos)
{
return Some(rv);
}
}
}

// Fall back to CSD input regions extending beyond tile bounds (shadows, resize
// handles, GTK 3 subsurface popups) so normal pointer input still reaches them.
for (col, col_x) in self.columns_in_render_order() {
let col_off = Point::from((col_x, 0.));
let col_render_off = col.render_offset();

for (tile, tile_off, visible) in col.tiles_in_render_order() {
if !visible {
continue;
}

let tile_pos =
view_off + col_off + col_render_off + tile_off + tile.render_offset();
let tile_pos = tile_pos.to_physical_precise_round(scale).to_logical(scale);

if let Some(rv) = HitType::hit_tile(tile, tile_pos, pos) {
return Some(rv);
}
Expand Down
21 changes: 21 additions & 0 deletions src/layout/tile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,27 @@ impl<W: LayoutElement> Tile<W> {
activation_region.contains(point)
}

/// Like `hit()`, but only returns a result if the point is within the tile's activation
/// region (i.e. within tile bounds). This prevents CSD input regions (shadows, resize handles)
/// from claiming hits outside the tile.
pub fn hit_within_activation_region(&self, point: Point<f64, Logical>) -> Option<HitType> {
let offset = self.bob_offset();
let point = point - offset;

if self.is_in_activation_region(point) {
if self.is_in_input_region(point) {
let win_pos = self.buf_loc() + offset;
Some(HitType::Input { win_pos })
} else {
Some(HitType::Activate {
is_tab_indicator: false,
})
}
} else {
None
}
}

pub fn hit(&self, point: Point<f64, Logical>) -> Option<HitType> {
let offset = self.bob_offset();
let point = point - offset;
Expand Down
2 changes: 1 addition & 1 deletion src/layout/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1768,7 +1768,7 @@ impl<W: LayoutElement> Workspace<W> {

let pos_within_tile = pos - tile_pos;

if tile.hit(pos_within_tile).is_some() {
if tile.hit_within_activation_region(pos_within_tile).is_some() {
let size = tile.tile_size().to_f64();

let mut edges = ResizeEdge::empty();
Expand Down