diff --git a/main.c b/main.c index 45252207..934461e5 100644 --- a/main.c +++ b/main.c @@ -13,6 +13,7 @@ //#include #include +#include #include #define LOG_MODULE "main" @@ -367,6 +368,40 @@ main(int argc, char *const *argv) goto out; } + /* Cursor */ + term.wl.pointer.surface = wl_compositor_create_surface(term.wl.compositor); + if (term.wl.pointer.surface == NULL) { + LOG_ERR("failed to create cursor surface"); + goto out; + } + + unsigned cursor_size = 24; + const char *cursor_theme = getenv("XCURSOR_THEME"); + + { + const char *env_cursor_size = getenv("XCURSOR_SIZE"); + if (env_cursor_size != NULL) { + unsigned size; + if (sscanf(env_cursor_size, "%u", &size) == 1) + cursor_size = size; + } + } + + LOG_INFO("cursor theme: %s, size: %u", cursor_theme, cursor_size); + + term.wl.pointer.theme = wl_cursor_theme_load( + cursor_theme, cursor_size * 1 /* backend->monitor->scale */, + term.wl.shm); + if (term.wl.pointer.theme == NULL) { + LOG_ERR("failed to load cursor theme"); + return false; + } + + term.wl.pointer.cursor = wl_cursor_theme_get_cursor( + term.wl.pointer.theme, "left_ptr"); + assert(term.wl.pointer.cursor != NULL); + render_update_cursor_surface(&term); + term.wl.surface = wl_compositor_create_surface(term.wl.compositor); if (term.wl.surface == NULL) { LOG_ERR("failed to create wayland surface"); @@ -537,6 +572,12 @@ out: xdg_toplevel_destroy(term.wl.xdg_toplevel); if (term.wl.xdg_surface != NULL) xdg_surface_destroy(term.wl.xdg_surface); + if (term.wl.pointer.theme != NULL) + wl_cursor_theme_destroy(term.wl.pointer.theme); + if (term.wl.pointer.pointer != NULL) + wl_pointer_destroy(term.wl.pointer.pointer); + if (term.wl.pointer.surface != NULL) + wl_surface_destroy(term.wl.pointer.surface); if (term.wl.surface != NULL) wl_surface_destroy(term.wl.surface); if (term.wl.shell != NULL) diff --git a/render.c b/render.c index a6c1b9c3..38fa4d86 100644 --- a/render.c +++ b/render.c @@ -3,6 +3,7 @@ #include #include +#include #include #define LOG_MODULE "render" @@ -530,3 +531,31 @@ render_set_title(struct terminal *term, const char *title) { xdg_toplevel_set_title(term->wl.xdg_toplevel, title); } + +void +render_update_cursor_surface(struct terminal *term) +{ + if (term->wl.pointer.cursor == NULL) + return; + + //const int scale = backend->monitor->scale; + const int scale = 1; + + struct wl_cursor_image *image = term->wl.pointer.cursor->images[0]; + + wl_surface_set_buffer_scale(term->wl.pointer.surface, scale); + + wl_surface_attach( + term->wl.pointer.surface, wl_cursor_image_get_buffer(image), 0, 0); + + wl_pointer_set_cursor( + term->wl.pointer.pointer, term->wl.pointer.serial, + term->wl.pointer.surface, + image->hotspot_x / scale, image->hotspot_y / scale); + + + wl_surface_damage_buffer( + term->wl.pointer.surface, 0, 0, INT32_MAX, INT32_MAX); + + wl_surface_commit(term->wl.pointer.surface); +} diff --git a/render.h b/render.h index 0e34a070..7a79e882 100644 --- a/render.h +++ b/render.h @@ -8,3 +8,4 @@ cairo_scaled_font_t *attrs_to_font( void grid_render(struct terminal *term); void render_resize(struct terminal *term, int width, int height); void render_set_title(struct terminal *term, const char *title); +void render_update_cursor_surface(struct terminal *term); diff --git a/terminal.h b/terminal.h index 04f2cc3a..a7b6f5cd 100644 --- a/terminal.h +++ b/terminal.h @@ -20,6 +20,14 @@ struct wayland { struct wl_shm *shm; struct wl_seat *seat; struct wl_keyboard *keyboard; + struct { + struct wl_pointer *pointer; + uint32_t serial; + + struct wl_surface *surface; + struct wl_cursor_theme *theme; + struct wl_cursor *cursor; + } pointer; struct xdg_wm_base *shell; struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel;