Skip to content

Commit 7d3618a

Browse files
committed
feat: cursor-zoom - working zoom!
1 parent 66f476f commit 7d3618a

File tree

1 file changed

+83
-1
lines changed

1 file changed

+83
-1
lines changed

src/niri.rs

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4036,11 +4036,54 @@ impl Niri {
40364036
elements.push(elem)
40374037
});
40384038

4039+
let output_scale = Scale::from(output.current_scale().fractional_scale());
40394040
if self.debug_draw_opaque_regions {
4040-
let output_scale = Scale::from(output.current_scale().fractional_scale());
40414041
draw_opaque_regions(&mut elements, output_scale);
40424042
}
40434043

4044+
// Apply cursor zoom to all elements except the cursor itself
4045+
// if cursor zoom is active. Per-monitor like overview zoom.
4046+
if self.cursor_zoom_factor > 1.0 {
4047+
let zoom_factor = self.cursor_zoom_factor;
4048+
let pointer = self.seat.get_pointer().unwrap();
4049+
let cursor_pos = pointer.current_location();
4050+
let output_geo = self.global_space.output_geometry(output).unwrap();
4051+
let cursor_pos_in_output = cursor_pos - output_geo.loc.to_f64();
4052+
let output_size = output_geo.size.to_f64();
4053+
let output_rect = Rectangle::new(Point::new(0., 0.), output_size);
4054+
4055+
let mut zoomed_elements = Vec::new();
4056+
4057+
macro_rules! process_zoom {
4058+
($elem:expr, $($variant:ident),*) => {
4059+
match $elem {
4060+
$(
4061+
OutputRenderElements::$variant(elem) => {
4062+
if let Some(elem) = apply_cursor_zoom(
4063+
elem,
4064+
output_scale,
4065+
zoom_factor,
4066+
cursor_pos_in_output,
4067+
output_rect,
4068+
) {
4069+
zoomed_elements.push(elem.into());
4070+
}
4071+
}
4072+
)*
4073+
// Other elements pass through unchanged for now
4074+
// Skip cursor, specifically - it renders at logical position
4075+
_ => zoomed_elements.push($elem),
4076+
}
4077+
};
4078+
}
4079+
4080+
for elem in elements.drain(..) {
4081+
process_zoom!(elem, LayerSurface, SolidColor, Wayland, Monitor);
4082+
}
4083+
4084+
elements = zoomed_elements;
4085+
}
4086+
40444087
elements
40454088
}
40464089

@@ -4264,6 +4307,7 @@ impl Niri {
42644307
push(backdrop);
42654308
}
42664309

4310+
/// Renders the output with cursor zoom applied.
42674311
fn layers_in_render_order<'a>(
42684312
&'a self,
42694313
layer_map: &'a LayerMap,
@@ -6126,6 +6170,30 @@ fn scale_relocate_crop<E: Element>(
61266170
CropRenderElement::from_element(elem, output_scale, ws_geo)
61276171
}
61286172

6173+
fn apply_cursor_zoom<E: Element>(
6174+
element: E,
6175+
output_scale: Scale<f64>,
6176+
zoom: f64,
6177+
cursor_pos: Point<f64, Logical>,
6178+
output_geo: Rectangle<f64, Logical>,
6179+
) -> Option<CropRenderElement<RelocateRenderElement<RescaleRenderElement<E>>>> {
6180+
let offset_x = (cursor_pos.x * (1.0 - zoom)) as i32;
6181+
let offset_y = (cursor_pos.y * (1.0 - zoom)) as i32;
6182+
let physical_offset = Point::<i32, Physical>::from((
6183+
(offset_x as f64 * output_scale.x) as i32,
6184+
(offset_y as f64 * output_scale.y) as i32,
6185+
));
6186+
let scaled = RescaleRenderElement::from_element(element, (0, 0).into(), zoom);
6187+
let relocated =
6188+
RelocateRenderElement::from_element(scaled, physical_offset, Relocate::Relative);
6189+
6190+
CropRenderElement::from_element(
6191+
relocated,
6192+
output_scale,
6193+
output_geo.to_physical_precise_round(output_scale),
6194+
)
6195+
}
6196+
61296197
niri_render_elements! {
61306198
PointerRenderElements<R> => {
61316199
Wayland = WaylandSurfaceRenderElement<R>,
@@ -6158,7 +6226,21 @@ niri_render_elements! {
61586226
WindowMruUi = WindowMruUiRenderElement<R>,
61596227
ExitConfirmDialog = ExitConfirmDialogRenderElement,
61606228
Texture = PrimaryGpuTextureRenderElement,
6229+
61616230
// Used for the CPU-rendered panels.
61626231
RelocatedMemoryBuffer = RelocateRenderElement<MemoryRenderBufferRenderElement<R>>,
6232+
6233+
RelocatedMonitor = CropRenderElement<RelocateRenderElement<RescaleRenderElement<
6234+
MonitorRenderElement<R>
6235+
>>>,
6236+
RelocatedWayland = CropRenderElement<RelocateRenderElement<RescaleRenderElement<
6237+
WaylandSurfaceRenderElement<R>
6238+
>>>,
6239+
RelocatedTile = CropRenderElement<RelocateRenderElement<RescaleRenderElement<
6240+
TileRenderElement<R>
6241+
>>>,
6242+
RelocatedExitConfirmDialog = CropRenderElement<RelocateRenderElement<RescaleRenderElement<
6243+
ExitConfirmDialogRenderElement
6244+
>>>,
61636245
}
61646246
}

0 commit comments

Comments
 (0)