@@ -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