diff --git a/docs/man/kmscon.1.xml.in b/docs/man/kmscon.1.xml.in
index f38262a3..950ab73c 100644
--- a/docs/man/kmscon.1.xml.in
+++ b/docs/man/kmscon.1.xml.in
@@ -327,6 +327,18 @@
(default: 50)
+
+
+
+
+ Enable mouse/touchpad/trackpoint in kmscon (default: off).
+ It allows to select, and copy/paste text with a pointing device,
+ and also to scroll with the mouse wheel.
+ It's still experimental, and may not work with specific devices.
+
+
+
+
Grabs / Keyboard Shortcuts:
diff --git a/docs/man/kmscon.conf.1.xml.in b/docs/man/kmscon.conf.1.xml.in
index d8b3bac6..0a3005d5 100644
--- a/docs/man/kmscon.conf.1.xml.in
+++ b/docs/man/kmscon.conf.1.xml.in
@@ -68,6 +68,7 @@ xkb-model=pc102
xkb-layout=de
xkb-repeat-delay=200
xkb-repeat-rate=65
+mouse
### Video Options ###
drm
@@ -262,6 +263,17 @@ font-name=Ubuntu Mono
+
+
+
+ Enable mouse/touchpad/trackpoint in kmscon (default: off).
+ It allows to select, and copy/paste text with a pointing device,
+ and also to scroll with the mouse wheel.
+ It's still experimental, and may not work with specific devices.
+
+
+
+
### Grabs/Keyboard-Shortcuts ###
diff --git a/meson.build b/meson.build
index af837860..2b5266ee 100644
--- a/meson.build
+++ b/meson.build
@@ -47,7 +47,7 @@ systemdsystemunitdir = systemd_deps.get_variable('systemdsystemunitdir', default
fs = import('fs')
xkbcommon_deps = dependency('xkbcommon', version: '>=0.5.0')
-libtsm_deps = dependency('libtsm', version: '>=4.1.0')
+libtsm_deps = dependency('libtsm', version: '>=4.3.0')
libudev_deps = dependency('libudev', version: '>=172')
dl_deps = dependency('dl')
threads_deps = dependency('threads')
diff --git a/src/kmscon_conf.c b/src/kmscon_conf.c
index fd38bfd6..2be56f8c 100644
--- a/src/kmscon_conf.c
+++ b/src/kmscon_conf.c
@@ -110,6 +110,8 @@ static void print_help()
"\t Initial delay for key-repeat in ms\n"
"\t --xkb-repeat-rate [50]\n"
"\t Delay between two key repeats in ms\n"
+ "\t --mouse [off]\n"
+ "\t Enable experimental mouse support\n"
"\n"
"Grabs / Keyboard-Shortcuts:\n"
"\t --grab-scroll-up [Up]\n"
@@ -733,6 +735,7 @@ int kmscon_conf_new(struct conf_ctx **out)
CONF_OPTION_STRING(0, "xkb-compose-file", &conf->xkb_compose_file, ""),
CONF_OPTION_UINT(0, "xkb-repeat-delay", &conf->xkb_repeat_delay, 250),
CONF_OPTION_UINT(0, "xkb-repeat-rate", &conf->xkb_repeat_rate, 50),
+ CONF_OPTION_BOOL(0, "mouse", &conf->mouse, false),
/* Grabs / Keyboard-Shortcuts */
CONF_OPTION_GRAB(0, "grab-scroll-up", &conf->grab_scroll_up, &def_grab_scroll_up),
diff --git a/src/kmscon_conf.h b/src/kmscon_conf.h
index e62ba18b..1964d22a 100644
--- a/src/kmscon_conf.h
+++ b/src/kmscon_conf.h
@@ -111,6 +111,8 @@ struct kmscon_conf_t {
unsigned int xkb_repeat_delay;
/* keyboard key-repeat rate */
unsigned int xkb_repeat_rate;
+ /* Enable mouse support */
+ bool mouse;
/* Grabs / Keyboard-Shortcuts */
/* scroll-up grab */
diff --git a/src/kmscon_main.c b/src/kmscon_main.c
index 14497134..2322d646 100644
--- a/src/kmscon_main.c
+++ b/src/kmscon_main.c
@@ -476,7 +476,7 @@ static void app_monitor_event(struct uterm_monitor *mon,
case UTERM_MONITOR_INPUT:
log_debug("new input device %s on seat %s",
ev->dev_node, seat->name);
- kmscon_seat_add_input(seat->seat, ev->dev_node);
+ kmscon_seat_add_input(seat->seat, ev->dev_node, seat->conf->mouse);
break;
}
break;
diff --git a/src/kmscon_seat.c b/src/kmscon_seat.c
index 692762bf..ade4433c 100644
--- a/src/kmscon_seat.c
+++ b/src/kmscon_seat.c
@@ -577,7 +577,7 @@ static int seat_vt_event(struct uterm_vt *vt, struct uterm_vt_event *ev,
}
static void seat_input_event(struct uterm_input *input,
- struct uterm_input_event *ev,
+ struct uterm_input_key_event *ev,
void *data)
{
struct kmscon_seat *seat = data;
@@ -766,7 +766,7 @@ int kmscon_seat_new(struct kmscon_seat **out,
if (ret)
goto err_conf;
- ret = uterm_input_register_cb(seat->input, seat_input_event, seat);
+ ret = uterm_input_register_key_cb(seat->input, seat_input_event, seat);
if (ret)
goto err_input;
@@ -788,7 +788,7 @@ int kmscon_seat_new(struct kmscon_seat **out,
return 0;
err_input_cb:
- uterm_input_unregister_cb(seat->input, seat_input_event, seat);
+ uterm_input_unregister_key_cb(seat->input, seat_input_event, seat);
err_input:
uterm_input_unref(seat->input);
err_conf:
@@ -834,7 +834,7 @@ void kmscon_seat_free(struct kmscon_seat *seat)
}
uterm_vt_deallocate(seat->vt);
- uterm_input_unregister_cb(seat->input, seat_input_event, seat);
+ uterm_input_unregister_key_cb(seat->input, seat_input_event, seat);
uterm_input_unref(seat->input);
kmscon_conf_free(seat->conf_ctx);
free(seat->name);
@@ -924,12 +924,12 @@ void kmscon_seat_refresh_display(struct kmscon_seat *seat,
}
}
-int kmscon_seat_add_input(struct kmscon_seat *seat, const char *node)
+int kmscon_seat_add_input(struct kmscon_seat *seat, const char *node, bool mouse)
{
if (!seat || !node)
return -EINVAL;
- uterm_input_add_dev(seat->input, node);
+ uterm_input_add_dev(seat->input, node, mouse);
return 0;
}
diff --git a/src/kmscon_seat.h b/src/kmscon_seat.h
index 439e3582..a179caf4 100644
--- a/src/kmscon_seat.h
+++ b/src/kmscon_seat.h
@@ -90,7 +90,7 @@ void kmscon_seat_remove_display(struct kmscon_seat *seat,
struct uterm_display *disp);
void kmscon_seat_refresh_display(struct kmscon_seat *seat,
struct uterm_display *disp);
-int kmscon_seat_add_input(struct kmscon_seat *seat, const char *node);
+int kmscon_seat_add_input(struct kmscon_seat *seat, const char *node, bool mouse);
void kmscon_seat_remove_input(struct kmscon_seat *seat, const char *node);
const char *kmscon_seat_get_name(struct kmscon_seat *seat);
diff --git a/src/kmscon_terminal.c b/src/kmscon_terminal.c
index 7fa8eb8e..d5be714c 100644
--- a/src/kmscon_terminal.c
+++ b/src/kmscon_terminal.c
@@ -37,6 +37,7 @@
#include
#include "conf.h"
#include "eloop.h"
+#include "font.h"
#include "kmscon_conf.h"
#include "kmscon_seat.h"
#include "kmscon_terminal.h"
@@ -59,6 +60,17 @@ struct screen {
bool pending;
};
+struct kmscon_pointer {
+ bool visible;
+ bool select;
+ int32_t x;
+ int32_t y;
+ unsigned int posx;
+ unsigned int posy;
+ char *copy;
+ int copy_len;
+};
+
struct kmscon_terminal {
unsigned long ref;
struct ev_eloop *eloop;
@@ -82,6 +94,8 @@ struct kmscon_terminal {
struct kmscon_font_attr font_attr;
struct kmscon_font *font;
struct kmscon_font *bold_font;
+
+ struct kmscon_pointer pointer;
};
static void do_clear_margins(struct screen *scr)
@@ -130,6 +144,35 @@ static void do_clear_margins(struct screen *scr)
static int font_set(struct kmscon_terminal *term);
+
+static void coord_to_cell(struct kmscon_terminal *term, int32_t x, int32_t y, unsigned int *posx, unsigned int *posy)
+{
+ int fw = term->font->attr.width;
+ int fh = term->font->attr.height;
+ int w = tsm_screen_get_width(term->console);
+ int h = tsm_screen_get_height(term->console);
+
+ *posx = x / fw;
+ *posy = y / fh;
+
+ if (*posx >= w)
+ *posx = w;
+
+ if (*posy >= h)
+ *posy = h;
+}
+
+static void draw_pointer(struct screen *scr)
+{
+ struct tsm_screen_attr attr;
+
+ if (!scr->term->pointer.visible)
+ return;
+
+ tsm_vte_get_def_attr(scr->term->vte, &attr);
+ kmscon_text_draw_pointer(scr->txt, scr->term->pointer.x, scr->term->pointer.y, &attr);
+}
+
static void do_redraw_screen(struct screen *scr)
{
int ret;
@@ -142,6 +185,7 @@ static void do_redraw_screen(struct screen *scr)
kmscon_text_prepare(scr->txt);
tsm_screen_draw(scr->term->console, kmscon_text_draw_cb, scr->txt);
+ draw_pointer(scr);
kmscon_text_render(scr->txt);
ret = uterm_display_swap(scr->disp, false);
@@ -201,6 +245,49 @@ static bool has_kms_display(struct kmscon_terminal *term)
return false;
}
+/*
+ * Align the pointer maximum to the minimum width and height of all screens
+ * according to their orientation, as kmscon only support mirroring, and one
+ * terminal size for all screens.
+ */
+static void update_pointer_max_all(struct kmscon_terminal *term)
+{
+ struct shl_dlist *iter;
+ struct screen *scr;
+ struct uterm_mode *mode;
+ unsigned int max_x = INT_MAX;
+ unsigned int max_y = INT_MAX;
+ unsigned int sw, sh;
+
+ if (!term->awake)
+ return;
+
+ shl_dlist_for_each(iter, &term->screens) {
+ scr = shl_dlist_entry(iter, struct screen, list);
+
+ mode = uterm_display_get_current(scr->disp);
+ if (!mode)
+ continue;
+
+ if (scr->txt->orientation == OR_NORMAL || scr->txt->orientation == OR_UPSIDE_DOWN) {
+ sw = uterm_mode_get_width(mode);
+ sh = uterm_mode_get_height(mode);
+ } else {
+ sw = uterm_mode_get_height(mode);
+ sh = uterm_mode_get_width(mode);
+ }
+ if (!sw || !sh)
+ continue;
+
+ if (sw < max_x)
+ max_x = sw;
+ if (sh < max_y)
+ max_y = sh;
+ }
+ if (max_x < INT_MAX && max_y < INT_MAX)
+ uterm_input_set_pointer_max(term->input, max_x, max_y);
+}
+
static void redraw_all_test(struct kmscon_terminal *term)
{
struct shl_dlist *iter;
@@ -245,6 +332,15 @@ static void osc_event(struct tsm_vte *vte, const char *osc_string,
}
}
+static void mouse_event(struct tsm_vte *vte, enum tsm_mouse_track_mode track_mode,
+ bool track_pixels, void *data)
+{
+ struct kmscon_terminal *term = data;
+
+ term->pointer.select = false;
+ tsm_screen_selection_reset(term->console);
+}
+
/*
* Resize terminal
* We support multiple monitors per terminal. As some software-rendering
@@ -264,6 +360,8 @@ static void terminal_resize(struct kmscon_terminal *term,
{
bool resize = false;
+ update_pointer_max_all(term);
+
if (!term->min_cols || (cols > 0 && cols < term->min_cols)) {
term->min_cols = cols;
resize = true;
@@ -500,7 +598,7 @@ static void rm_display(struct kmscon_terminal *term, struct uterm_display *disp)
}
static void input_event(struct uterm_input *input,
- struct uterm_input_event *ev,
+ struct uterm_input_key_event *ev,
void *data)
{
struct kmscon_terminal *term = data;
@@ -585,6 +683,124 @@ static void input_event(struct uterm_input *input,
}
}
+static void start_selection(struct tsm_screen *console, unsigned int x, unsigned int y)
+{
+ tsm_screen_selection_reset(console);
+ tsm_screen_selection_start(console, x, y);
+}
+
+static void update_selection(struct tsm_screen *console, unsigned int x, unsigned int y)
+{
+ tsm_screen_selection_target(console, x, y);
+}
+
+static void copy_selection(struct kmscon_terminal *term)
+{
+ if (term->pointer.copy) {
+ free(term->pointer.copy);
+ term->pointer.copy = NULL;
+ term->pointer.copy_len = 0;
+ }
+ term->pointer.copy_len = tsm_screen_selection_copy(term->console, &term->pointer.copy);
+}
+
+static void forward_pointer_event(struct kmscon_terminal *term, struct uterm_input_pointer_event *ev)
+{
+ unsigned int event;
+
+ switch (ev->event) {
+ case UTERM_MOVED:
+ event = TSM_MOUSE_EVENT_MOVED;
+ break;
+ case UTERM_BUTTON:
+ if (ev->pressed)
+ event = TSM_MOUSE_EVENT_PRESSED;
+ else
+ event = TSM_MOUSE_EVENT_RELEASED;
+ break;
+ default:
+ return;
+ }
+ tsm_vte_handle_mouse(term->vte, term->pointer.posx, term->pointer.posy,
+ term->pointer.x, term->pointer.y, ev->button, event, 0);
+}
+
+static void handle_pointer_button(struct kmscon_terminal *term, struct uterm_input_pointer_event *ev)
+{
+ switch(ev->button) {
+ case 0:
+ if (ev->pressed) {
+ if (ev->double_click) {
+ tsm_screen_selection_word(term->console, term->pointer.posx, term->pointer.posy);
+ copy_selection(term);
+ term->pointer.select = false;
+ } else {
+ term->pointer.select = true;
+ start_selection(term->console, term->pointer.posx, term->pointer.posy);
+ }
+ } else {
+ if (term->pointer.select)
+ copy_selection(term);
+ term->pointer.select = false;
+ }
+ break;
+ case 1:
+ term->pointer.select = false;
+ tsm_screen_selection_reset(term->console);
+ break;
+ case 2:
+ if (ev->pressed) {
+ kmscon_pty_write(term->pty, term->pointer.copy, term->pointer.copy_len);
+ tsm_screen_selection_reset(term->console);
+ }
+ }
+}
+
+static void pointer_event(struct uterm_input *input,
+ struct uterm_input_pointer_event *ev,
+ void *data)
+{
+ struct kmscon_terminal *term = data;
+
+ if (ev->event == UTERM_MOVED) {
+ term->pointer.x = ev->pointer_x;
+ term->pointer.y = ev->pointer_y;
+
+ coord_to_cell(term, term->pointer.x, term->pointer.y, &term->pointer.posx, &term->pointer.posy);
+ term->pointer.visible = true;
+ }
+
+ if (tsm_vte_get_mouse_mode(term->vte) != TSM_MOUSE_TRACK_DISABLE &&
+ ev->event != UTERM_SYNC) {
+ forward_pointer_event(term, ev);
+ return;
+ }
+
+ switch (ev->event) {
+ default:
+ break;
+ case UTERM_MOVED:
+ if (term->pointer.select)
+ update_selection(term->console,term->pointer.posx, term->pointer.posy);
+ break;
+ case UTERM_BUTTON:
+ handle_pointer_button(term, ev);
+ break;
+ case UTERM_WHEEL:
+ if (ev->wheel > 0)
+ tsm_screen_sb_up(term->console, 3);
+ else
+ tsm_screen_sb_down(term->console, 3);
+ break;
+ case UTERM_SYNC:
+ redraw_all(term);
+ break;
+ case UTERM_HIDE_TIMEOUT:
+ term->pointer.visible = false;
+ break;
+ }
+}
+
static void rm_all_screens(struct kmscon_terminal *term)
{
struct shl_dlist *iter;
@@ -615,6 +831,8 @@ static int terminal_open(struct kmscon_terminal *term)
return ret;
term->opened = true;
+
+ update_pointer_max_all(term);
redraw_all(term);
return 0;
}
@@ -631,7 +849,8 @@ static void terminal_destroy(struct kmscon_terminal *term)
terminal_close(term);
rm_all_screens(term);
- uterm_input_unregister_cb(term->input, input_event, term);
+ uterm_input_unregister_pointer_cb(term->input, pointer_event, term);
+ uterm_input_unregister_key_cb(term->input, input_event, term);
ev_eloop_rm_fd(term->ptyfd);
kmscon_pty_unref(term->pty);
kmscon_font_unref(term->bold_font);
@@ -745,6 +964,7 @@ int kmscon_terminal_register(struct kmscon_session **out,
BUILD_BACKSPACE_SENDS_DELETE);
tsm_vte_set_osc_cb(term->vte, osc_event, (void *)term);
+ tsm_vte_set_mouse_cb(term->vte, mouse_event, (void *)term);
ret = tsm_vte_set_palette(term->vte, term->conf->palette);
if (ret)
@@ -792,15 +1012,21 @@ int kmscon_terminal_register(struct kmscon_session **out,
if (ret)
goto err_pty;
- ret = uterm_input_register_cb(term->input, input_event, term);
+ ret = uterm_input_register_key_cb(term->input, input_event, term);
if (ret)
goto err_ptyfd;
+ if (term->conf->mouse) {
+ ret = uterm_input_register_pointer_cb(term->input, pointer_event, term);
+ if (ret)
+ goto err_input;
+ }
+
ret = kmscon_seat_register_session(seat, &term->session, session_event,
term);
if (ret) {
log_error("cannot register session for terminal: %d", ret);
- goto err_input;
+ goto err_pointer;
}
ev_eloop_ref(term->eloop);
@@ -809,8 +1035,10 @@ int kmscon_terminal_register(struct kmscon_session **out,
log_debug("new terminal object %p", term);
return 0;
+err_pointer:
+ uterm_input_unregister_pointer_cb(term->input, pointer_event, term);
err_input:
- uterm_input_unregister_cb(term->input, input_event, term);
+ uterm_input_unregister_key_cb(term->input, input_event, term);
err_ptyfd:
ev_eloop_rm_fd(term->ptyfd);
err_pty:
diff --git a/src/meson.build b/src/meson.build
index dee686c3..3f6db43f 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -103,6 +103,7 @@ uterm_srcs = [
'uterm_vt.c',
'uterm_input.c',
'uterm_input_uxkb.c',
+ 'uterm_input_pointer.c',
embed_gen.process('uterm_input_fallback.xkb', extra_args: keymap_regex),
]
uterm_dep = [
diff --git a/src/text.c b/src/text.c
index 6d1b496d..29cb079d 100644
--- a/src/text.c
+++ b/src/text.c
@@ -466,6 +466,30 @@ int kmscon_text_draw(struct kmscon_text *txt,
return txt->ops->draw(txt, id, ch, len, width, posx, posy, attr);
}
+/**
+ * kmscon_text_draw_pointer:
+ * @txt: valid text renderer
+ * @x: X-position of the center of the pointer in pixel
+ * @y: Y-position of the center of the pointer in pixel
+ * @attr: glyph attributes
+ *
+ * This draws a single I glyph at the requested position. The position is a
+ * a pixel position! You must precede this call with kmscon_text_prepare().
+ * Use this function to feed the mouse pointer into the rendering pipeline
+ * and finally call kmscon_text_render().
+ *
+ * Returns: 0 on success or negative error code if it couldn't be drawn.
+ */
+int kmscon_text_draw_pointer(struct kmscon_text *txt,
+ unsigned int x, unsigned int y,
+ const struct tsm_screen_attr *attr)
+{
+ if (!txt || !txt->rendering || !txt->ops->draw_pointer)
+ return -EINVAL;
+
+ return txt->ops->draw_pointer(txt, x, y, attr);
+}
+
/**
* kmscon_text_render:
* @txt: valid text renderer
diff --git a/src/text.h b/src/text.h
index 0c51ce94..4fde896b 100644
--- a/src/text.h
+++ b/src/text.h
@@ -82,6 +82,10 @@ struct kmscon_text_ops {
unsigned int width,
unsigned int posx, unsigned int posy,
const struct tsm_screen_attr *attr);
+ int (*draw_pointer) (struct kmscon_text *txt,
+ unsigned int x,
+ unsigned int y,
+ const struct tsm_screen_attr *attr);
int (*render) (struct kmscon_text *txt);
void (*abort) (struct kmscon_text *txt);
};
@@ -113,6 +117,9 @@ int kmscon_text_draw(struct kmscon_text *txt,
unsigned int width,
unsigned int posx, unsigned int posy,
const struct tsm_screen_attr *attr);
+int kmscon_text_draw_pointer(struct kmscon_text *txt,
+ unsigned int x, unsigned int y,
+ const struct tsm_screen_attr *attr);
int kmscon_text_render(struct kmscon_text *txt);
void kmscon_text_abort(struct kmscon_text *txt);
diff --git a/src/text_bblit.c b/src/text_bblit.c
index 0c1a3240..1d6dcc3a 100644
--- a/src/text_bblit.c
+++ b/src/text_bblit.c
@@ -38,6 +38,7 @@
#include
#include "font_rotate.h"
#include "shl_log.h"
+#include "shl_misc.h"
#include "text.h"
#include "uterm_video.h"
@@ -242,6 +243,73 @@ static int bblit_draw(struct kmscon_text *txt,
return ret;
}
+static int bblit_draw_pointer(struct kmscon_text *txt,
+ unsigned int pointer_x, unsigned int pointer_y,
+ const struct tsm_screen_attr *attr)
+{
+ struct uterm_video_buffer *bb_glyph;
+ struct uterm_mode *mode;
+ uint32_t ch = 'I';
+ uint64_t id = ch;
+ unsigned int sw, sh;
+ unsigned int m_x, m_y, x, y;
+ int ret;
+
+ mode = uterm_display_get_current(txt->disp);
+ if (!mode)
+ return -EINVAL;
+ sw = uterm_mode_get_width(mode);
+ sh = uterm_mode_get_height(mode);
+
+ if (txt->orientation == OR_NORMAL || txt->orientation == OR_UPSIDE_DOWN) {
+ m_x = SHL_DIV_ROUND_UP(FONT_WIDTH(txt), 2);
+ m_y = SHL_DIV_ROUND_UP(FONT_HEIGHT(txt), 2);
+ } else {
+ m_x = SHL_DIV_ROUND_UP(FONT_HEIGHT(txt), 2);
+ m_y = SHL_DIV_ROUND_UP(FONT_WIDTH(txt), 2);
+ }
+
+ ret = find_glyph(txt, &bb_glyph, id, &ch, 1, attr);
+ if (ret)
+ return ret;
+
+ switch (txt->orientation) {
+ default:
+ case OR_NORMAL:
+ x = pointer_x;
+ y = pointer_y;
+ break;
+ case OR_UPSIDE_DOWN:
+ x = sw - pointer_x;
+ y = sh - pointer_y;
+ break;
+ case OR_RIGHT:
+ x = sw - pointer_y;
+ y = pointer_x;
+ break;
+ case OR_LEFT:
+ x = pointer_y;
+ y = sh - pointer_x;
+ break;
+ }
+ if (x < m_x)
+ x = m_x;
+ if (x + m_x > sw)
+ x = sw - m_x;
+ if (y < m_y)
+ y = m_y;
+ if (y + m_y > sh)
+ y = sh - m_y;
+ x -= m_x;
+ y -= m_y;
+
+ /* draw glyph */
+ ret = uterm_display_fake_blend(txt->disp, bb_glyph, x, y,
+ attr->fr, attr->fg, attr->fb,
+ attr->br, attr->bg, attr->bb);
+ return ret;
+}
+
struct kmscon_text_ops kmscon_text_bblit_ops = {
.name = "bblit",
.owner = NULL,
@@ -252,6 +320,7 @@ struct kmscon_text_ops kmscon_text_bblit_ops = {
.rotate = bblit_rotate,
.prepare = NULL,
.draw = bblit_draw,
+ .draw_pointer = bblit_draw_pointer,
.render = NULL,
.abort = NULL,
};
diff --git a/src/text_bbulk.c b/src/text_bbulk.c
index f22d2dc3..ae2cdca4 100644
--- a/src/text_bbulk.c
+++ b/src/text_bbulk.c
@@ -32,7 +32,6 @@
* pushes all of them at once to the video device.
*/
-#include
#include
#include
#include
@@ -41,6 +40,7 @@
#include "font_rotate.h"
#include "shl_hashtable.h"
#include "shl_log.h"
+#include "shl_misc.h"
#include "text.h"
#include "uterm_video.h"
@@ -48,6 +48,8 @@
struct bbulk {
struct uterm_video_blend_req *reqs;
+ unsigned int req_len;
+ unsigned int req_total_len;
struct shl_hashtable *glyphs;
struct shl_hashtable *bold_glyphs;
};
@@ -101,10 +103,12 @@ static int bbulk_set(struct kmscon_text *txt)
txt->rows = sw / FONT_HEIGHT(txt);
txt->cols = sh / FONT_WIDTH(txt);
}
- bb->reqs = malloc(sizeof(*bb->reqs) * txt->cols * txt->rows);
+
+ bb->req_total_len = txt->cols * txt->rows + 1; // + 1 for the pointer
+ bb->reqs = malloc(sizeof(*bb->reqs) * bb->req_total_len);
if (!bb->reqs)
return -ENOMEM;
- memset(bb->reqs, 0, sizeof(*bb->reqs) * txt->cols * txt->rows);
+ memset(bb->reqs, 0, sizeof(*bb->reqs) * bb->req_total_len);
for (i = 0; i < txt->rows; ++i) {
for (j = 0; j < txt->cols; ++j) {
@@ -277,13 +281,94 @@ static int bbulk_draw(struct kmscon_text *txt,
return 0;
}
+static int bblit_draw_pointer(struct kmscon_text *txt,
+ unsigned int pointer_x, unsigned int pointer_y,
+ const struct tsm_screen_attr *attr)
+{
+ struct bbulk *bb = txt->data;
+ struct uterm_video_blend_req *req;
+ struct uterm_video_buffer *bb_glyph;
+ struct uterm_mode *mode;
+ uint32_t ch = 'I';
+ uint64_t id = ch;
+ unsigned int sw, sh;
+ unsigned int m_x, m_y, x, y;
+ int ret;
+
+ mode = uterm_display_get_current(txt->disp);
+ if (!mode)
+ return -EINVAL;
+ sw = uterm_mode_get_width(mode);
+ sh = uterm_mode_get_height(mode);
+
+ if (txt->orientation == OR_NORMAL || txt->orientation == OR_UPSIDE_DOWN) {
+ m_x = SHL_DIV_ROUND_UP(FONT_WIDTH(txt), 2);
+ m_y = SHL_DIV_ROUND_UP(FONT_HEIGHT(txt), 2);
+ } else {
+ m_x = SHL_DIV_ROUND_UP(FONT_HEIGHT(txt), 2);
+ m_y = SHL_DIV_ROUND_UP(FONT_WIDTH(txt), 2);
+ }
+
+ // pointer is the last request
+ req = &bb->reqs[bb->req_total_len - 1];
+
+ ret = find_glyph(txt, &bb_glyph, id, &ch, 1, attr);
+ if (ret)
+ return ret;
+
+ req->buf = bb_glyph;
+
+ switch (txt->orientation) {
+ default:
+ case OR_NORMAL:
+ x = pointer_x;
+ y = pointer_y;
+ break;
+ case OR_UPSIDE_DOWN:
+ x = sw - pointer_x;
+ y = sh - pointer_y;
+ break;
+ case OR_RIGHT:
+ x = sw - pointer_y;
+ y = pointer_x;
+ break;
+ case OR_LEFT:
+ x = pointer_y;
+ y = sh - pointer_x;
+ break;
+ }
+ if (x < m_x)
+ x = m_x;
+ if (x + m_x > sw)
+ x = sw - m_x;
+ if (y < m_y)
+ y = m_y;
+ if (y + m_y > sh)
+ y = sh - m_y;
+ x -= m_x;
+ y -= m_y;
+
+ req->x = x;
+ req->y = y;
+
+ req->fr = attr->fr;
+ req->fg = attr->fg;
+ req->fb = attr->fb;
+ req->br = attr->br;
+ req->bg = attr->bg;
+ req->bb = attr->bb;
+
+ bb->req_len = bb->req_total_len;
+ return 0;
+}
+
static int bbulk_render(struct kmscon_text *txt)
{
struct bbulk *bb = txt->data;
int ret;
ret = uterm_display_fake_blendv(txt->disp, bb->reqs,
- txt->cols * txt->rows);
+ bb->req_len);
return ret;
}
@@ -293,9 +378,9 @@ static int bbulk_prepare(struct kmscon_text *txt)
int i;
// Clear previous requests
- for (i = 0; i < txt->rows * txt->cols; ++i)
+ for (i = 0; i < bb->req_total_len; ++i)
bb->reqs[i].buf = NULL;
-
+ bb->req_len = txt->cols * txt->rows;
return 0;
}
@@ -309,6 +394,7 @@ struct kmscon_text_ops kmscon_text_bbulk_ops = {
.rotate = bbulk_rotate,
.prepare = bbulk_prepare,
.draw = bbulk_draw,
+ .draw_pointer = bblit_draw_pointer,
.render = bbulk_render,
.abort = NULL,
};
diff --git a/src/text_gltex.c b/src/text_gltex.c
index 6a1c8f39..4997514e 100644
--- a/src/text_gltex.c
+++ b/src/text_gltex.c
@@ -344,7 +344,7 @@ static struct atlas *get_atlas(struct kmscon_text *txt, unsigned int num)
log_debug("new atlas of size %ux%u for %zu", width, height, newsize);
- nsize = txt->cols * txt->rows;
+ nsize = txt->cols * txt->rows + 1; // +1 for the mouse pointer
atlas->cache_pos = malloc(sizeof(GLfloat) * nsize * 2 * 6);
if (!atlas->cache_pos)
@@ -602,6 +602,7 @@ static int gltex_draw(struct kmscon_text *txt,
struct gltex *gt = txt->data;
struct atlas *atlas;
struct glyph *glyph;
+ float gl_x1, gl_x2, gl_y1, gl_y2;
int ret, i, idx;
if (!width)
@@ -618,45 +619,39 @@ static int gltex_draw(struct kmscon_text *txt,
if (atlas->cache_num >= atlas->cache_size)
return -ERANGE;
- atlas->cache_pos[atlas->cache_num * 2 * 6 + 0] =
- gt->advance_x * posx - 1;
- atlas->cache_pos[atlas->cache_num * 2 * 6 + 1] =
- 1 - gt->advance_y * posy;
- atlas->cache_pos[atlas->cache_num * 2 * 6 + 2] =
- gt->advance_x * posx - 1;
- atlas->cache_pos[atlas->cache_num * 2 * 6 + 3] =
- 1 - (gt->advance_y * posy + gt->advance_y);
- atlas->cache_pos[atlas->cache_num * 2 * 6 + 4] =
- gt->advance_x * posx + width * gt->advance_x - 1;
- atlas->cache_pos[atlas->cache_num * 2 * 6 + 5] =
- 1 - (gt->advance_y * posy + gt->advance_y);
-
- atlas->cache_pos[atlas->cache_num * 2 * 6 + 6] =
- gt->advance_x * posx - 1;
- atlas->cache_pos[atlas->cache_num * 2 * 6 + 7] =
- 1 - gt->advance_y * posy;
- atlas->cache_pos[atlas->cache_num * 2 * 6 + 8] =
- gt->advance_x * posx + width * gt->advance_x - 1;
- atlas->cache_pos[atlas->cache_num * 2 * 6 + 9] =
- 1 - (gt->advance_y * posy + gt->advance_y);
- atlas->cache_pos[atlas->cache_num * 2 * 6 + 10] =
- gt->advance_x * posx + width * gt->advance_x - 1;
- atlas->cache_pos[atlas->cache_num * 2 * 6 + 11] =
- 1 - gt->advance_y * posy;
-
- atlas->cache_texpos[atlas->cache_num * 2 * 6 + 0] = glyph->texoff;
- atlas->cache_texpos[atlas->cache_num * 2 * 6 + 1] = 0.0;
- atlas->cache_texpos[atlas->cache_num * 2 * 6 + 2] = glyph->texoff;
- atlas->cache_texpos[atlas->cache_num * 2 * 6 + 3] = 1.0;
- atlas->cache_texpos[atlas->cache_num * 2 * 6 + 4] = glyph->texoff + width;
- atlas->cache_texpos[atlas->cache_num * 2 * 6 + 5] = 1.0;
-
- atlas->cache_texpos[atlas->cache_num * 2 * 6 + 6] = glyph->texoff;
- atlas->cache_texpos[atlas->cache_num * 2 * 6 + 7] = 0.0;
- atlas->cache_texpos[atlas->cache_num * 2 * 6 + 8] = glyph->texoff + width;
- atlas->cache_texpos[atlas->cache_num * 2 * 6 + 9] = 1.0;
- atlas->cache_texpos[atlas->cache_num * 2 * 6 + 10] = glyph->texoff + width;
- atlas->cache_texpos[atlas->cache_num * 2 * 6 + 11] = 0.0;
+ idx = atlas->cache_num * 2 * 6;
+ gl_x1 = gt->advance_x * posx - 1.0;
+ gl_x2 = gl_x1 + width * gt->advance_x;
+ gl_y1 = 1.0 - gt->advance_y * posy;
+ gl_y2 = gl_y1 - gt->advance_y;
+
+ atlas->cache_pos[idx + 0] = gl_x1;
+ atlas->cache_pos[idx + 1] = gl_y1;
+ atlas->cache_pos[idx + 2] = gl_x1;
+ atlas->cache_pos[idx + 3] = gl_y2;
+ atlas->cache_pos[idx + 4] = gl_x2;
+ atlas->cache_pos[idx + 5] = gl_y2;
+
+ atlas->cache_pos[idx + 6] = gl_x1;
+ atlas->cache_pos[idx + 7] = gl_y1;
+ atlas->cache_pos[idx + 8] = gl_x2;
+ atlas->cache_pos[idx + 9] = gl_y2;
+ atlas->cache_pos[idx + 10] = gl_x2;
+ atlas->cache_pos[idx + 11] = gl_y1;
+
+ atlas->cache_texpos[idx + 0] = glyph->texoff;
+ atlas->cache_texpos[idx + 1] = 0.0;
+ atlas->cache_texpos[idx + 2] = glyph->texoff;
+ atlas->cache_texpos[idx + 3] = 1.0;
+ atlas->cache_texpos[idx + 4] = glyph->texoff + width;
+ atlas->cache_texpos[idx + 5] = 1.0;
+
+ atlas->cache_texpos[idx + 6] = glyph->texoff;
+ atlas->cache_texpos[idx + 7] = 0.0;
+ atlas->cache_texpos[idx + 8] = glyph->texoff + width;
+ atlas->cache_texpos[idx + 9] = 1.0;
+ atlas->cache_texpos[idx + 10] = glyph->texoff + width;
+ atlas->cache_texpos[idx + 11] = 0.0;
for (i = 0; i < 6; ++i) {
idx = atlas->cache_num * 3 * 6 + i * 3;
@@ -682,6 +677,92 @@ static int gltex_draw(struct kmscon_text *txt,
return 0;
}
+static int gltex_draw_pointer(struct kmscon_text *txt,
+ unsigned int x, unsigned int y,
+ const struct tsm_screen_attr *attr)
+{
+ struct gltex *gt = txt->data;
+ struct atlas *atlas;
+ struct glyph *glyph;
+ float gl_x1, gl_x2, gl_y1, gl_y2;
+ unsigned int sw, sh;
+ int ret, i, idx;
+ uint32_t ch = 'I';
+ uint64_t id = ch;
+
+ ret = find_glyph(txt, &glyph, id, &ch, 1, attr);
+ if (ret)
+ return ret;
+
+ atlas = glyph->atlas;
+
+ if (atlas->cache_num >= atlas->cache_size)
+ return -ERANGE;
+
+ if(txt->orientation == OR_NORMAL || txt->orientation == OR_UPSIDE_DOWN) {
+ sw = gt->sw;
+ sh = gt->sh;
+ } else {
+ sw = gt->sh;
+ sh = gt->sw;
+ }
+
+ if (x > sw)
+ x = sw;
+
+ if (y > sh)
+ y = sh;
+
+ gl_x1 = x * 2.0 / sw - 1.0 - gt->advance_x / 2.0;
+ gl_y1 = 1.0 - y * 2.0 / sh + gt->advance_y / 2.0;
+ gl_x2 = gl_x1 + gt->advance_x;
+ gl_y2 = gl_y1 - gt->advance_y;
+
+ idx = atlas->cache_num * 2 * 6;
+
+ atlas->cache_pos[idx + 0] = gl_x1;
+ atlas->cache_pos[idx + 1] = gl_y1;
+ atlas->cache_pos[idx + 2] = gl_x1;
+ atlas->cache_pos[idx + 3] = gl_y2;
+ atlas->cache_pos[idx + 4] = gl_x2;
+ atlas->cache_pos[idx + 5] = gl_y2;
+
+ atlas->cache_pos[idx + 6] = gl_x1;
+ atlas->cache_pos[idx + 7] = gl_y1;
+ atlas->cache_pos[idx + 8] = gl_x2;
+ atlas->cache_pos[idx + 9] = gl_y2;
+ atlas->cache_pos[idx + 10] = gl_x2;
+ atlas->cache_pos[idx + 11] = gl_y1;
+
+ atlas->cache_texpos[idx + 0] = glyph->texoff;
+ atlas->cache_texpos[idx + 1] = 0.0;
+ atlas->cache_texpos[idx + 2] = glyph->texoff;
+ atlas->cache_texpos[idx + 3] = 1.0;
+ atlas->cache_texpos[idx + 4] = glyph->texoff + 1.0;
+ atlas->cache_texpos[idx + 5] = 1.0;
+
+ atlas->cache_texpos[idx + 6] = glyph->texoff;
+ atlas->cache_texpos[idx + 7] = 0.0;
+ atlas->cache_texpos[idx + 8] = glyph->texoff + 1.0;
+ atlas->cache_texpos[idx + 9] = 1.0;
+ atlas->cache_texpos[idx + 10] = glyph->texoff + 1.0;
+ atlas->cache_texpos[idx + 11] = 0.0;
+
+ for (i = 0; i < 6; ++i) {
+ idx = atlas->cache_num * 3 * 6 + i * 3;
+ atlas->cache_fgcol[idx + 0] = attr->fr / 255.0;
+ atlas->cache_fgcol[idx + 1] = attr->fg / 255.0;
+ atlas->cache_fgcol[idx + 2] = attr->fb / 255.0;
+ atlas->cache_bgcol[idx + 0] = attr->br / 255.0;
+ atlas->cache_bgcol[idx + 1] = attr->bg / 255.0;
+ atlas->cache_bgcol[idx + 2] = attr->bb / 255.0;
+ }
+
+ ++atlas->cache_num;
+
+ return 0;
+}
+
static int gltex_render(struct kmscon_text *txt)
{
struct gltex *gt = txt->data;
@@ -748,6 +829,7 @@ struct kmscon_text_ops kmscon_text_gltex_ops = {
.rotate = gltex_rotate,
.prepare = gltex_prepare,
.draw = gltex_draw,
+ .draw_pointer = gltex_draw_pointer,
.render = gltex_render,
.abort = NULL,
};
diff --git a/src/text_pixman.c b/src/text_pixman.c
index 8f4da68c..5c29e11a 100644
--- a/src/text_pixman.c
+++ b/src/text_pixman.c
@@ -36,6 +36,7 @@
#include "font_rotate.h"
#include "shl_hashtable.h"
#include "shl_log.h"
+#include "shl_misc.h"
#include "text.h"
#include "uterm_video.h"
@@ -431,7 +432,7 @@ static int tp_draw(struct kmscon_text *txt,
* image for each glyph here.
* libc malloc() is pretty fast, but this still costs us a lot of
* rendering performance. */
- if (!fc.red && !fc.green && !fc.blue) {
+ if (fc.red == 0xff00 && fc.green == 0xff00 && fc.blue == 0xff00) {
col = tp->white;
pixman_image_ref(col);
} else {
@@ -491,6 +492,119 @@ static int tp_draw(struct kmscon_text *txt,
return 0;
}
+static int tp_draw_pointer(struct kmscon_text *txt,
+ unsigned int pointer_x, unsigned int pointer_y,
+ const struct tsm_screen_attr *attr)
+{
+ struct tp_pixman *tp = txt->data;
+ struct uterm_mode *mode;
+ struct tp_glyph *glyph;
+ uint32_t ch = 'I';
+ uint64_t id = ch;
+ int ret;
+ unsigned int x, y, w, h, sw, sh;
+ unsigned int m_x, m_y;
+ uint32_t bc;
+ pixman_color_t fc;
+ pixman_image_t *col;
+
+ mode = uterm_display_get_current(txt->disp);
+ if (!mode)
+ return -EINVAL;
+ sw = uterm_mode_get_width(mode);
+ sh = uterm_mode_get_height(mode);
+
+ ret = find_glyph(txt, &glyph, id, &ch, 1, attr);
+ if (ret)
+ return ret;
+
+ bc = (attr->br << 16) | (attr->bg << 8) | (attr->bb);
+ fc.red = attr->fr << 8;
+ fc.green = attr->fg << 8;
+ fc.blue = attr->fb << 8;
+ fc.alpha = 0xffff;
+
+ /* TODO: We _really_ should fix pixman to allow something like
+ * pixman_image_set_solid_fill(img, &fc) to avoid allocating a pixman
+ * image for each glyph here.
+ * libc malloc() is pretty fast, but this still costs us a lot of
+ * rendering performance. */
+ if (attr->fr == 0xff && attr->fg == 0xff && attr->fb == 0xff) {
+ col = tp->white;
+ pixman_image_ref(col);
+ } else {
+ col = pixman_image_create_solid_fill(&fc);
+ if (!col) {
+ log_error("cannot create pixman color image");
+ return -ENOMEM;
+ }
+ }
+
+ if (txt->orientation == OR_NORMAL || txt->orientation == OR_UPSIDE_DOWN) {
+ w = FONT_WIDTH(txt);
+ h = FONT_HEIGHT(txt);
+ } else {
+ w = FONT_HEIGHT(txt);
+ h = FONT_WIDTH(txt);
+ }
+
+ m_x = SHL_DIV_ROUND_UP(w, 2);
+ m_y = SHL_DIV_ROUND_UP(h, 2);
+
+ switch (txt->orientation) {
+ default:
+ case OR_NORMAL:
+ x = pointer_x;
+ y = pointer_y;
+ break;
+ case OR_UPSIDE_DOWN:
+ x = sw - pointer_x;
+ y = sh - pointer_y;
+ break;
+ case OR_RIGHT:
+ x = sw - pointer_y;
+ y = pointer_x;
+ break;
+ case OR_LEFT:
+ x = pointer_y;
+ y = sh - pointer_x;
+ break;
+ }
+ if (x < m_x)
+ x = m_x;
+ if (x + m_x > sw)
+ x = sw - m_x;
+ if (y < m_y)
+ y = m_y;
+ if (y + m_y > sh)
+ y = sh - m_y;
+ x -= m_x;
+ y -= m_y;
+
+ if (!bc) {
+ pixman_image_composite(PIXMAN_OP_SRC,
+ col,
+ glyph->surf,
+ tp->surf[tp->cur],
+ 0, 0, 0, 0,
+ x, y, w, h);
+ } else {
+ pixman_fill(tp->c_data, tp->c_stride / 4, tp->c_bpp,
+ x, y, w, h, bc);
+
+ pixman_image_composite(PIXMAN_OP_OVER,
+ col,
+ glyph->surf,
+ tp->surf[tp->cur],
+ 0, 0, 0, 0,
+ x, y, w, h);
+ }
+
+ pixman_image_unref(col);
+
+ return 0;
+}
+
static int tp_render(struct kmscon_text *txt)
{
struct tp_pixman *tp = txt->data;
@@ -519,6 +633,7 @@ struct kmscon_text_ops kmscon_text_pixman_ops = {
.rotate = tp_rotate,
.prepare = tp_prepare,
.draw = tp_draw,
+ .draw_pointer = tp_draw_pointer,
.render = tp_render,
.abort = NULL,
};
diff --git a/src/uterm_input.c b/src/uterm_input.c
index 5e64dfea..cec0798e 100644
--- a/src/uterm_input.c
+++ b/src/uterm_input.c
@@ -51,15 +51,27 @@
static void input_free_dev(struct uterm_input_dev *dev);
-static void notify_key(struct uterm_input_dev *dev,
- uint16_t type,
- uint16_t code,
- int32_t value)
+static void notify_event(struct uterm_input_dev *dev,
+ uint16_t type,
+ uint16_t code,
+ int32_t value)
{
- if (type != EV_KEY)
- return;
-
- uxkb_dev_process(dev, value, code);
+ switch (type) {
+ case EV_KEY:
+ if (dev->capabilities & UTERM_DEVICE_HAS_KEYS)
+ uxkb_dev_process(dev, value, code);
+ pointer_dev_button(dev, code, value);
+ break;
+ case EV_REL:
+ pointer_dev_rel(dev, code, value);
+ break;
+ case EV_ABS:
+ pointer_dev_abs(dev, code, value);
+ break;
+ case EV_SYN:
+ pointer_dev_sync(dev);
+ break;
+ }
}
static void input_data_dev(struct ev_fd *fd, int mask, void *data)
@@ -93,7 +105,7 @@ static void input_data_dev(struct ev_fd *fd, int mask, void *data)
} else {
n = len / sizeof(*ev);
for (i = 0; i < n; i++)
- notify_key(dev, ev[i].type, ev[i].code,
+ notify_event(dev, ev[i].type, ev[i].code,
ev[i].value);
}
}
@@ -112,8 +124,8 @@ static int input_wake_up_dev(struct uterm_input_dev *dev)
dev->node, errno);
return -EFAULT;
}
-
- uxkb_dev_wake_up(dev);
+ if (dev->capabilities & UTERM_DEVICE_HAS_KEYS)
+ uxkb_dev_wake_up(dev);
ret = ev_eloop_new_fd(dev->input->eloop, &dev->fd, dev->rfd,
EV_READABLE, input_data_dev, dev);
@@ -131,7 +143,8 @@ static void input_sleep_dev(struct uterm_input_dev *dev)
if (dev->rfd < 0)
return;
- uxkb_dev_sleep(dev);
+ if (dev->capabilities & UTERM_DEVICE_HAS_KEYS)
+ uxkb_dev_sleep(dev);
dev->repeating = false;
ev_timer_update(dev->repeat_timer, NULL);
@@ -141,6 +154,80 @@ static void input_sleep_dev(struct uterm_input_dev *dev)
dev->rfd = -1;
}
+static int input_init_keyboard(struct uterm_input_dev *dev)
+{
+ dev->num_syms = 1;
+ dev->event.keysyms = malloc(sizeof(uint32_t) * dev->num_syms);
+ if (!dev->event.keysyms)
+ return -1;
+ dev->event.codepoints = malloc(sizeof(uint32_t) * dev->num_syms);
+ if (!dev->event.codepoints)
+ goto err_syms;
+ dev->repeat_event.keysyms = malloc(sizeof(uint32_t) * dev->num_syms);
+ if (!dev->repeat_event.keysyms)
+ goto err_codepoints;
+ dev->repeat_event.codepoints = malloc(sizeof(uint32_t) * dev->num_syms);
+ if (!dev->repeat_event.codepoints)
+ goto err_rsyms;
+
+ if (uxkb_dev_init(dev))
+ goto err_rcodepoints;
+
+ return 0;
+
+err_rcodepoints:
+ free(dev->repeat_event.codepoints);
+err_rsyms:
+ free(dev->repeat_event.keysyms);
+err_codepoints:
+ free(dev->event.codepoints);
+err_syms:
+ free(dev->event.keysyms);
+ return -1;
+}
+
+static void input_exit_keyboard(struct uterm_input_dev *dev)
+{
+ uxkb_dev_destroy(dev);
+ free(dev->repeat_event.codepoints);
+ free(dev->repeat_event.keysyms);
+ free(dev->event.codepoints);
+ free(dev->event.keysyms);
+}
+
+static int input_init_abs(struct uterm_input_dev *dev)
+{
+ struct input_absinfo info;
+ int ret, fd;
+
+ fd = open(dev->node, O_NONBLOCK | O_CLOEXEC | O_RDONLY);
+ if (fd < 0)
+ return 0;
+
+ ret = ioctl(fd, EVIOCGABS(ABS_X), &info);
+ if (ret < 0)
+ goto err_closefd;
+
+ dev->pointer.min_x = info.minimum;
+ dev->pointer.max_x = info.maximum;
+
+ ret = ioctl(fd, EVIOCGABS(ABS_Y), &info);
+ if (ret < 0)
+ goto err_closefd;
+
+ dev->pointer.min_y = info.minimum;
+ dev->pointer.max_y = info.maximum;
+
+ llog_debug(dev->input, "ABSX min %d max %d ABSY min %d max %d\n",
+ dev->pointer.min_x, dev->pointer.max_x,
+ dev->pointer.min_y, dev->pointer.max_y);
+ return 0;
+
+err_closefd:
+ close(fd);
+ return ret;
+}
+
static void input_new_dev(struct uterm_input *input,
const char *node,
unsigned int capabilities)
@@ -155,28 +242,28 @@ static void input_new_dev(struct uterm_input *input,
dev->input = input;
dev->rfd = -1;
dev->capabilities = capabilities;
+ dev->pointer.kind = POINTER_NONE;
dev->node = strdup(node);
if (!dev->node)
goto err_free;
- dev->num_syms = 1;
- dev->event.keysyms = malloc(sizeof(uint32_t) * dev->num_syms);
- if (!dev->event.keysyms)
- goto err_node;
- dev->event.codepoints = malloc(sizeof(uint32_t) * dev->num_syms);
- if (!dev->event.codepoints)
- goto err_syms;
- dev->repeat_event.keysyms = malloc(sizeof(uint32_t) * dev->num_syms);
- if (!dev->repeat_event.keysyms)
- goto err_codepoints;
- dev->repeat_event.codepoints = malloc(sizeof(uint32_t) * dev->num_syms);
- if (!dev->repeat_event.codepoints)
- goto err_rsyms;
-
- ret = uxkb_dev_init(dev);
- if (ret)
- goto err_rcodepoints;
+ if (dev->capabilities & UTERM_DEVICE_HAS_KEYS) {
+ ret = input_init_keyboard(dev);
+ if (ret)
+ goto err_node;
+ }
+ if (dev->capabilities & UTERM_DEVICE_HAS_ABS) {
+ ret = input_init_abs(dev);
+ if (ret)
+ goto err_node;
+ if (dev->capabilities & UTERM_DEVICE_HAS_TOUCH)
+ dev->pointer.kind = POINTER_TOUCHPAD;
+ else
+ dev->pointer.kind = POINTER_VMOUSE;
+ }
+ if (dev->capabilities & UTERM_DEVICE_HAS_REL)
+ dev->pointer.kind = POINTER_MOUSE;
if (input->awake > 0) {
ret = input_wake_up_dev(dev);
@@ -189,15 +276,8 @@ static void input_new_dev(struct uterm_input *input,
return;
err_kbd:
- uxkb_dev_destroy(dev);
-err_rcodepoints:
- free(dev->repeat_event.codepoints);
-err_rsyms:
- free(dev->repeat_event.keysyms);
-err_codepoints:
- free(dev->event.codepoints);
-err_syms:
- free(dev->event.keysyms);
+ if (dev->capabilities & UTERM_DEVICE_HAS_KEYS)
+ input_exit_keyboard(dev);
err_node:
free(dev->node);
err_free:
@@ -209,15 +289,22 @@ static void input_free_dev(struct uterm_input_dev *dev)
llog_debug(dev->input, "free device %s", dev->node);
input_sleep_dev(dev);
shl_dlist_unlink(&dev->list);
- uxkb_dev_destroy(dev);
- free(dev->repeat_event.codepoints);
- free(dev->repeat_event.keysyms);
- free(dev->event.codepoints);
- free(dev->event.keysyms);
+ if (dev->capabilities & UTERM_DEVICE_HAS_KEYS)
+ input_exit_keyboard(dev);
free(dev->node);
free(dev);
}
+static void hide_pointer_timer(struct ev_timer *timer, uint64_t num, void *data)
+{
+ struct uterm_input *input = data;
+ struct uterm_input_pointer_event pev;
+
+ pev.event = UTERM_HIDE_TIMEOUT;
+
+ shl_hook_call(input->pointer_hook, input, &pev);
+}
+
SHL_EXPORT
int uterm_input_new(struct uterm_input **out,
struct ev_eloop *eloop,
@@ -261,10 +348,19 @@ int uterm_input_new(struct uterm_input **out,
input->repeat_rate = repeat_rate;
shl_dlist_init(&input->devices);
- ret = shl_hook_new(&input->hook);
+ ret = shl_hook_new(&input->key_hook);
if (ret)
goto err_free;
+ ret = shl_hook_new(&input->pointer_hook);
+ if (ret)
+ goto err_hook;
+
+ ret = ev_eloop_new_timer(input->eloop, &input->hide_pointer, NULL,
+ hide_pointer_timer, input);
+ if (ret)
+ goto err_hook_pointer;
+
/* xkbcommon won't use the XKB_DEFAULT_OPTIONS environment
* variable if options is an empty string.
* So if all variables are empty, use NULL instead.
@@ -280,15 +376,22 @@ int uterm_input_new(struct uterm_input **out,
ret = uxkb_desc_init(input, model, layout, variant, options, locale,
keymap, compose_file, compose_file_len);
if (ret)
- goto err_hook;
+ goto err_hide_timer;
llog_debug(input, "new object %p", input);
ev_eloop_ref(input->eloop);
*out = input;
return 0;
+err_hide_timer:
+ ev_eloop_rm_timer(input->hide_pointer);
+
+err_hook_pointer:
+ shl_hook_free(input->pointer_hook);
+
err_hook:
- shl_hook_free(input->hook);
+ shl_hook_free(input->key_hook);
+
err_free:
free(input);
return ret;
@@ -321,7 +424,7 @@ void uterm_input_unref(struct uterm_input *input)
}
uxkb_desc_destroy(input);
- shl_hook_free(input->hook);
+ shl_hook_free(input->key_hook);
ev_eloop_unref(input->eloop);
free(input);
}
@@ -338,6 +441,8 @@ static unsigned int probe_device_capabilities(struct uterm_input *input,
unsigned int capabilities = 0;
unsigned long evbits[NLONGS(EV_CNT)] = { 0 };
unsigned long keybits[NLONGS(KEY_CNT)] = { 0 };
+ unsigned long relbits[NLONGS(REL_CNT)] = { 0 };
+ unsigned long absbits[NLONGS(ABS_CNT)] = { 0 };
fd = open(node, O_NONBLOCK | O_CLOEXEC | O_RDONLY);
if (fd < 0)
@@ -365,6 +470,32 @@ static unsigned int probe_device_capabilities(struct uterm_input *input,
break;
}
}
+ if (input_bit_is_set(keybits, BTN_LEFT))
+ capabilities |= UTERM_DEVICE_HAS_MOUSE_BTN;
+ if (input_bit_is_set(keybits, BTN_TOUCH))
+ capabilities |= UTERM_DEVICE_HAS_TOUCH;
+ }
+
+ if (input_bit_is_set(evbits, EV_SYN) &&
+ input_bit_is_set(evbits, EV_REL)) {
+ ret = ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbits)), relbits);
+ if (ret < 0)
+ goto err_ioctl;
+ if (input_bit_is_set(relbits, REL_X) &&
+ input_bit_is_set(relbits, REL_Y))
+ capabilities |= UTERM_DEVICE_HAS_REL;
+ if (input_bit_is_set(relbits, REL_WHEEL))
+ capabilities |= UTERM_DEVICE_HAS_WHEEL;
+ }
+
+ if (input_bit_is_set(evbits, EV_SYN) &&
+ input_bit_is_set(evbits, EV_ABS)) {
+ ret = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits);
+ if (ret < 0)
+ goto err_ioctl;
+ if (input_bit_is_set(absbits, ABS_X) &&
+ input_bit_is_set(absbits, ABS_Y))
+ capabilities |= UTERM_DEVICE_HAS_ABS;
}
if (input_bit_is_set(evbits, EV_LED))
@@ -380,8 +511,10 @@ static unsigned int probe_device_capabilities(struct uterm_input *input,
return 0;
}
+#define HAS_ALL(caps, flags) (((caps) & (flags)) == (flags))
+
SHL_EXPORT
-void uterm_input_add_dev(struct uterm_input *input, const char *node)
+void uterm_input_add_dev(struct uterm_input *input, const char *node, bool mouse)
{
unsigned int capabilities;
@@ -389,12 +522,20 @@ void uterm_input_add_dev(struct uterm_input *input, const char *node)
return;
capabilities = probe_device_capabilities(input, node);
- if (!(capabilities & UTERM_DEVICE_HAS_KEYS)) {
- llog_debug(input, "ignoring non-useful device %s", node);
+ if (HAS_ALL(capabilities, UTERM_DEVICE_HAS_KEYS)) {
+ input_new_dev(input, node, capabilities);
return;
}
-
- input_new_dev(input, node, capabilities);
+ if (HAS_ALL(capabilities, UTERM_DEVICE_HAS_REL | UTERM_DEVICE_HAS_MOUSE_BTN) ||
+ HAS_ALL(capabilities, UTERM_DEVICE_HAS_ABS | UTERM_DEVICE_HAS_TOUCH) ||
+ HAS_ALL(capabilities, UTERM_DEVICE_HAS_ABS | UTERM_DEVICE_HAS_MOUSE_BTN)) {
+ if (mouse)
+ input_new_dev(input, node, capabilities);
+ else
+ llog_debug(input, "ignoring pointer device %s", node);
+ } else {
+ llog_debug(input, "ignoring non-useful device %s", node);
+ }
}
SHL_EXPORT
@@ -418,25 +559,47 @@ void uterm_input_remove_dev(struct uterm_input *input, const char *node)
}
SHL_EXPORT
-int uterm_input_register_cb(struct uterm_input *input,
- uterm_input_cb cb,
+int uterm_input_register_key_cb(struct uterm_input *input,
+ uterm_input_key_cb cb,
void *data)
{
if (!input || !cb)
return -EINVAL;
- return shl_hook_add_cast(input->hook, cb, data, false);
+ return shl_hook_add_cast(input->key_hook, cb, data, false);
}
SHL_EXPORT
-void uterm_input_unregister_cb(struct uterm_input *input,
- uterm_input_cb cb,
+void uterm_input_unregister_key_cb(struct uterm_input *input,
+ uterm_input_key_cb cb,
void *data)
{
if (!input || !cb)
return;
- shl_hook_rm_cast(input->hook, cb, data);
+ shl_hook_rm_cast(input->key_hook, cb, data);
+}
+
+SHL_EXPORT
+int uterm_input_register_pointer_cb(struct uterm_input *input,
+ uterm_input_pointer_cb cb,
+ void *data)
+{
+ if (!input || !cb)
+ return -EINVAL;
+
+ return shl_hook_add_cast(input->pointer_hook, cb, data, false);
+}
+
+SHL_EXPORT
+void uterm_input_unregister_pointer_cb(struct uterm_input *input,
+ uterm_input_pointer_cb cb,
+ void *data)
+{
+ if (!input || !cb)
+ return;
+
+ shl_hook_rm_cast(input->pointer_hook, cb, data);
}
SHL_EXPORT
@@ -496,3 +659,15 @@ bool uterm_input_is_awake(struct uterm_input *input)
return input->awake > 0;
}
+
+SHL_EXPORT
+void uterm_input_set_pointer_max(struct uterm_input *input,
+ unsigned int max_x,
+ unsigned int max_y)
+{
+ if (!input)
+ return;
+
+ input->pointer_max_x = max_x;
+ input->pointer_max_y = max_y;
+}
diff --git a/src/uterm_input.h b/src/uterm_input.h
index 91d704bc..55a05d9f 100644
--- a/src/uterm_input.h
+++ b/src/uterm_input.h
@@ -61,7 +61,7 @@ enum uterm_input_modifier {
/* keep in sync with TSM_VTE_INVALID */
#define UTERM_INPUT_INVALID 0xffffffff
-struct uterm_input_event {
+struct uterm_input_key_event {
bool handled; /* user-controlled, default is false */
uint16_t keycode; /* linux keycode - KEY_* - linux/input.h */
uint32_t ascii; /* ascii keysym for @keycode */
@@ -72,11 +72,33 @@ struct uterm_input_event {
uint32_t *codepoints; /* ucs4 unicode value or UTERM_INPUT_INVALID */
};
+enum uterm_input_pointer_type {
+ UTERM_MOVED,
+ UTERM_BUTTON,
+ UTERM_WHEEL,
+ UTERM_SYNC,
+ UTERM_HIDE_TIMEOUT,
+};
+
+struct uterm_input_pointer_event {
+ enum uterm_input_pointer_type event;
+ int32_t pointer_x;
+ int32_t pointer_y;
+ int32_t wheel;
+ uint8_t button;
+ bool pressed;
+ bool double_click;
+};
+
#define UTERM_INPUT_HAS_MODS(_ev, _mods) (((_ev)->mods & (_mods)) == (_mods))
-typedef void (*uterm_input_cb) (struct uterm_input *input,
- struct uterm_input_event *ev,
- void *data);
+typedef void (*uterm_input_key_cb) (struct uterm_input *input,
+ struct uterm_input_key_event *ev,
+ void *data);
+
+typedef void (*uterm_input_pointer_cb) (struct uterm_input *input,
+ struct uterm_input_pointer_event *ev,
+ void *data);
int uterm_input_new(struct uterm_input **out, struct ev_eloop *eloop,
const char *model, const char *layout, const char *variant,
@@ -87,16 +109,24 @@ int uterm_input_new(struct uterm_input **out, struct ev_eloop *eloop,
void uterm_input_ref(struct uterm_input *input);
void uterm_input_unref(struct uterm_input *input);
-void uterm_input_add_dev(struct uterm_input *input, const char *node);
+void uterm_input_add_dev(struct uterm_input *input, const char *node, bool mouse);
void uterm_input_remove_dev(struct uterm_input *input, const char *node);
-int uterm_input_register_cb(struct uterm_input *input, uterm_input_cb cb,
+int uterm_input_register_key_cb(struct uterm_input *input, uterm_input_key_cb cb,
+ void *data);
+void uterm_input_unregister_key_cb(struct uterm_input *input, uterm_input_key_cb cb,
+ void *data);
+
+int uterm_input_register_pointer_cb(struct uterm_input *input, uterm_input_pointer_cb cb,
void *data);
-void uterm_input_unregister_cb(struct uterm_input *input, uterm_input_cb cb,
+void uterm_input_unregister_pointer_cb(struct uterm_input *input, uterm_input_pointer_cb cb,
void *data);
void uterm_input_sleep(struct uterm_input *input);
void uterm_input_wake_up(struct uterm_input *input);
bool uterm_input_is_awake(struct uterm_input *input);
+void uterm_input_set_pointer_max(struct uterm_input *input,
+ unsigned int max_x,
+ unsigned int max_y);
#endif /* UTERM_UTERM_INPUT_H */
diff --git a/src/uterm_input_internal.h b/src/uterm_input_internal.h
index 816bfd20..2a99a283 100644
--- a/src/uterm_input_internal.h
+++ b/src/uterm_input_internal.h
@@ -42,6 +42,36 @@
enum uterm_input_device_capability {
UTERM_DEVICE_HAS_KEYS = (1 << 0),
UTERM_DEVICE_HAS_LEDS = (1 << 1),
+ UTERM_DEVICE_HAS_REL = (1 << 2),
+ UTERM_DEVICE_HAS_ABS = (1 << 3),
+ UTERM_DEVICE_HAS_MOUSE_BTN = (1 << 4),
+ UTERM_DEVICE_HAS_TOUCH = (1 << 5),
+ UTERM_DEVICE_HAS_WHEEL = (1 << 6),
+};
+
+enum pointer_kind {
+ POINTER_NONE,
+ POINTER_MOUSE,
+ POINTER_TOUCHPAD,
+ POINTER_VMOUSE,
+};
+
+struct uterm_input_pointer {
+ /* For pointers (mouse/trackpad/trackpoint/touchscreen) */
+ enum pointer_kind kind;
+ enum uterm_input_pointer_type action;
+ struct timespec last_click;
+ int32_t x;
+ int32_t y;
+
+ bool touchpaddown;
+ int32_t off_x;
+ int32_t off_y;
+
+ int32_t min_x;
+ int32_t max_x;
+ int32_t min_y;
+ int32_t max_y;
};
struct uterm_input_dev {
@@ -52,17 +82,21 @@ struct uterm_input_dev {
int rfd;
char *node;
struct ev_fd *fd;
+
+ /* For keyboards */
struct xkb_state *state;
struct xkb_compose_state *compose_state;
/* Used in sleep/wake up to store the key's pressed/released state. */
char key_state_bits[SHL_DIV_ROUND_UP(KEY_CNT, CHAR_BIT)];
unsigned int num_syms;
- struct uterm_input_event event;
- struct uterm_input_event repeat_event;
+ struct uterm_input_key_event event;
+ struct uterm_input_key_event repeat_event;
bool repeating;
struct ev_timer *repeat_timer;
+
+ struct uterm_input_pointer pointer;
};
struct uterm_input {
@@ -74,11 +108,16 @@ struct uterm_input {
unsigned int repeat_rate;
unsigned int repeat_delay;
- struct shl_hook *hook;
+ struct shl_hook *key_hook;
struct xkb_context *ctx;
struct xkb_keymap *keymap;
struct xkb_compose_table *compose_table;
+ struct shl_hook *pointer_hook;
+ int32_t pointer_max_x;
+ int32_t pointer_max_y;
+ struct ev_timer *hide_pointer;
+
struct shl_dlist devices;
};
@@ -106,4 +145,12 @@ int uxkb_dev_process(struct uterm_input_dev *dev,
void uxkb_dev_sleep(struct uterm_input_dev *dev);
void uxkb_dev_wake_up(struct uterm_input_dev *dev);
+void pointer_dev_rel(struct uterm_input_dev *dev,
+ uint16_t code, int32_t value);
+void pointer_dev_abs(struct uterm_input_dev *dev,
+ uint16_t code, int32_t value);
+void pointer_dev_button(struct uterm_input_dev *dev,
+ uint16_t code, int32_t value);
+void pointer_dev_sync(struct uterm_input_dev *dev);
+
#endif /* UTERM_INPUT_INTERNAL_H */
diff --git a/src/uterm_input_pointer.c b/src/uterm_input_pointer.c
new file mode 100644
index 00000000..851c381d
--- /dev/null
+++ b/src/uterm_input_pointer.c
@@ -0,0 +1,177 @@
+#include
+#include
+#include
+#include "eloop.h"
+#include "shl_hook.h"
+#include "shl_llog.h"
+#include "uterm_input.h"
+#include "uterm_input_internal.h"
+
+
+static void pointer_update_inactivity_timer(struct uterm_input_dev *dev)
+{
+ struct itimerspec spec;
+
+ spec.it_interval.tv_nsec = 0;
+ spec.it_interval.tv_sec = 0;
+ spec.it_value.tv_nsec = 0;
+ spec.it_value.tv_sec = 20;
+ ev_timer_update(dev->input->hide_pointer, &spec);
+}
+
+static void pointer_dev_send_move(struct uterm_input_dev *dev)
+{
+ struct uterm_input_pointer_event pev = {0};
+
+ pev.event = UTERM_MOVED;
+ pev.pointer_x = dev->pointer.x;
+ pev.pointer_y = dev->pointer.y;
+
+ shl_hook_call(dev->input->pointer_hook, dev->input, &pev);
+}
+
+static void pointer_dev_send_wheel(struct uterm_input_dev *dev, int32_t value)
+{
+ struct uterm_input_pointer_event pev = {0};
+
+ pev.event = UTERM_WHEEL;
+ pev.wheel = value;
+
+ shl_hook_call(dev->input->pointer_hook, dev->input, &pev);
+}
+
+static void pointer_dev_send_button(struct uterm_input_dev *dev, uint8_t button, bool pressed, bool dbl_click)
+{
+ struct uterm_input_pointer_event pev = {0};
+
+ pev.event = UTERM_BUTTON;
+ pev.button = button;
+ pev.pressed = pressed;
+ pev.double_click = dbl_click;
+
+ shl_hook_call(dev->input->pointer_hook, dev->input, &pev);
+}
+
+void pointer_dev_sync(struct uterm_input_dev *dev)
+{
+ struct uterm_input_pointer_event pev = {0};
+
+ pev.event = UTERM_SYNC;
+
+ shl_hook_call(dev->input->pointer_hook, dev->input, &pev);
+ pointer_update_inactivity_timer(dev);
+ dev->pointer.touchpaddown = false;
+}
+
+void pointer_dev_rel(struct uterm_input_dev *dev,
+ uint16_t code, int32_t value)
+{
+ switch (code) {
+ case REL_X:
+ dev->pointer.x += value;
+ if (dev->pointer.x < 0)
+ dev->pointer.x = 0;
+ if (dev->pointer.x > dev->input->pointer_max_x)
+ dev->pointer.x = dev->input->pointer_max_x;
+ pointer_dev_send_move(dev);
+ break;
+ case REL_Y:
+ dev->pointer.y += value;
+ if (dev->pointer.y < 0)
+ dev->pointer.y = 0;
+ if (dev->pointer.y > dev->input->pointer_max_y)
+ dev->pointer.y = dev->input->pointer_max_y;
+ pointer_dev_send_move(dev);
+ break;
+ case REL_WHEEL:
+ pointer_dev_send_wheel(dev, value);
+ break;
+ default:
+ break;
+ }
+}
+
+void pointer_dev_abs(struct uterm_input_dev *dev,
+ uint16_t code, int32_t value)
+{
+ switch (code) {
+ case ABS_X:
+ if (dev->pointer.kind == POINTER_TOUCHPAD) {
+ if (dev->pointer.touchpaddown == true)
+ dev->pointer.off_x = dev->pointer.x - value;
+
+ dev->pointer.x = dev->pointer.off_x + value;
+ if (dev->pointer.x < 0) {
+ dev->pointer.x = 0;
+ dev->pointer.off_x = -value;
+ }
+ if (dev->pointer.x > dev->input->pointer_max_x) {
+ dev->pointer.x = dev->input->pointer_max_x;
+ dev->pointer.off_x = dev->input->pointer_max_x - value;
+ }
+ } else if (dev->pointer.kind == POINTER_VMOUSE) {
+ dev->pointer.x = ((value - dev->pointer.min_x) * dev->input->pointer_max_x) / (dev->pointer.max_x - dev->pointer.min_x);
+ } else {
+ return;
+ }
+ break;
+ case ABS_Y:
+ if (dev->pointer.kind == POINTER_TOUCHPAD) {
+ if (dev->pointer.touchpaddown == true)
+ dev->pointer.off_y = dev->pointer.y - value;
+
+ dev->pointer.y = dev->pointer.off_y + value;
+ if (dev->pointer.y < 0) {
+ dev->pointer.y = 0;
+ dev->pointer.off_y = -value;
+ }
+ if (dev->pointer.y > dev->input->pointer_max_y) {
+ dev->pointer.y = dev->input->pointer_max_y;
+ dev->pointer.off_y = dev->input->pointer_max_y - value;
+ }
+ } else if (dev->pointer.kind == POINTER_VMOUSE) {
+ dev->pointer.y = ((value - dev->pointer.min_y) * dev->input->pointer_max_y) / (dev->pointer.max_y - dev->pointer.min_y);
+ } else {
+ return;
+ }
+ break;
+ default:
+ return;
+ }
+ pointer_dev_send_move(dev);
+}
+
+void pointer_dev_button(struct uterm_input_dev *dev,
+ uint16_t code, int32_t value)
+{
+ struct timespec tp;
+ uint64_t elapsed;
+ bool pressed = (value == 1);
+ bool dbl_click = false;
+
+ switch (code) {
+ case BTN_LEFT:
+ if (pressed) {
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+ elapsed = (tp.tv_sec - dev->pointer.last_click.tv_sec) * 1000 + (tp.tv_nsec - dev->pointer.last_click.tv_nsec) / 1000000;
+ dbl_click = (elapsed < 500);
+ dev->pointer.last_click = tp;
+ }
+ pointer_dev_send_button(dev, 0, pressed, dbl_click);
+ break;
+ case BTN_RIGHT:
+ pointer_dev_send_button(dev, 1, pressed, false);
+ break;
+ case BTN_TOOL_DOUBLETAP:
+ case BTN_TOOL_TRIPLETAP:
+ case BTN_MIDDLE:
+ pointer_dev_send_button(dev, 2, pressed, false);
+ break;
+ case BTN_TOUCH:
+ dev->pointer.touchpaddown = true;
+ break;
+ default:
+ break;
+ }
+}
+
diff --git a/src/uterm_input_uxkb.c b/src/uterm_input_uxkb.c
index 1d28a8da..926b6725 100644
--- a/src/uterm_input_uxkb.c
+++ b/src/uterm_input_uxkb.c
@@ -209,7 +209,7 @@ static void timer_event(struct ev_timer *timer, uint64_t num, void *data)
struct uterm_input_dev *dev = data;
dev->repeat_event.handled = false;
- shl_hook_call(dev->input->hook, dev->input, &dev->repeat_event);
+ shl_hook_call(dev->input->key_hook, dev->input, &dev->repeat_event);
}
int uxkb_dev_init(struct uterm_input_dev *dev)
@@ -338,7 +338,7 @@ static inline int uxkb_dev_resize_event(struct uterm_input_dev *dev, size_t s)
}
static int uxkb_dev_fill_event(struct uterm_input_dev *dev,
- struct uterm_input_event *ev,
+ struct uterm_input_key_event *ev,
xkb_keycode_t code,
int num_syms,
const xkb_keysym_t *syms)
@@ -532,7 +532,7 @@ int uxkb_dev_process(struct uterm_input_dev *dev,
return -ENOKEY;
dev->event.handled = false;
- shl_hook_call(dev->input->hook, dev->input, &dev->event);
+ shl_hook_call(dev->input->key_hook, dev->input, &dev->event);
return 0;
}
diff --git a/src/uterm_vt.c b/src/uterm_vt.c
index 55f7c57e..1760a429 100644
--- a/src/uterm_vt.c
+++ b/src/uterm_vt.c
@@ -573,7 +573,7 @@ static int real_deactivate(struct uterm_vt *vt)
return -EINPROGRESS;
}
-static void real_input(struct uterm_vt *vt, struct uterm_input_event *ev)
+static void real_input(struct uterm_vt *vt, struct uterm_input_key_event *ev)
{
int id;
struct vt_stat vts;
@@ -696,7 +696,7 @@ static int fake_deactivate(struct uterm_vt *vt)
return vt_call_deactivate(vt, false);
}
-static void fake_input(struct uterm_vt *vt, struct uterm_input_event *ev)
+static void fake_input(struct uterm_vt *vt, struct uterm_input_key_event *ev)
{
if (ev->handled)
return;
@@ -749,7 +749,7 @@ static void fake_close(struct uterm_vt *vt)
*/
static void vt_input(struct uterm_input *input,
- struct uterm_input_event *ev,
+ struct uterm_input_key_event *ev,
void *data)
{
struct uterm_vt *vt = data;
@@ -890,7 +890,7 @@ int uterm_vt_allocate(struct uterm_vt_master *vtm,
if (ret)
goto err_sig1;
- ret = uterm_input_register_cb(vt->input, vt_input, vt);
+ ret = uterm_input_register_key_cb(vt->input, vt_input, vt);
if (ret)
goto err_sig2;
@@ -930,7 +930,7 @@ int uterm_vt_allocate(struct uterm_vt_master *vtm,
return 0;
err_input:
- uterm_input_unregister_cb(vt->input, vt_input, vt);
+ uterm_input_unregister_key_cb(vt->input, vt_input, vt);
err_sig2:
ev_eloop_unregister_signal_cb(vtm->eloop, SIGUSR2, vt_sigusr2, vt);
err_sig1:
diff --git a/tests/test_input.c b/tests/test_input.c
index 8cf22943..ae1f1069 100644
--- a/tests/test_input.c
+++ b/tests/test_input.c
@@ -89,7 +89,7 @@ static void print_modifiers(unsigned int mods)
}
static void input_arrived(struct uterm_input *input,
- struct uterm_input_event *ev,
+ struct uterm_input_key_event *ev,
void *data)
{
char s[32];
@@ -148,16 +148,16 @@ static void monitor_event(struct uterm_monitor *mon,
0, 0, log_llog, NULL);
if (ret)
return;
- ret = uterm_input_register_cb(input, input_arrived, NULL);
+ ret = uterm_input_register_key_cb(input, input_arrived, NULL);
if (ret)
return;
uterm_input_wake_up(input);
} else if (ev->type == UTERM_MONITOR_FREE_SEAT) {
- uterm_input_unregister_cb(input, input_arrived, NULL);
+ uterm_input_unregister_key_cb(input, input_arrived, NULL);
uterm_input_unref(input);
} else if (ev->type == UTERM_MONITOR_NEW_DEV) {
if (ev->dev_type == UTERM_MONITOR_INPUT)
- uterm_input_add_dev(input, ev->dev_node);
+ uterm_input_add_dev(input, ev->dev_node, true);
} else if (ev->type == UTERM_MONITOR_FREE_DEV) {
if (ev->dev_type == UTERM_MONITOR_INPUT)
uterm_input_remove_dev(input, ev->dev_node);