terminal: use the 'text' xcursor pointer whenever selection is possible

This commit is contained in:
Daniel Eklöf 2019-11-28 19:35:47 +01:00
parent 729ba8b8ac
commit 0dd37f0a36
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
6 changed files with 72 additions and 36 deletions

4
csi.c
View file

@ -875,14 +875,17 @@ csi_dispatch(struct terminal *term, uint8_t final)
case 1000:
term->mouse_tracking = MOUSE_CLICK;
term_xcursor_update(term);
break;
case 1002:
term->mouse_tracking = MOUSE_DRAG;
term_xcursor_update(term);
break;
case 1003:
term->mouse_tracking = MOUSE_MOTION;
term_xcursor_update(term);
break;
case 1004:
@ -1000,6 +1003,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
case 1002: /* MOUSE_BUTTON_EVENT */
case 1003: /* MOUSE_ANY_EVENT */
term->mouse_tracking = MOUSE_NONE;
term_xcursor_update(term);
break;
case 1005: /* MOUSE_UTF8 */

View file

@ -88,6 +88,7 @@ keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
wayl->focused = wayl_terminal_from_surface(wayl, surface);
assert(wayl->focused != NULL);
term_focus_in(wayl->focused);
term_xcursor_update(wayl->focused);
}
static bool
@ -379,6 +380,8 @@ keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
xkb_state_update_mask(
wayl->kbd.xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
bool old_shift = wayl->kbd.shift;
/* Update state of modifiers we're interrested in for e.g mouse events */
wayl->kbd.shift = xkb_state_mod_index_is_active(
wayl->kbd.xkb_state, wayl->kbd.mod_shift, XKB_STATE_MODS_DEPRESSED);
@ -388,6 +391,9 @@ keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
wayl->kbd.xkb_state, wayl->kbd.mod_ctrl, XKB_STATE_MODS_DEPRESSED);
wayl->kbd.meta = xkb_state_mod_index_is_active(
wayl->kbd.xkb_state, wayl->kbd.mod_meta, XKB_STATE_MODS_DEPRESSED);
if (wayl->moused && old_shift != wayl->kbd.shift)
term_xcursor_update(wayl->moused);
}
static void
@ -431,7 +437,7 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
wayl->mouse.col = x / term->cell_width;
wayl->mouse.row = y / term->cell_height;
wayl_update_cursor_surface(wayl, term);
term_xcursor_update(term);
}
static void

View file

@ -483,6 +483,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
.text = conf->cursor.color.text,
.cursor = conf->cursor.color.cursor,
},
.xcursor = "text",
.selection = {
.start = {-1, -1},
.end = {-1, -1},
@ -1429,6 +1430,19 @@ term_mouse_motion(struct terminal *term, int button, int row, int col,
}
}
void
term_xcursor_update(struct terminal *term)
{
const bool is_focused = term->wl->focused == term;
const char *new_cursor =
is_focused && selection_enabled(term) ? "text" : "left_ptr";
LOG_DBG("setting xcursor to '%s' for term=%p", new_cursor, term);
term->xcursor = new_cursor;
wayl_cursor_set(term->wl, term);
}
void
term_set_window_title(struct terminal *term, const char *title)
{

View file

@ -240,6 +240,7 @@ struct terminal {
uint32_t text;
uint32_t cursor;
} cursor_color;
const char *xcursor;
struct {
struct coord start;
@ -365,6 +366,7 @@ void term_mouse_up(struct terminal *term, int button, int row, int col,
bool shift, bool alt, bool ctrl);
void term_mouse_motion(struct terminal *term, int button, int row, int col,
bool shift, bool alt, bool ctrl);
void term_xcursor_update(struct terminal *term);
void term_set_window_title(struct terminal *term, const char *title);
void term_flash(struct terminal *term, unsigned duration_ms);

View file

@ -28,6 +28,9 @@
#define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y))
static bool wayl_reload_cursor_theme(
struct wayland *wayl, const struct terminal *term);
static void
shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
{
@ -792,7 +795,45 @@ wayl_win_destroy(struct wl_window *win)
}
bool
wayl_reload_cursor_theme(struct wayland *wayl, struct terminal *term)
wayl_cursor_set(struct wayland *wayl, const struct terminal *term)
{
if (wayl->pointer.theme == NULL)
return false;
if (wayl->moused != term) {
/* This terminal doesn't have mouse focus */
return true;
}
wayl->pointer.cursor = wl_cursor_theme_get_cursor(wayl->pointer.theme, term->xcursor);
if (wayl->pointer.cursor == NULL) {
LOG_ERR("%s: failed to load xcursor pointer '%s'",
wayl->pointer.theme_name, term->xcursor);
return false;
}
const int scale = term->scale;
struct wl_cursor_image *image = wayl->pointer.cursor->images[0];
wl_surface_attach(
wayl->pointer.surface, wl_cursor_image_get_buffer(image), 0, 0);
wl_pointer_set_cursor(
wayl->pointer.pointer, wayl->pointer.serial,
wayl->pointer.surface,
image->hotspot_x / scale, image->hotspot_y / scale);
wl_surface_damage_buffer(
wayl->pointer.surface, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_set_buffer_scale(wayl->pointer.surface, scale);
wl_surface_commit(wayl->pointer.surface);
wl_display_roundtrip(wayl->display);
return true;
}
static bool
wayl_reload_cursor_theme(struct wayland *wayl, const struct terminal *term)
{
if (wayl->pointer.size == 0)
return true;
@ -808,45 +849,15 @@ wayl_reload_cursor_theme(struct wayland *wayl, struct terminal *term)
wayl->pointer.theme = wl_cursor_theme_load(
wayl->pointer.theme_name, wayl->pointer.size * term->scale, wayl->shm);
if (wayl->pointer.theme == NULL) {
LOG_ERR("failed to load cursor theme");
return false;
}
wayl->pointer.cursor = wl_cursor_theme_get_cursor(
wayl->pointer.theme, "left_ptr");
assert(wayl->pointer.cursor != NULL);
wayl_update_cursor_surface(wayl, term);
return true;
return wayl_cursor_set(wayl, term);
}
void
wayl_update_cursor_surface(struct wayland *wayl, struct terminal *term)
{
if (wayl->pointer.cursor == NULL)
return;
const int scale = term->scale;
wl_surface_set_buffer_scale(wayl->pointer.surface, scale);
struct wl_cursor_image *image = wayl->pointer.cursor->images[0];
wl_surface_attach(
wayl->pointer.surface, wl_cursor_image_get_buffer(image), 0, 0);
wl_pointer_set_cursor(
wayl->pointer.pointer, wayl->pointer.serial,
wayl->pointer.surface,
image->hotspot_x / scale, image->hotspot_y / scale);
wl_surface_damage_buffer(
wayl->pointer.surface, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_commit(wayl->pointer.surface);
}
struct terminal *
wayl_terminal_from_surface(struct wayland *wayl, struct wl_surface *surface)
{

View file

@ -166,8 +166,7 @@ struct terminal *wayl_terminal_from_xdg_toplevel(
struct wayland *wayl, struct xdg_toplevel *toplevel);
/* TODO: pass something other than 'term'? Need scale... */
bool wayl_reload_cursor_theme(struct wayland *wayl, struct terminal *term);
void wayl_update_cursor_surface(struct wayland *wayl, struct terminal *term);
bool wayl_cursor_set(struct wayland *wayl, const struct terminal *term);
struct wl_window *wayl_win_init(struct wayland *wayl);
void wayl_win_destroy(struct wl_window *win);