@@ -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+
61296197niri_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