mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-05 07:15:30 -04:00
terminal: use the 'text' xcursor pointer whenever selection is possible
This commit is contained in:
parent
729ba8b8ac
commit
0dd37f0a36
6 changed files with 72 additions and 36 deletions
4
csi.c
4
csi.c
|
|
@ -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 */
|
||||||
|
|
|
||||||
8
input.c
8
input.c
|
|
@ -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
|
||||||
|
|
|
||||||
14
terminal.c
14
terminal.c
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
77
wayland.c
77
wayland.c
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue