Commit Graph

41 Commits

Author SHA1 Message Date
Ivan Molodetskikh fee8719299 Implement xray background effect 2026-04-15 14:35:14 +03:00
Ivan Molodetskikh dd1f28998f Bundle renderer and target into a RenderCtx 2026-04-15 14:35:14 +03:00
Ivan Molodetskikh 7f132ecf95 Refactor rendering to push-based instead of pull-based (#3113)
Our current rendering code constructs and returns complex
`-> impl Iterator<Item = SomeRenderElement>` types that are collected
into a vector at the top level Niri::render(). This causes some
problems:
- It's hard to write logic around returning iterators. Especially things
  like conditions, since the returned iterator must have a single type,
  you can't branch and return different iterators. This will be solved
  by gen fn but alas it's not here yet.
- In many cases, the returned `-> impl Iterator` will borrow from &self
  leading to complex lifetimes. In certain cases, it is also desirable
  for it to borrow the &mut NiriRenderer, which causes a lot of issues
  because it's exclusive (&mut).
- Sometimes those issues are too hard to deal with, leading to the
  escape hatch of allocating and returning a temporary
  Vec<SomeRenderElement>, like in
  Scrolling/FloatingSpace::render_elements(). These allocations are
  unfortunate because they are not really necessary.
- It's impossible to use some downstream combinators with this
  `-> impl Iterator` approach, leading to functions like Smithay's
  render_elements_from_surface_tree() returning a Vec. This is extra
  unfortunate because it results in a temporary allocation per Wayland
  toplevel/popup.
- It's hard to properly create profiling spans for the rendering
  functions since the spans are dropped when the (lazy) iterator is
  returned and not when all the code actually completes.
- The code compiles down to complex state machines in generated iterator
  types with logic located in Iterator::next(), which makes it annoying
  to follow in debuggers and profiling tools.

This refactor changes the code to push-based iteration: rendering
functions receive a push() closure that they call to push their render
elements. It solves all of the aforementioned problems:
- The logic becomes simpler. Just use conditionals and loops as normal.
- No borrowing and lifetimes since we're not returning anything.
- All temporary Vecs are removed because the problems they worked around
  no longer exist.
- The new push_elements_from_surface_tree() helper is the same as
  render_elements_from_surface_tree() but doesn't allocate a temporary
  Vec since it's not necessary; the push() closure can be passed down.
- Profiling spans work normally since the function returns when it ran
  all of the logic.
- The code compiles down to normal functions and calls as expected.

Generally, the iterator approach gives these advantages:
- You can wrap the returned items in the upstream logic. This is
  possible in exactly the same way with the push closure.
- You can decide to cut the iterator short in the upstream logic. This
  is not possible with push-based iteration, but we don't actually use
  it anywhere.

I chose the push closure type to be &mut dyn FnMut(SomeRenderElement).
It's deliberately not a generic impl FnMut() to avoid duplicating the
rendering logic when it's called from several different places. But it's
still a normal closure that can capture the outside context.

While my original idea for this refactor was to simplify the logic while
getting rid of temporary Vecs, it also appears to have brought a
consistent 2-3x speedup to the whole render list construction. On an old
Eee PC laptop I even observed a 8x speedup.

The refactor also results in smaller binary size, presumably due to
removing many iterator combinators and state tracking.
2025-12-25 14:26:19 +03:00
Ivan Molodetskikh e1fad994da Implement maximize-to-edges (true Wayland maximize) 2025-10-15 09:04:16 +03:00
Ivan Molodetskikh 09cf8402c3 Add per-output layout config 2025-10-02 09:33:08 +03:00
Ivan Molodetskikh a5e285865b Move background rendering to Workspace
Per-output background-color doesn't work yet.
2025-10-02 09:33:08 +03:00
Ivan Molodetskikh 4c524b4719 layout: Store Layout directly in Options 2025-10-02 09:33:08 +03:00
Ivan Molodetskikh 1fa9dd32ed config: Split Layout from LayoutPart 2025-10-02 09:33:08 +03:00
Ivan Molodetskikh 2fb993d221 Bump Smithay (xkbcommon wvkbd fix) 2025-08-11 09:07:13 +03:00
Duncan Overbruck 398bc78ea0 add urgent border color and gradient 2025-05-10 12:14:41 -07:00
Ivan Molodetskikh 9571d149b2 Render workspaces separately with gaps between
This design makes more sense spatially, and is required for the
Overview. Gaps also make it clear how clipping windows to workspace
bounds works.

Background and bottom layer-shell surfaces get duplicated for each
workspace, while top and overlay stay "on top".
2025-04-25 02:00:18 -07:00
Ivan Molodetskikh 926e63a5f3 Refactor request_fullscreen() to be an argument on request_size() 2025-03-17 22:31:19 -07:00
Ivan Molodetskikh a0e2a15c60 Take border into account for fixed preset-column-width for tiled windows 2025-01-31 21:30:22 +03:00
Ivan Molodetskikh 8409107a5b Implement default-window-height for scrolling windows 2024-12-30 20:12:37 +03:00
Ivan Molodetskikh be05b66ac3 Hide focus ring for unfocused layout and under interactive move 2024-12-30 20:12:37 +03:00
Ivan Molodetskikh 6fba4c371e Implement default-window-height window rule
Only works for floats that aren't initially fullscreen atm.
2024-12-30 20:12:37 +03:00
Ivan Molodetskikh daaee43be3 layout: Refactor window opening targets 2024-12-30 20:12:37 +03:00
Ivan Molodetskikh 10460191b9 Honor min/max size in more places like initial configure 2024-12-30 20:12:37 +03:00
Ivan Molodetskikh c5fffd6e2c Initial WIP floating window implementation 2024-12-30 20:12:37 +03:00
Ivan Molodetskikh 8665003269 layout: Extract ScrollingSpace
Leave the Workspace to do the workspace parts, and extract the scrolling parts
into a new file. This is a pre-requisite for things like the floating layer
(which will live in a workspace alongside the scrolling layer).

As part of this huge refactor, I found and fixed at least these issues:
- Wrong horizontal popup unconstraining for a smaller window in an
  always-centered column.
- Wrong workspace switch in focus_up_or_right().
2024-12-01 22:24:21 -08:00
Christian Meissl 305fc3b557 Activate newly mapped windows with a valid activation token
most of the time the activation token is passed
while the window is still unmapped. in this case
store the intend to activate the window for
later retrieval on map.
2024-11-29 21:57:36 -08:00
Ivan Molodetskikh 4c22c3285d Refactor animation timing to use lazy clocks 2024-11-25 04:07:59 -08:00
Ivan Molodetskikh 93cee2994a Refactor animations to take explicit current time 2024-11-25 04:07:59 -08:00
Rasmus Eneman e887ee93a3 Implement interactive window move 2024-10-27 23:07:39 -07:00
Ivan Molodetskikh 29602ca995 layout: Extract Monitor::workspaces_with_render_positions() 2024-10-14 11:08:44 +03:00
Ivan Molodetskikh f0157e03e7 Use libdisplay-info for make/model/serial parsing, implement throughout 2024-09-03 13:48:08 +03:00
Ivan Molodetskikh 09f3d3fb12 Extract Niri::update_render_elements() 2024-08-23 12:54:07 +03:00
Ivan Molodetskikh 7bfdf87bf0 Implement resize transactions 2024-08-22 15:19:11 +03:00
Ivan Molodetskikh 3ace97660f Implement gradient color interpolation option (#548)
* Added the better color averaging code (tested & functional)

* rustfmt

* Make Color f32 0..1, clarify premul/unpremul

* Fix imports and test name

* Premultiply gradient colors matching CSS

* Fix indentation

* fixup

* Add gradient image

---------

Co-authored-by: K's Thinkpad <K.T.Kraft@protonmail.com>
2024-07-16 07:22:03 +00:00
Ivan Molodetskikh 1dae45c58d Refactor layout to fractional-logical
Lets borders, gaps, and everything else stay pixel-perfect even with
fractional scale. Allows setting fractional border widths, gaps,
struts.

See the new wiki .md for more details.
2024-06-18 14:01:28 +03:00
Ivan Molodetskikh 9dfa121b8e Implement interactive mouse resizing 2024-05-10 20:23:08 +04:00
Ivan Molodetskikh 73cc0079d6 Split update_render_elements() from advance_animations()
advance_animations() is called from places like input, whereas
update_render_elements() is strictly for rendering.
2024-05-04 11:10:02 +04:00
Ivan Molodetskikh 3e598c565e Implement border window rule 2024-04-24 22:01:26 +04:00
Ivan Molodetskikh ff42f9b9d3 Start move animations from add/remove window/column 2024-04-16 08:59:15 +04:00
Ivan Molodetskikh 493c8dc890 Implement block-out-from window rule, fix alpha on window screenshots 2024-03-24 10:22:56 +04:00
Ivan Molodetskikh d421e1fbf8 Move PartialEq from LayoutElement to an associated type 2024-03-19 18:29:13 +04:00
Ivan Molodetskikh 2317021a7c Implement explicit unmapped window state tracking 2024-02-23 14:01:32 +04:00
Ivan Molodetskikh 48f0f6fb3c Implement gradient borders 2024-02-21 22:15:21 +04:00
Ivan Molodetskikh befdebfa03 Add the beginnings of window rules 2024-02-14 08:32:14 +04:00
Ivan Molodetskikh 18f06a7acd Fix border getting default values for focus ring 2024-02-12 09:34:54 +04:00
Ivan Molodetskikh f9085db564 Implement window open animations 2024-02-07 13:16:54 +04:00