mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
Add default-floating-position relative-to property
This commit is contained in:
+13
-1
@@ -1090,6 +1090,17 @@ pub struct FoIPosition {
|
||||
pub x: FloatOrInt<-65535, 65535>,
|
||||
#[knuffel(property)]
|
||||
pub y: FloatOrInt<-65535, 65535>,
|
||||
#[knuffel(property, default)]
|
||||
pub relative_to: RelativeTo,
|
||||
}
|
||||
|
||||
#[derive(knuffel::DecodeScalar, Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum RelativeTo {
|
||||
#[default]
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomLeft,
|
||||
BottomRight,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
@@ -3214,7 +3225,7 @@ mod tests {
|
||||
open-floating false
|
||||
open-focused true
|
||||
default-window-height { fixed 500; }
|
||||
default-floating-position x=100 y=-200
|
||||
default-floating-position x=100 y=-200 relative-to="bottom-left"
|
||||
|
||||
focus-ring {
|
||||
off
|
||||
@@ -3502,6 +3513,7 @@ mod tests {
|
||||
default_floating_position: Some(FoIPosition {
|
||||
x: FloatOrInt(100.),
|
||||
y: FloatOrInt(-200.),
|
||||
relative_to: RelativeTo::BottomLeft,
|
||||
}),
|
||||
focus_ring: BorderRule {
|
||||
off: true,
|
||||
|
||||
+23
-7
@@ -2,7 +2,7 @@ use std::cmp::max;
|
||||
use std::iter::zip;
|
||||
use std::rc::Rc;
|
||||
|
||||
use niri_config::PresetSize;
|
||||
use niri_config::{PresetSize, RelativeTo};
|
||||
use niri_ipc::{PositionChange, SizeChange};
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::utils::{Logical, Point, Rectangle, Scale, Serial, Size};
|
||||
@@ -415,12 +415,7 @@ impl<W: LayoutElement> FloatingSpace<W> {
|
||||
}
|
||||
}
|
||||
|
||||
let pos = tile.floating_pos.map(|pos| self.scale_by_working_area(pos));
|
||||
let pos = pos.or_else(|| {
|
||||
tile.default_floating_logical_pos()
|
||||
.map(|pos| pos + self.working_area.loc)
|
||||
});
|
||||
let pos = pos.unwrap_or_else(|| {
|
||||
let pos = self.stored_or_default_tile_pos(&tile).unwrap_or_else(|| {
|
||||
center_preferring_top_left_in_area(self.working_area, tile.tile_size())
|
||||
});
|
||||
|
||||
@@ -1191,6 +1186,27 @@ impl<W: LayoutElement> FloatingSpace<W> {
|
||||
Size::from((width, height))
|
||||
}
|
||||
|
||||
pub fn stored_or_default_tile_pos(&self, tile: &Tile<W>) -> Option<Point<f64, Logical>> {
|
||||
let pos = tile.floating_pos.map(|pos| self.scale_by_working_area(pos));
|
||||
pos.or_else(|| {
|
||||
tile.window().rules().default_floating_position.map(|pos| {
|
||||
let relative_to = pos.relative_to;
|
||||
let size = tile.tile_size();
|
||||
let area = self.working_area;
|
||||
|
||||
let mut pos = Point::from((pos.x.0, pos.y.0));
|
||||
if relative_to == RelativeTo::TopRight || relative_to == RelativeTo::BottomRight {
|
||||
pos.x = area.size.w - size.w - pos.x;
|
||||
}
|
||||
if relative_to == RelativeTo::BottomLeft || relative_to == RelativeTo::BottomRight {
|
||||
pos.y = area.size.h - size.h - pos.y;
|
||||
}
|
||||
|
||||
pos + self.working_area.loc
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn view_size(&self) -> Size<f64, Logical> {
|
||||
self.view_size
|
||||
|
||||
@@ -999,11 +999,6 @@ impl<W: LayoutElement> Tile<W> {
|
||||
&self.options
|
||||
}
|
||||
|
||||
pub fn default_floating_logical_pos(&self) -> Option<Point<f64, Logical>> {
|
||||
let pos = self.window().rules().default_floating_position?;
|
||||
Some(Point::from((pos.x.0, pos.y.0)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn view_size(&self) -> Size<f64, Logical> {
|
||||
self.view_size
|
||||
|
||||
+3
-10
@@ -1143,9 +1143,8 @@ impl<W: LayoutElement> Workspace<W> {
|
||||
removed.tile.stop_move_animations();
|
||||
|
||||
// Come up with a default floating position close to the tile position.
|
||||
if removed.tile.floating_pos.is_none()
|
||||
&& removed.tile.default_floating_logical_pos().is_none()
|
||||
{
|
||||
let stored_or_default = self.floating.stored_or_default_tile_pos(&removed.tile);
|
||||
if stored_or_default.is_none() {
|
||||
let offset = if self.options.center_focused_column == CenterFocusedColumn::Always {
|
||||
Point::from((0., 0.))
|
||||
} else {
|
||||
@@ -1236,13 +1235,7 @@ impl<W: LayoutElement> Workspace<W> {
|
||||
};
|
||||
|
||||
let working_area_loc = self.floating.working_area().loc;
|
||||
let pos = tile
|
||||
.floating_pos
|
||||
.map(|pos| self.floating.scale_by_working_area(pos));
|
||||
let pos = pos.or_else(|| {
|
||||
tile.default_floating_logical_pos()
|
||||
.map(|pos| pos + working_area_loc)
|
||||
});
|
||||
let pos = self.floating.stored_or_default_tile_pos(tile);
|
||||
|
||||
// If there's no stored floating position, we can only set both components at once, not
|
||||
// adjust.
|
||||
|
||||
@@ -52,7 +52,7 @@ window-rule {
|
||||
block-out-from "screencast"
|
||||
// block-out-from "screen-capture"
|
||||
variable-refresh-rate true
|
||||
default-floating-position x=100 y=200
|
||||
default-floating-position x=100 y=200 relative-to="bottom-left"
|
||||
|
||||
focus-ring {
|
||||
// off
|
||||
@@ -523,15 +523,22 @@ Afterward, the window will remember its last floating position.
|
||||
By default, new floating windows open at the center of the screen, and windows from the tiling layout open close to their visual screen position.
|
||||
|
||||
The position uses logical coordinates relative to the working area.
|
||||
By default, they are relative to the top-left corner of the working area, but you can change this by setting `relative-to` to one of these values: `top-left`, `top-right`, `bottom-left`, `bottom-right`.
|
||||
|
||||
For example, if you have a bar at the top, then `x=0 y=0` will put the top-left corner of the window directly below the bar.
|
||||
If instead you write `x=0 y=0 relative-to="top-right"`, then the top-right corner of the window will align with the top-right corner of the workspace, also directly below the bar.
|
||||
|
||||
The coordinates change direction based on `relative-to`.
|
||||
For example, by default (top-left), `x=100 y=200` will put the window 100 pixels to the right and 200 pixels down from the top-left corner.
|
||||
If you use `x=100 y=200 relative-to="bottom-left"`, it will put the window 100 pixels to the right and 200 pixels *up* from the bottom-left corner.
|
||||
|
||||
```kdl
|
||||
// Open the Firefox picture-in-picture window at the top-left corner of the screen
|
||||
// Open the Firefox picture-in-picture window at the bottom-left corner of the screen
|
||||
// with a small gap.
|
||||
window-rule {
|
||||
match app-id="firefox$" title="^Picture-in-Picture$"
|
||||
|
||||
default-floating-position x=32 y=32
|
||||
default-floating-position x=32 y=32 relative-to="bottom-left"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user