2019-07-11 09:51:51 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
2019-08-05 19:02:27 +02:00
|
|
|
#include <stdbool.h>
|
2019-07-11 12:16:50 +02:00
|
|
|
#include <wayland-client.h>
|
|
|
|
|
|
2019-07-11 09:51:51 +02:00
|
|
|
#include "terminal.h"
|
|
|
|
|
|
2019-07-11 12:16:50 +02:00
|
|
|
extern const struct wl_data_device_listener data_device_listener;
|
2019-07-11 17:02:21 +02:00
|
|
|
extern const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener;
|
2019-07-11 12:16:50 +02:00
|
|
|
|
2020-01-03 23:29:45 +01:00
|
|
|
void selection_start(
|
2021-01-02 21:20:41 +01:00
|
|
|
struct terminal *term, int col, int row,
|
2021-01-06 10:53:27 +01:00
|
|
|
enum selection_kind new_kind, bool spaces_only);
|
2019-07-11 09:51:51 +02:00
|
|
|
void selection_update(struct terminal *term, int col, int row);
|
2020-07-08 18:41:09 +02:00
|
|
|
void selection_finalize(
|
|
|
|
|
struct seat *seat, struct terminal *term, uint32_t serial);
|
2020-05-16 21:36:08 +02:00
|
|
|
void selection_dirty_cells(struct terminal *term);
|
2019-07-11 09:51:51 +02:00
|
|
|
void selection_cancel(struct terminal *term);
|
2021-01-06 11:11:46 +01:00
|
|
|
void selection_extend(
|
|
|
|
|
struct seat *seat, struct terminal *term,
|
|
|
|
|
int col, int row, enum selection_kind kind);
|
2019-08-09 21:27:51 +02:00
|
|
|
|
term: scrolling: hopefully fix all selection/scrolling related crashes
When scrolling, there are a couple of cases where an existing
selection must be canceled because we cannot meaningfully represent it
after scrolling.
These are when the selection is (partly) inside:
* The top scrolling region
* The bottom scrolling region
* The new lines scrolled in. I.e. re-used lines
For the scrolling regions, the real problem is when the selection
crosses the scrolling region boundary; a selection that is completely
inside a scrolling regions _might_ be possible to keep, but we would
need to translate the selection coordinates to the new scrolling
region lines.
For simplicity, we cancel the selection if it touches the scrolling
region. Period.
The last item, newly scrolled in lines is when the selection covers
very old lines and we're now wrapping around the scrollback history.
Then there's a fourth problem case: when the user has started a
selection, but hasn't yet moved the cursor. In this case, we have no
end point.
What's more problematic is that when the user (after scrolling) moves
the cursor, we try to create a huge selection that covers mostly
empty (NULL) rows, causing us to crash.
This can happen e.g. when reverse scrolling in such a way that we wrap
around the scrollback history.
The actual viewport in this case is something like `-n - m`. But the
selection we'll end up trying to create will be `m - (rows - n)`. This
range may very well contain NULL rows.
To deal with this, we simply cancel the selection.
2020-05-17 15:34:49 +02:00
|
|
|
bool selection_on_rows(const struct terminal *term, int start, int end);
|
2019-08-09 21:27:51 +02:00
|
|
|
|
2022-07-28 18:27:13 +02:00
|
|
|
void selection_scroll_up(struct terminal *term, int rows);
|
|
|
|
|
void selection_scroll_down(struct terminal *term, int rows);
|
2020-05-19 18:49:42 +02:00
|
|
|
void selection_view_up(struct terminal *term, int new_view);
|
|
|
|
|
void selection_view_down(struct terminal *term, int new_view);
|
|
|
|
|
|
2020-09-09 18:44:49 +02:00
|
|
|
void selection_clipboard_unset(struct seat *seat);
|
|
|
|
|
void selection_primary_unset(struct seat *seat);
|
|
|
|
|
|
2020-09-09 18:45:10 +02:00
|
|
|
bool selection_clipboard_has_data(const struct seat *seat);
|
|
|
|
|
bool selection_primary_has_data(const struct seat *seat);
|
|
|
|
|
|
2020-07-31 17:02:53 +02:00
|
|
|
char *selection_to_text(const struct terminal *term);
|
2020-07-08 18:41:09 +02:00
|
|
|
void selection_to_clipboard(
|
|
|
|
|
struct seat *seat, struct terminal *term, uint32_t serial);
|
|
|
|
|
void selection_from_clipboard(
|
|
|
|
|
struct seat *seat, struct terminal *term, uint32_t serial);
|
|
|
|
|
void selection_to_primary(
|
|
|
|
|
struct seat *seat, struct terminal *term, uint32_t serial);
|
|
|
|
|
void selection_from_primary(struct seat *seat, struct terminal *term);
|
2019-07-19 11:12:14 +02:00
|
|
|
|
2019-11-05 09:13:47 +01:00
|
|
|
/* Copy text *to* primary/clipboard */
|
2020-07-08 18:41:09 +02:00
|
|
|
bool text_to_clipboard(
|
|
|
|
|
struct seat *seat, struct terminal *term, char *text, uint32_t serial);
|
|
|
|
|
bool text_to_primary(
|
|
|
|
|
struct seat *seat, struct terminal *term, char *text, uint32_t serial);
|
2019-11-05 09:13:47 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Copy text *from* primary/clipboard
|
|
|
|
|
*
|
|
|
|
|
* Note that these are asynchronous; they *will* return
|
|
|
|
|
* immediately. The 'cb' callback will be called 0..n times with
|
|
|
|
|
* clipboard data. When done (or on error), the 'done' callback is
|
|
|
|
|
* called.
|
|
|
|
|
*
|
|
|
|
|
* As such, keep this in mind:
|
|
|
|
|
* - The 'user' context must not be stack allocated
|
|
|
|
|
* - Don't expect clipboard data to have been received when these
|
|
|
|
|
* functions return (it will *never* have been received at this
|
|
|
|
|
* point).
|
|
|
|
|
*/
|
2019-07-19 14:20:00 +02:00
|
|
|
void text_from_clipboard(
|
2020-07-09 11:20:46 +02:00
|
|
|
struct seat *seat, struct terminal *term,
|
2020-10-28 19:16:04 +01:00
|
|
|
void (*cb)(char *data, size_t size, void *user),
|
2019-11-05 08:49:32 +01:00
|
|
|
void (*done)(void *user), void *user);
|
2019-08-09 21:27:51 +02:00
|
|
|
|
|
|
|
|
void text_from_primary(
|
2020-07-08 18:41:09 +02:00
|
|
|
struct seat *seat, struct terminal *term,
|
2020-10-28 19:16:04 +01:00
|
|
|
void (*cb)(char *data, size_t size, void *user),
|
2019-11-05 08:49:32 +01:00
|
|
|
void (*dont)(void *user), void *user);
|
selection: auto-scroll: selection keeps scrolling while mouse is outside grid
Moving the mouse outside the grid while we have an on-going selection
now starts a timer. The interval of this timer depends on the mouse’s
distance from the grid - the further away the mouse is, the shorter
interval.
On each timer timeout, we scroll one line, and update the
selection. Thus, the shorter the interval, the faster we scroll.
The timer is canceled as soon as the mouse enters the grid again, or
the selection is either canceled or finalized.
The timer FD is created and destroyed on-demand.
Most of the logic is now in selection.c. The exception is the
calculation of the timer interval, which depends on the mouse’s
position. Thus, this is done in input.c.
The scroll+selection update logic needs to know a) which direction
we’re scrolling in, and b) which *column* the selection should be
updated with.
If the mouse is outside the grid’s left or right margins, the stored
mouse column will be -1. I.e. we don’t know whether the mouse is on
the left or right side of the grid. This is why the caller, that
starts the timer, must provide this value.
The same applies to top and bottom margins, but since we already have
the scroll *direction*, which row value to use can be derived from this.
2020-10-11 15:44:20 +02:00
|
|
|
|
|
|
|
|
void selection_start_scroll_timer(
|
|
|
|
|
struct terminal *term, int interval_ns,
|
|
|
|
|
enum selection_scroll_direction direction, int col);
|
|
|
|
|
void selection_stop_scroll_timer(struct terminal *term);
|
2021-03-28 21:03:53 +02:00
|
|
|
|
|
|
|
|
void selection_find_word_boundary_left(
|
|
|
|
|
struct terminal *term, struct coord *pos, bool spaces_only);
|
|
|
|
|
void selection_find_word_boundary_right(
|
selection: find_word_boundary_right: add “stop-on-space-to-word-boundary”
When true, selection_find_word_boundary_right() behaves as before - it
stops as soon as it encounters a character that isn’t of the
same *type* as the “initial” character (the last character in the
selection).
Take this, for example:
The Quick Brown Fox
The selection will first stop at the end of “the”, then just *before*
“quick”, then at the end of “quick”. Then just *before* “brown”, and
then at the end of “brown”, and so on.
This suits mouse selections pretty good. But when
selection_find_word_boundary_right() is used to extend a search match,
it’s better to ignore space-to-word character transitions. That is, we
want
The Quick Brown Fox
to first extend to the end of “the”, then immediately to the end of
“quick”, then to the end of “brown”, and so on.
Setting the ‘stop_to_space_to_word_boundary’ argument to false results
in latter behavior.
This is now done by search, when executing the
“extend-to-word-boundary” and “extend-to-next-whitespace” key
bindings.
2022-04-27 18:44:57 +02:00
|
|
|
struct terminal *term, struct coord *pos, bool spaces_only,
|
|
|
|
|
bool stop_on_space_to_word_boundary);
|
2022-04-25 19:59:23 +02:00
|
|
|
|
|
|
|
|
struct coord selection_get_start(const struct terminal *term);
|
|
|
|
|
struct coord selection_get_end(const struct terminal *term);
|