Work on mouse support, it's a mess
This commit is contained in:
parent
5692f32bcf
commit
456093e4ed
|
@ -196,7 +196,7 @@ handle_csi_u (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handler for CSI M / CSI m mouse events in SRG and rxvt encodings
|
* Handler for CSI M / CSI m mouse events in SGR and rxvt encodings
|
||||||
* Note: This does not handle X10 encoding
|
* Note: This does not handle X10 encoding
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -262,6 +262,7 @@ termkey_interpret_mouse (termkey_t *tk, const termkey_key_t *key,
|
||||||
|
|
||||||
termkey_key_get_linecol (key, line, col);
|
termkey_key_get_linecol (key, line, col);
|
||||||
|
|
||||||
|
// XXX: WTF is this logic?
|
||||||
if (!event)
|
if (!event)
|
||||||
return TERMKEY_RES_KEY;
|
return TERMKEY_RES_KEY;
|
||||||
|
|
||||||
|
|
128
driver-ti.c
128
driver-ti.c
|
@ -58,6 +58,9 @@ typedef struct
|
||||||
|
|
||||||
char *start_string;
|
char *start_string;
|
||||||
char *stop_string;
|
char *stop_string;
|
||||||
|
|
||||||
|
bool have_mouse;
|
||||||
|
char *set_mouse_string;
|
||||||
}
|
}
|
||||||
termkey_ti_t;
|
termkey_ti_t;
|
||||||
|
|
||||||
|
@ -172,56 +175,41 @@ compress_trie (struct trie_node *n)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static bool
|
||||||
load_terminfo (termkey_ti_t *ti, const char *term)
|
load_terminfo (termkey_ti_t *ti, const char *term)
|
||||||
{
|
{
|
||||||
int i;
|
const char *mouse_report_string = NULL;
|
||||||
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
#ifdef HAVE_UNIBILIUM
|
||||||
unibi_term *unibi = unibi_from_term (term);
|
unibi_term *unibi = unibi_from_term (term);
|
||||||
if (!unibi)
|
if (!unibi)
|
||||||
return 0;
|
return false;
|
||||||
#else
|
|
||||||
int err;
|
|
||||||
|
|
||||||
/* Have to cast away the const. But it's OK - we know terminfo won't
|
for (int i = unibi_string_begin_ + 1; i < unibi_string_end_; i++)
|
||||||
* really modify term */
|
|
||||||
if (setupterm ((char *) term, 1, &err) != OK)
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
|
||||||
for (i = unibi_string_begin_ + 1; i < unibi_string_end_; i++)
|
|
||||||
#else
|
|
||||||
for (i = 0; strfnames[i]; i++)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
// Only care about the key_* constants
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
|
||||||
const char *name = unibi_name_str (i);
|
const char *name = unibi_name_str (i);
|
||||||
#else
|
|
||||||
const char *name = strfnames[i];
|
|
||||||
#endif
|
|
||||||
if (strncmp (name, "key_", 4) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
#ifdef HAVE_UNIBILIUM
|
|
||||||
const char *value = unibi_get_str (unibi, i);
|
const char *value = unibi_get_str (unibi, i);
|
||||||
#else
|
#else
|
||||||
|
/* Have to cast away the const. But it's OK - we know terminfo won't
|
||||||
|
* really modify term */
|
||||||
|
int err;
|
||||||
|
if (setupterm ((char *) term, 1, &err) != OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 0; strfnames[i]; i++)
|
||||||
|
{
|
||||||
|
const char *name = strfnames[i];
|
||||||
const char *value = tigetstr (strnames[i]);
|
const char *value = tigetstr (strnames[i]);
|
||||||
#endif
|
#endif
|
||||||
|
// Only care about the key_* constants
|
||||||
|
if (strncmp (name, "key_", 4) != 0)
|
||||||
|
continue;
|
||||||
if (!value || value == (char*) -1)
|
if (!value || value == (char*) -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
struct trie_node *node = NULL;
|
trie_node_t *node = NULL;
|
||||||
if (strcmp (name + 4, "mouse") == 0)
|
if (!strcmp (name + 4, "mouse"))
|
||||||
{
|
mouse_report_string = value;
|
||||||
node = malloc (sizeof *node);
|
|
||||||
if (!node)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
node->type = TYPE_MOUSE;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
termkey_type_t type;
|
termkey_type_t type;
|
||||||
|
@ -241,7 +229,36 @@ load_terminfo (termkey_ti_t *ti, const char *term)
|
||||||
if (node && !insert_seq (ti, value, node))
|
if (node && !insert_seq (ti, value, node))
|
||||||
{
|
{
|
||||||
free (node);
|
free (node);
|
||||||
return 0;
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone the behaviour of ncurses for xterm mouse support
|
||||||
|
#ifdef HAVE_UNIBILIUM
|
||||||
|
const char *set_mouse_string = unibi_get_str (unibi, "XM");
|
||||||
|
#else
|
||||||
|
const char *set_mouse_string = tigetstr ("XM");
|
||||||
|
#endif
|
||||||
|
if (!set_mouse_string || set_mouse_string == (char *) -1)
|
||||||
|
ti->set_mouse_string = strdup ("\E[?1000%?%p1%{1}%=%th%el%;");
|
||||||
|
else
|
||||||
|
ti->set_mouse_string = strdup (set_mouse_string);
|
||||||
|
|
||||||
|
if (!mouse_report_string && strstr (term, "xterm"))
|
||||||
|
mouse_report_string = "\x1b[M";
|
||||||
|
if (mouse_report_string)
|
||||||
|
{
|
||||||
|
ti->have_mouse = true;
|
||||||
|
|
||||||
|
trie_node_t *node = malloc (sizeof *node);
|
||||||
|
if (!node)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
node->type = TYPE_MOUSE;
|
||||||
|
if (!insert_seq (ti, mouse_report_string, node))
|
||||||
|
{
|
||||||
|
free (node);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,13 +288,13 @@ load_terminfo (termkey_ti_t *ti, const char *term)
|
||||||
unibi_destroy (unibi);
|
unibi_destroy (unibi);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
new_driver (termkey_t *tk, const char *term)
|
new_driver (termkey_t *tk, const char *term)
|
||||||
{
|
{
|
||||||
termkey_ti_t *ti = malloc (sizeof *ti);
|
termkey_ti_t *ti = calloc (1, sizeof *ti);
|
||||||
if (!ti)
|
if (!ti)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -300,15 +317,14 @@ abort_free_ti:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static bool
|
||||||
write_string (termkey_t *tk, char *string)
|
write_string (termkey_t *tk, char *string)
|
||||||
{
|
{
|
||||||
if (tk->fd == -1 || !isatty (tk->fd) || !string)
|
if (tk->fd == -1 || !isatty (tk->fd) || !string)
|
||||||
return 1;
|
return true;
|
||||||
|
|
||||||
/* The terminfo database will contain keys in application cursor key mode.
|
// The terminfo database will contain keys in application cursor key mode.
|
||||||
* We may need to enable that mode
|
// We may need to enable that mode
|
||||||
*/
|
|
||||||
|
|
||||||
// Can't call putp or tputs because they suck and don't give us fd control
|
// Can't call putp or tputs because they suck and don't give us fd control
|
||||||
size_t len = strlen (string);
|
size_t len = strlen (string);
|
||||||
|
@ -316,17 +332,38 @@ write_string (termkey_t *tk, char *string)
|
||||||
{
|
{
|
||||||
ssize_t written = write (tk->fd, string, len);
|
ssize_t written = write (tk->fd, string, len);
|
||||||
if (written == -1)
|
if (written == -1)
|
||||||
return 0;
|
return false;
|
||||||
string += written;
|
string += written;
|
||||||
len -= written;
|
len -= written;
|
||||||
}
|
}
|
||||||
return 1;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
set_mouse (termkey_ti_t *ti, bool enable)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_UNIBILIUM
|
||||||
|
unibi_var_t params[9] = { enable, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
char start_string[unibi_run (ti->set_mouse_string, params, NULL, 0)];
|
||||||
|
unibi_run (ti->set_mouse_string, params,
|
||||||
|
start_string, sizeof start_string);
|
||||||
|
#else
|
||||||
|
char *start_string = tparm (ti->set_mouse_string,
|
||||||
|
enable, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
#endif
|
||||||
|
return write_string (ti->tk, start_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
start_driver (termkey_t *tk, void *info)
|
start_driver (termkey_t *tk, void *info)
|
||||||
{
|
{
|
||||||
termkey_ti_t *ti = info;
|
termkey_ti_t *ti = info;
|
||||||
|
// TODO: Don't start the mouse automatically, find a nice place to put
|
||||||
|
// a public function to be called by users.
|
||||||
|
// TODO: Try to autodetect rxvt and use its protocol instead of mode 1000
|
||||||
|
// TODO: Also give the user a choice to use 1005, 1006 or 1015
|
||||||
|
if (ti->have_mouse && !set_mouse (ti, true))
|
||||||
|
return false;
|
||||||
return write_string (tk, ti->start_string);
|
return write_string (tk, ti->start_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,6 +371,8 @@ static int
|
||||||
stop_driver (termkey_t *tk, void *info)
|
stop_driver (termkey_t *tk, void *info)
|
||||||
{
|
{
|
||||||
termkey_ti_t *ti = info;
|
termkey_ti_t *ti = info;
|
||||||
|
if (ti->have_mouse && !set_mouse (ti, false))
|
||||||
|
return false;
|
||||||
return write_string (tk, ti->stop_string);
|
return write_string (tk, ti->stop_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,6 +381,7 @@ free_driver (void *info)
|
||||||
{
|
{
|
||||||
termkey_ti_t *ti = info;
|
termkey_ti_t *ti = info;
|
||||||
free_trie (ti->root);
|
free_trie (ti->root);
|
||||||
|
free (ti->set_mouse_string);
|
||||||
free (ti->start_string);
|
free (ti->start_string);
|
||||||
free (ti->stop_string);
|
free (ti->stop_string);
|
||||||
free (ti);
|
free (ti);
|
||||||
|
|
|
@ -86,21 +86,21 @@ static inline void
|
||||||
termkey_key_get_linecol (const termkey_key_t *key, int *line, int *col)
|
termkey_key_get_linecol (const termkey_key_t *key, int *line, int *col)
|
||||||
{
|
{
|
||||||
if (col)
|
if (col)
|
||||||
*col = (unsigned char) key->code.mouse[1]
|
*col = ((unsigned char) key->code.mouse[1]
|
||||||
| ((unsigned char) key->code.mouse[3] & 0x0f) << 8;
|
| ((unsigned char) key->code.mouse[3] & 0x0f) << 8) - 1;
|
||||||
|
|
||||||
if (line)
|
if (line)
|
||||||
*line = (unsigned char) key->code.mouse[2]
|
*line = ((unsigned char) key->code.mouse[2]
|
||||||
| ((unsigned char) key->code.mouse[3] & 0x70) << 4;
|
| ((unsigned char) key->code.mouse[3] & 0x70) << 4) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
termkey_key_set_linecol (termkey_key_t *key, int line, int col)
|
termkey_key_set_linecol (termkey_key_t *key, int line, int col)
|
||||||
{
|
{
|
||||||
if (line > 0xfff)
|
if (++line > 0xfff)
|
||||||
line = 0xfff;
|
line = 0xfff;
|
||||||
|
|
||||||
if (col > 0x7ff)
|
if (++col > 0x7ff)
|
||||||
col = 0x7ff;
|
col = 0x7ff;
|
||||||
|
|
||||||
key->code.mouse[1] = (line & 0x0ff);
|
key->code.mouse[1] = (line & 0x0ff);
|
||||||
|
|
|
@ -137,6 +137,7 @@ struct termkey_key
|
||||||
uint32_t codepoint; /* TERMKEY_TYPE_KEY */
|
uint32_t codepoint; /* TERMKEY_TYPE_KEY */
|
||||||
int number; /* TERMKEY_TYPE_FUNCTION */
|
int number; /* TERMKEY_TYPE_FUNCTION */
|
||||||
termkey_sym_t sym; /* TERMKEY_TYPE_KEYSYM */
|
termkey_sym_t sym; /* TERMKEY_TYPE_KEYSYM */
|
||||||
|
// TODO: rewrite this insanity
|
||||||
char mouse[4]; /* TERMKEY_TYPE_MOUSE */
|
char mouse[4]; /* TERMKEY_TYPE_MOUSE */
|
||||||
/* opaque, see termkey_interpret_mouse() */
|
/* opaque, see termkey_interpret_mouse() */
|
||||||
} code;
|
} code;
|
||||||
|
|
Loading…
Reference in New Issue