cursor-renderer: Align OpenGL cursor rect to physical pixel grid

When stage views are scaled with fractional scales, the cursor rectangle
won't be aligned with the physical pixel grid, making it potentially
blurry when positioned in between physical pixels. This can be avoided
by aligning the drawn rectangle to the physical pixel grid of the stage
view the cursor is located on.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/413

https://gitlab.gnome.org/GNOME/mutter/merge_requests/610
This commit is contained in:
Jonas Ådahl 2019-05-06 15:25:16 +02:00
parent 4abca411f3
commit 178b975d6a

View File

@ -30,6 +30,7 @@
#include "backends/meta-stage-private.h"
#include "clutter/clutter.h"
#include "clutter/clutter-mutter.h"
#include "cogl/cogl.h"
#include "meta/meta-backend.h"
#include "meta/util.h"
@ -82,6 +83,33 @@ meta_cursor_renderer_emit_painted (MetaCursorRenderer *renderer,
g_signal_emit (renderer, signals[CURSOR_PAINTED], 0, cursor_sprite);
}
static void
align_cursor_position (MetaCursorRenderer *renderer,
ClutterRect *rect)
{
MetaCursorRendererPrivate *priv =
meta_cursor_renderer_get_instance_private (renderer);
MetaBackend *backend = meta_get_backend ();
ClutterActor *stage = meta_backend_get_stage (backend);
ClutterStageView *view;
cairo_rectangle_int_t view_layout;
float view_scale;
view = clutter_stage_get_view_at (CLUTTER_STAGE (stage),
priv->current_x,
priv->current_y);
if (!view)
return;
clutter_stage_view_get_layout (view, &view_layout);
view_scale = clutter_stage_view_get_scale (view);
clutter_rect_offset (rect, -view_layout.x, -view_layout.y);
rect->origin.x = floorf (rect->origin.x * view_scale) / view_scale;
rect->origin.y = floorf (rect->origin.y * view_scale) / view_scale;
clutter_rect_offset (rect, view_layout.x, view_layout.y);
}
static void
queue_redraw (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
@ -92,13 +120,16 @@ queue_redraw (MetaCursorRenderer *renderer,
CoglTexture *texture;
ClutterRect rect = CLUTTER_RECT_INIT_ZERO;
if (cursor_sprite)
rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
/* During early initialization, we can have no stage */
if (!stage)
return;
if (cursor_sprite)
{
rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
align_cursor_position (renderer, &rect);
}
if (!priv->stage_overlay)
priv->stage_overlay = meta_stage_create_cursor_overlay (META_STAGE (stage));