Add mouse_set and cursor_define DisplayChangeListener callbacks and mouse pointer rendering support.
Signed-off-by: Gerd Hoffmann <kra...@redhat.com> --- ui/fbdev.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 95 insertions(+), 0 deletions(-) diff --git a/ui/fbdev.c b/ui/fbdev.c index d55850e..d859d84 100644 --- a/ui/fbdev.c +++ b/ui/fbdev.c @@ -82,6 +82,12 @@ static pixman_image_t *framebuffer; static pixman_transform_t transform; static pixman_region16_t dirty; +static QEMUCursor *ptr_cursor; +static pixman_image_t *ptr_image; +static int ptr_refresh; +static int px, py, pw, ph; +static int mx, my, mon; + /* fwd decls */ static int fbdev_activate_vt(int tty, int vtno, bool wait); @@ -877,6 +883,51 @@ static void fbdev_render(DisplayState *ds) pixman_region_init(&dirty); } +static void fbdev_unrender_ptr(DisplayState *ds) +{ + if (!pw && !ph) { + return; + } + pixman_region_union_rect(&dirty, &dirty, px, py, pw, ph); + ph = pw = 0; +} + +static void fbdev_render_ptr(DisplayState *ds) +{ + pixman_region16_t region; + pixman_transform_t transform; + + if (!mon || !ptr_image) { + return; + } + if (mx < 0 || mx >= cw || my < 0 || my >= ch) { + return; + } + + px = mx - ptr_cursor->hot_x; + py = my - ptr_cursor->hot_y; + pw = ptr_cursor->width; + ph = ptr_cursor->height; + + pixman_transform_init_identity(&transform); + pixman_transform_translate(&transform, NULL, + pixman_int_to_fixed(-cx), + pixman_int_to_fixed(-cy)); + pixman_transform_translate(&transform, NULL, + pixman_int_to_fixed(-px), + pixman_int_to_fixed(-py)); + pixman_image_set_transform(ptr_image, &transform); + + pixman_region_init_rect(®ion, 0, 0, pw, ph); + pixman_image_set_clip_region(ptr_image, ®ion); + + pixman_image_composite(PIXMAN_OP_OVER, ptr_image, NULL, framebuffer, + 0, 0, 0, 0, 0, 0, fb_var.xres, fb_var.yres); + + pixman_region_fini(®ion); + ptr_refresh = 0; +} + /* -------------------------------------------------------------------- */ /* qemu interfaces */ @@ -918,6 +969,9 @@ static void fbdev_update(DisplayState *ds, int x, int y, int w, int h) } pixman_region_union_rect(&dirty, &dirty, x, y, w, h); + if (ptr_image && mon && pw && ph) { + ptr_refresh++; + } } static void fbdev_resize(DisplayState *ds) @@ -954,9 +1008,48 @@ static void fbdev_refresh(DisplayState *ds) fbdev_update(ds, 0, 0, 0, 0); } + if (ptr_refresh) { + fbdev_unrender_ptr(ds); + } if (pixman_region_not_empty(&dirty)) { fbdev_render(ds); } + if (ptr_refresh) { + fbdev_render_ptr(ds); + } +} + +static void fbdev_mouse_set(DisplayState *ds, int x, int y, int on) +{ + ptr_refresh++; + mx = x; + my = y; + mon = on; +} + +static void fbdev_cursor_define(DisplayState *ds, QEMUCursor *cursor) +{ + ptr_refresh++; + + if (ptr_cursor) { + cursor_put(ptr_cursor); + ptr_cursor = NULL; + } + if (ptr_image) { + pixman_image_unref(ptr_image); + ptr_image = NULL; + } + + if (!cursor) { + return; + } + + ptr_cursor = cursor; + cursor_get(ptr_cursor); + ptr_image = pixman_image_create_bits(PIXMAN_a8r8g8b8, + cursor->width, cursor->height, + cursor->data, + cursor->width * 4); } static void fbdev_exit_notifier(Notifier *notifier, void *data) @@ -985,6 +1078,8 @@ int fbdev_display_init(DisplayState *ds, const char *device, Error **err) dcl->dpy_resize = fbdev_resize; dcl->dpy_setdata = fbdev_setdata; dcl->dpy_refresh = fbdev_refresh; + dcl->dpy_mouse_set = fbdev_mouse_set; + dcl->dpy_cursor_define = fbdev_cursor_define; register_displaychangelistener(ds, dcl); trace_fbdev_enabled(); -- 1.7.1