Skip to content

Commit 6237be1

Browse files
committed
fix: cursor behavior for selection
- Code cleanup seems to keep jumping out at me
1 parent dd6bf9f commit 6237be1

File tree

1 file changed

+85
-113
lines changed

1 file changed

+85
-113
lines changed

src/niri.rs

Lines changed: 85 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -4046,112 +4046,49 @@ impl Niri {
40464046
elements
40474047
}
40484048

4049-
pub fn render<R: NiriRenderer>(
4049+
pub fn zoom_render_elements<R: NiriRenderer>(
40504050
&self,
4051-
renderer: &mut R,
4051+
elements: Vec<OutputRenderElements<R>>,
40524052
output: &Output,
4053-
include_pointer: bool,
4054-
target: RenderTarget,
40554053
) -> Vec<OutputRenderElements<R>> {
4056-
let mut elements = Vec::new();
4054+
let output_scale = Scale::from(output.current_scale().fractional_scale());
4055+
let output_geo = self.global_space.output_geometry(output).unwrap();
4056+
let output_size = output_geo.size.to_f64();
4057+
let output_rect = Rectangle::new(Point::new(0., 0.), output_size);
40574058

40584059
let monitor = self.layout.monitor_for_output(output).unwrap();
40594060
let zoom_factor = monitor.zoom_factor;
4060-
let zoom_enabled = monitor.zoom_enabled;
4061-
4062-
if zoom_enabled && zoom_factor > 1.0 {
4063-
// Use Nearest neighbor filtering for high zoom levels (pixel-perfect),
4064-
// Linear for lower zoom levels (smooth).
4065-
let filter = if zoom_factor > 3.0 {
4066-
TextureFilter::Nearest
4067-
} else {
4068-
TextureFilter::Linear
4069-
};
4070-
let gles = renderer.as_gles_renderer();
4071-
let _ = gles.upscale_filter(filter).map_err(|err| {
4072-
warn!("error setting upscale filter: {err:?}");
4073-
});
4074-
let _ = gles.downscale_filter(filter).map_err(|err| {
4075-
warn!("error setting downscale filter: {err:?}");
4076-
});
4077-
}
4061+
let zoom_frozen = monitor.zoom_frozen;
4062+
let zoom_movement = monitor.zoom_movement;
40784063

4079-
self.render_inner(renderer, output, include_pointer, target, &mut |elem| {
4080-
elements.push(elem)
4081-
});
4082-
4083-
let output_scale = Scale::from(output.current_scale().fractional_scale());
4084-
if self.debug_draw_opaque_regions {
4085-
draw_opaque_regions(&mut elements, output_scale);
4086-
}
4087-
4088-
let elements = if zoom_enabled && zoom_factor > 1.0 {
4089-
let output_geo = self.global_space.output_geometry(output).unwrap();
4090-
let output_size = output_geo.size.to_f64();
4091-
let output_rect = Rectangle::new(Point::new(0., 0.), output_size);
4092-
4093-
let zoom_center = match monitor.zoom_movement {
4094-
niri_ipc::ZoomMovement::Cursor => {
4095-
if monitor.zoom_frozen {
4096-
monitor.zoom_center
4097-
} else {
4098-
let pointer = self.seat.get_pointer().unwrap();
4099-
let cursor_pos = pointer.current_location();
4100-
cursor_pos - output_geo.loc.to_f64()
4101-
}
4102-
}
4103-
niri_ipc::ZoomMovement::EdgePushed => monitor.zoom_center,
4104-
};
4105-
4106-
let scale_with_zoom = self.config.borrow().cursor.scale_with_zoom;
4107-
4108-
// Compute physical offset for zoom repositioning.
4109-
macro_rules! zoom_offset {
4110-
($center:expr) => {{
4111-
let offset_x = ($center.x * (1.0 - zoom_factor)) as i32;
4112-
let offset_y = ($center.y * (1.0 - zoom_factor)) as i32;
4113-
Point::<i32, Physical>::from((
4114-
(offset_x as f64 * output_scale.x) as i32,
4115-
(offset_y as f64 * output_scale.y) as i32,
4116-
))
4117-
}};
4064+
let zoom_center = match (zoom_frozen, zoom_movement) {
4065+
(true, _) | (_, niri_ipc::ZoomMovement::EdgePushed) => monitor.zoom_center,
4066+
(false, niri_ipc::ZoomMovement::Cursor) => {
4067+
let pointer = self.seat.get_pointer().unwrap();
4068+
let cursor_pos = pointer.current_location();
4069+
cursor_pos // - output_geo.loc.to_f64()
41184070
}
4071+
};
41194072

4120-
macro_rules! reposition_offset {
4121-
($elem:expr, $center:expr) => {{
4122-
let elem_geo = $elem.geometry(output_scale);
4123-
let elem_pos_logical: Point<f64, Logical> = Point::from((
4124-
elem_geo.loc.x as f64 / output_scale.x,
4125-
elem_geo.loc.y as f64 / output_scale.y,
4126-
));
4127-
let offset_x = (($center.x - elem_pos_logical.x) * (1.0 - zoom_factor)) as i32;
4128-
let offset_y = (($center.y - elem_pos_logical.y) * (1.0 - zoom_factor)) as i32;
4129-
Point::<i32, Physical>::from((
4130-
(offset_x as f64 * output_scale.x) as i32,
4131-
(offset_y as f64 * output_scale.y) as i32,
4132-
))
4133-
}};
4134-
}
4073+
let scale_with_zoom = self.config.borrow().cursor.scale_with_zoom;
41354074

4136-
// Generate match arms for each OutputRenderElement variant.
4137-
macro_rules! apply_zoom {
4075+
// Generate match arms for each OutputRenderElement variant.
4076+
macro_rules! apply_zoom {
41384077
($elem:expr, $($variant:ident),*) => {
41394078
match $elem {
4140-
OutputRenderElements::Pointer(elem) if !scale_with_zoom => {
4141-
let offset = reposition_offset!(elem, zoom_center);
4142-
let relocated =
4143-
RelocateRenderElement::from_element(elem, offset, Relocate::Relative);
4144-
CropRenderElement::from_element(
4145-
relocated,
4146-
output_scale,
4147-
output_rect.to_physical_precise_round(output_scale),
4148-
)
4149-
.map(Into::into)
4150-
.into()
4079+
OutputRenderElements::Pointer(_) if !scale_with_zoom => {
4080+
// When scale_with_zoom=false, cursor should pass through unchanged
4081+
// to match host compositor cursor position exactly
4082+
Some($elem)
41514083
}
41524084
$(
41534085
OutputRenderElements::$variant(elem) => {
4154-
let offset = zoom_offset!(zoom_center);
4086+
let offset_x = (zoom_center.x * (1.0 - zoom_factor)) as i32;
4087+
let offset_y = (zoom_center.y * (1.0 - zoom_factor)) as i32;
4088+
let offset = Point::<i32, Physical>::from((
4089+
(offset_x as f64 * output_scale.x) as i32,
4090+
(offset_y as f64 * output_scale.y) as i32,
4091+
));
41554092
let scaled =
41564093
RescaleRenderElement::from_element(elem, (0, 0).into(), zoom_factor);
41574094
let relocated =
@@ -4168,30 +4105,65 @@ impl Niri {
41684105
// Other elements pass through unchanged
41694106
_ => Some($elem),
41704107
}
4171-
};
4108+
}
41724109
}
41734110

4174-
elements
4175-
.into_iter()
4176-
.filter_map(|elem| {
4177-
apply_zoom!(
4178-
elem,
4179-
Monitor,
4180-
RescaledTile,
4181-
LayerSurface,
4182-
Pointer,
4183-
Wayland,
4184-
SolidColor,
4185-
ExitConfirmDialog,
4186-
Texture,
4187-
RelocatedColor,
4188-
RelocatedLayerSurface
4189-
)
4190-
})
4191-
.collect()
4192-
} else {
4193-
elements
4194-
};
4111+
elements
4112+
.into_iter()
4113+
.filter_map(|elem| {
4114+
apply_zoom!(
4115+
elem,
4116+
Monitor,
4117+
RescaledTile,
4118+
LayerSurface,
4119+
Pointer,
4120+
Wayland,
4121+
SolidColor,
4122+
ExitConfirmDialog,
4123+
Texture,
4124+
RelocatedColor,
4125+
RelocatedLayerSurface
4126+
)
4127+
})
4128+
.collect()
4129+
}
4130+
4131+
pub fn render<R: NiriRenderer>(
4132+
&self,
4133+
renderer: &mut R,
4134+
output: &Output,
4135+
include_pointer: bool,
4136+
target: RenderTarget,
4137+
) -> Vec<OutputRenderElements<R>> {
4138+
let mut elements = Vec::new();
4139+
4140+
let monitor = self.layout.monitor_for_output(output).unwrap();
4141+
let zoom_factor = monitor.zoom_factor;
4142+
4143+
// Use Nearest neighbor filtering for high zoom levels (pixel-perfect),
4144+
if zoom_factor > 1.5 {
4145+
let filter = TextureFilter::Nearest;
4146+
let gles = renderer.as_gles_renderer();
4147+
let _ = gles.upscale_filter(filter).map_err(|err| {
4148+
warn!("error setting upscale filter: {err:?}");
4149+
});
4150+
let _ = gles.downscale_filter(filter).map_err(|err| {
4151+
warn!("error setting downscale filter: {err:?}");
4152+
});
4153+
}
4154+
4155+
self.render_inner(renderer, output, include_pointer, target, &mut |elem| {
4156+
elements.push(elem)
4157+
});
4158+
4159+
if self.debug_draw_opaque_regions {
4160+
let output_scale = Scale::from(output.current_scale().fractional_scale());
4161+
draw_opaque_regions(&mut elements, output_scale);
4162+
}
4163+
4164+
if zoom_factor > 1.0 {
4165+
elements = self.zoom_render_elements(elements, output);
4166+
}
41954167

41964168
elements
41974169
}

0 commit comments

Comments
 (0)