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: case 1000:
term->mouse_tracking = MOUSE_CLICK; term->mouse_tracking = MOUSE_CLICK;
term_xcursor_update(term);
break; break;
case 1002: case 1002:
term->mouse_tracking = MOUSE_DRAG; term->mouse_tracking = MOUSE_DRAG;
term_xcursor_update(term);
break; break;
case 1003: case 1003:
term->mouse_tracking = MOUSE_MOTION; term->mouse_tracking = MOUSE_MOTION;
term_xcursor_update(term);
break; break;
case 1004: case 1004:
@ -1000,6 +1003,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
case 1002: /* MOUSE_BUTTON_EVENT */ case 1002: /* MOUSE_BUTTON_EVENT */
case 1003: /* MOUSE_ANY_EVENT */ case 1003: /* MOUSE_ANY_EVENT */
term->mouse_tracking = MOUSE_NONE; term->mouse_tracking = MOUSE_NONE;
term_xcursor_update(term);
break; break;
case 1005: /* MOUSE_UTF8 */ 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); wayl->focused = wayl_terminal_from_surface(wayl, surface);
assert(wayl->focused != NULL); assert(wayl->focused != NULL);
term_focus_in(wayl->focused); term_focus_in(wayl->focused);
term_xcursor_update(wayl->focused);
} }
static bool static bool
@ -379,6 +380,8 @@ keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
xkb_state_update_mask( xkb_state_update_mask(
wayl->kbd.xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); 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 */ /* Update state of modifiers we're interrested in for e.g mouse events */
wayl->kbd.shift = xkb_state_mod_index_is_active( wayl->kbd.shift = xkb_state_mod_index_is_active(
wayl->kbd.xkb_state, wayl->kbd.mod_shift, XKB_STATE_MODS_DEPRESSED); 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.xkb_state, wayl->kbd.mod_ctrl, XKB_STATE_MODS_DEPRESSED);
wayl->kbd.meta = xkb_state_mod_index_is_active( wayl->kbd.meta = xkb_state_mod_index_is_active(
wayl->kbd.xkb_state, wayl->kbd.mod_meta, XKB_STATE_MODS_DEPRESSED); 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 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.col = x / term->cell_width;
wayl->mouse.row = y / term->cell_height; wayl->mouse.row = y / term->cell_height;
wayl_update_cursor_surface(wayl, term); term_xcursor_update(term);
} }
static void 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, .text = conf->cursor.color.text,
.cursor = conf->cursor.color.cursor, .cursor = conf->cursor.color.cursor,
}, },
.xcursor = "text",
.selection = { .selection = {
.start = {-1, -1}, .start = {-1, -1},
.end = {-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 void
term_set_window_title(struct terminal *term, const char *title) term_set_window_title(struct terminal *term, const char *title)
{ {

View file

@ -240,6 +240,7 @@ struct terminal {
uint32_t text; uint32_t text;
uint32_t cursor; uint32_t cursor;
} cursor_color; } cursor_color;
const char *xcursor;
struct { struct {
struct coord start; 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); bool shift, bool alt, bool ctrl);
void term_mouse_motion(struct terminal *term, int button, int row, int col, void term_mouse_motion(struct terminal *term, int button, int row, int col,
bool shift, bool alt, bool ctrl); 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_set_window_title(struct terminal *term, const char *title);
void term_flash(struct terminal *term, unsigned duration_ms); void term_flash(struct terminal *term, unsigned duration_ms);

View file

@ -28,6 +28,9 @@
#define min(x, y) ((x) < (y) ? (x) : (y)) #define min(x, y) ((x) < (y) ? (x) : (y))
#define max(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 static void
shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
{ {
@ -792,7 +795,45 @@ wayl_win_destroy(struct wl_window *win)
} }
bool 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) if (wayl->pointer.size == 0)
return true; 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 = wl_cursor_theme_load(
wayl->pointer.theme_name, wayl->pointer.size * term->scale, wayl->shm); wayl->pointer.theme_name, wayl->pointer.size * term->scale, wayl->shm);
if (wayl->pointer.theme == NULL) { if (wayl->pointer.theme == NULL) {
LOG_ERR("failed to load cursor theme"); LOG_ERR("failed to load cursor theme");
return false; return false;
} }
wayl->pointer.cursor = wl_cursor_theme_get_cursor( return wayl_cursor_set(wayl, term);
wayl->pointer.theme, "left_ptr");
assert(wayl->pointer.cursor != NULL);
wayl_update_cursor_surface(wayl, term);
return true;
} }
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 * struct terminal *
wayl_terminal_from_surface(struct wayland *wayl, struct wl_surface *surface) 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); struct wayland *wayl, struct xdg_toplevel *toplevel);
/* TODO: pass something other than 'term'? Need scale... */ /* TODO: pass something other than 'term'? Need scale... */
bool wayl_reload_cursor_theme(struct wayland *wayl, struct terminal *term); bool wayl_cursor_set(struct wayland *wayl, const struct terminal *term);
void wayl_update_cursor_surface(struct wayland *wayl, struct terminal *term);
struct wl_window *wayl_win_init(struct wayland *wayl); struct wl_window *wayl_win_init(struct wayland *wayl);
void wayl_win_destroy(struct wl_window *win); void wayl_win_destroy(struct wl_window *win);