aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2023-12-28 08:45:12 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-12-28 08:45:12 +0400
commitb13892ca637cccfb496e3204b2793c069af17ccb (patch)
tree751ba2381c595baae1296eb8cbd5889418541b10 /src
parent777ad4ee5c8cf84b2bfa13c6bdb0d254c24881f9 (diff)
downloadniri-b13892ca637cccfb496e3204b2793c069af17ccb.tar.gz
niri-b13892ca637cccfb496e3204b2793c069af17ccb.tar.bz2
niri-b13892ca637cccfb496e3204b2793c069af17ccb.zip
Activate windows when clicking on the border
Diffstat (limited to 'src')
-rw-r--r--src/layout/mod.rs9
-rw-r--r--src/layout/monitor.rs4
-rw-r--r--src/layout/tile.rs7
-rw-r--r--src/layout/workspace.rs21
-rw-r--r--src/niri.rs9
5 files changed, 41 insertions, 9 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 484a377a..1a9b5076 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -920,11 +920,18 @@ impl<W: LayoutElement> Layout<W> {
monitors[*active_monitor_idx].focus()
}
+ /// Returns the window under the cursor and the position of its toplevel surface within the
+ /// output.
+ ///
+ /// `Some((w, Some(p)))` means that the cursor is within the window's input region and can be
+ /// used for delivering events to the window. `Some((w, None))` means that the cursor is within
+ /// the window's activation region, but not within the window's input region. For example, the
+ /// cursor may be on the window's server-side border.
pub fn window_under(
&self,
output: &Output,
pos_within_output: Point<f64, Logical>,
- ) -> Option<(&W, Point<i32, Logical>)> {
+ ) -> Option<(&W, Option<Point<i32, Logical>>)> {
let MonitorSet::Normal { monitors, .. } = &self.monitor_set else {
return None;
};
diff --git a/src/layout/monitor.rs b/src/layout/monitor.rs
index aefbf29f..aa4c439e 100644
--- a/src/layout/monitor.rs
+++ b/src/layout/monitor.rs
@@ -450,7 +450,7 @@ impl<W: LayoutElement> Monitor<W> {
pub fn window_under(
&self,
pos_within_output: Point<f64, Logical>,
- ) -> Option<(&W, Point<i32, Logical>)> {
+ ) -> Option<(&W, Option<Point<i32, Logical>>)> {
match &self.workspace_switch {
Some(switch) => {
let size = output_size(&self.output);
@@ -469,7 +469,7 @@ impl<W: LayoutElement> Monitor<W> {
let ws = &self.workspaces[idx];
let (win, win_pos) = ws.window_under(pos_within_output + ws_offset.to_f64())?;
- Some((win, win_pos - ws_offset))
+ Some((win, win_pos.map(|p| p - ws_offset)))
}
None => {
let ws = &self.workspaces[self.active_workspace_idx];
diff --git a/src/layout/tile.rs b/src/layout/tile.rs
index 56af4fa4..ea8515af 100644
--- a/src/layout/tile.rs
+++ b/src/layout/tile.rs
@@ -6,7 +6,7 @@ use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRen
use smithay::backend::renderer::element::utils::{Relocate, RelocateRenderElement};
use smithay::backend::renderer::element::Kind;
use smithay::backend::renderer::{ImportAll, Renderer};
-use smithay::utils::{Logical, Point, Scale, Size};
+use smithay::utils::{Logical, Point, Rectangle, Scale, Size};
use super::focus_ring::FocusRing;
use super::workspace::WorkspaceRenderElement;
@@ -150,6 +150,11 @@ impl<W: LayoutElement> Tile<W> {
self.window.is_in_input_region(point)
}
+ pub fn is_in_activation_region(&self, point: Point<f64, Logical>) -> bool {
+ let activation_region = Rectangle::from_loc_and_size((0, 0), self.tile_size());
+ activation_region.to_f64().contains(point)
+ }
+
pub fn request_tile_size(&mut self, mut size: Size<i32, Logical>) {
// Can't go through effective_border_width() because we might be fullscreen.
if !self.border.is_off() {
diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs
index 32302187..090e27dd 100644
--- a/src/layout/workspace.rs
+++ b/src/layout/workspace.rs
@@ -761,7 +761,10 @@ impl<W: LayoutElement> Workspace<W> {
self.column_x(self.active_column_idx) + self.view_offset
}
- pub fn window_under(&self, pos: Point<f64, Logical>) -> Option<(&W, Point<i32, Logical>)> {
+ pub fn window_under(
+ &self,
+ pos: Point<f64, Logical>,
+ ) -> Option<(&W, Option<Point<i32, Logical>>)> {
if self.columns.is_empty() {
return None;
}
@@ -775,8 +778,12 @@ impl<W: LayoutElement> Workspace<W> {
self.column_x(self.active_column_idx) - view_pos,
col.tile_y(col.active_tile_idx),
));
- if active_tile.is_in_input_region(pos - tile_pos.to_f64()) {
- return Some((active_tile.window(), tile_pos + active_tile.buf_loc()));
+ let pos_within_tile = pos - tile_pos.to_f64();
+ if active_tile.is_in_input_region(pos_within_tile) {
+ let pos_within_surface = tile_pos + active_tile.buf_loc();
+ return Some((active_tile.window(), Some(pos_within_surface)));
+ } else if active_tile.is_in_activation_region(pos_within_tile) {
+ return Some((active_tile.window(), None));
}
let mut x = -view_pos;
@@ -788,8 +795,12 @@ impl<W: LayoutElement> Workspace<W> {
}
let tile_pos = Point::from((x, y));
- if tile.is_in_input_region(pos - tile_pos.to_f64()) {
- return Some((tile.window(), tile_pos + tile.buf_loc()));
+ let pos_within_tile = pos - tile_pos.to_f64();
+ if tile.is_in_input_region(pos_within_tile) {
+ let pos_within_surface = tile_pos + tile.buf_loc();
+ return Some((tile.window(), Some(pos_within_surface)));
+ } else if tile.is_in_activation_region(pos_within_tile) {
+ return Some((tile.window(), None));
}
}
diff --git a/src/niri.rs b/src/niri.rs
index a0a98c90..3a3a4f4d 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -1035,6 +1035,10 @@ impl Niri {
Some((output, pos_within_output))
}
+ /// Returns the window under the position to be activated.
+ ///
+ /// The cursor may be inside the window's activation region, but not within the window's input
+ /// region.
pub fn window_under(&self, pos: Point<f64, Logical>) -> Option<&Window> {
if self.is_locked() || self.screenshot_ui.is_open() {
return None;
@@ -1045,6 +1049,10 @@ impl Niri {
Some(window)
}
+ /// Returns the window under the cursor to be activated.
+ ///
+ /// The cursor may be inside the window's activation region, but not within the window's input
+ /// region.
pub fn window_under_cursor(&self) -> Option<&Window> {
let pos = self.seat.get_pointer().unwrap().current_location();
self.window_under(pos)
@@ -1103,6 +1111,7 @@ impl Niri {
self.layout
.window_under(output, pos_within_output)
.and_then(|(window, win_pos_within_output)| {
+ let win_pos_within_output = win_pos_within_output?;
window
.surface_under(
pos_within_output - win_pos_within_output.to_f64(),