diff --git a/server/region.c b/server/region.c index 0e52f2f0bdc..9f377ee05d3 100644 --- a/server/region.c +++ b/server/region.c @@ -724,6 +724,18 @@ void mirror_region( const rectangle_t *client_rect, struct region *region ) } +/* scale a region for a given dpi factor */ +void scale_region( struct region *region, unsigned int dpi_from, unsigned int dpi_to ) +{ + rectangle_t *rect, *end; + + if (!region->num_rects) return; + for (rect = region->rects, end = rect + region->num_rects; rect < end; rect++) + scale_dpi_rect( rect, dpi_from, dpi_to ); + scale_dpi_rect( ®ion->extents, dpi_from, dpi_to ); +} + + /* make a copy of a region; returns dst or NULL on error */ struct region *copy_region( struct region *dst, const struct region *src ) { diff --git a/server/user.h b/server/user.h index fe3aa0977dd..eb1b7ce1e4b 100644 --- a/server/user.h +++ b/server/user.h @@ -135,6 +135,7 @@ extern int is_region_empty( const struct region *region ); extern void get_region_extents( const struct region *region, rectangle_t *rect ); extern void offset_region( struct region *region, int x, int y ); extern void mirror_region( const rectangle_t *client_rect, struct region *region ); +extern void scale_region( struct region *region, unsigned int dpi_from, unsigned int dpi_to ); extern struct region *copy_region( struct region *dst, const struct region *src ); extern struct region *intersect_region( struct region *dst, const struct region *src1, const struct region *src2 ); diff --git a/server/window.c b/server/window.c index e45cf3856e5..8d056a21d40 100644 --- a/server/window.c +++ b/server/window.c @@ -649,6 +649,15 @@ static void map_dpi_rect( struct window *win, rectangle_t *rect, unsigned int fr scale_dpi_rect( rect, from, to ); } +/* map a region between different DPI scaling levels */ +static void map_dpi_region( struct window *win, struct region *region, unsigned int from, unsigned int to ) +{ + if (!from) from = get_monitor_dpi( win ); + if (!to) to = get_monitor_dpi( win ); + if (from == to) return; + scale_region( region, from, to ); +} + /* check if window and all its ancestors are visible */ static int is_visible( const struct window *win ) { @@ -1388,7 +1397,7 @@ static void validate_parents( struct window *child ) /* add/subtract a region (in client coordinates) to the update region of the window */ static void redraw_window( struct window *win, struct region *region, int frame, unsigned int flags ) { - struct region *tmp; + struct region *child_rgn, *tmp; struct window *child; if (flags & RDW_INVALIDATE) @@ -1450,11 +1459,19 @@ static void redraw_window( struct window *win, struct region *region, int frame, LIST_FOR_EACH_ENTRY( child, &win->children, struct window, entry ) { if (!(child->style & WS_VISIBLE)) continue; - if (!rect_in_region( tmp, &child->window_rect )) continue; - offset_region( tmp, -child->client_rect.left, -child->client_rect.top ); - redraw_window( child, tmp, 1, flags ); - offset_region( tmp, child->client_rect.left, child->client_rect.top ); + if (!(child_rgn = create_empty_region())) continue; + if (copy_region( child_rgn, tmp )) + { + map_dpi_region( child, child_rgn, win->dpi, child->dpi ); + if (rect_in_region( child_rgn, &child->window_rect )) + { + offset_region( child_rgn, -child->client_rect.left, -child->client_rect.top ); + redraw_window( child, child_rgn, 1, flags ); + } + } + free_region( child_rgn ); } + free_region( tmp ); }