From acbc0a019a8b9a94fb8a7c1c0c226f482504dd68 Mon Sep 17 00:00:00 2001 From: nyorain Date: Mon, 19 Jun 2017 20:01:35 +0200 Subject: [PATCH 1/5] Make logging ninja friendly When building with ninja instead of make __FILE__ will be relative and logging therefore break. This moves stripping the path from __FILE__ to runtime and handles a relative filepath as well as a full one. --- common/log.c | 26 ++++++++++++++++++++++++++ include/common/log.h | 5 +++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/common/log.c b/common/log.c index af07334a..1a4a28a8 100644 --- a/common/log.c +++ b/common/log.c @@ -58,3 +58,29 @@ void _wlr_log(log_importance_t verbosity, const char *fmt, ...) { log_callback(verbosity, fmt, args); va_end(args); } + +// strips the path prefix from filepath +// will try to strip WLR_SRC_DIR as well as a relative src dir +// e.g. '/src/build/wlroots/backend/wayland/backend.c' and +// '../backend/wayland/backend.c' will both be stripped to +// 'backend/wayland/backend.c' +const char *_strip_path(const char *filepath) { + const char *srcit = WLR_SRC_DIR; + const char *fileit = filepath; + + // remove WLR_SRC_DIR prefix + while(*fileit != '\0' && *srcit != '\0' && *fileit == *srcit) { + ++fileit; + ++srcit; + } + if(fileit != filepath) { + ++fileit; + } + + // remove relative prefix + while(*fileit == '.' || *fileit == '/') { + ++fileit; + } + + return fileit; +} diff --git a/include/common/log.h b/include/common/log.h index 3fca0dcf..98e57900 100644 --- a/include/common/log.h +++ b/include/common/log.h @@ -13,12 +13,13 @@ void _wlr_log(log_importance_t verbosity, const char *format, ...) ATTRIB_PRINTF(2, 3); void _wlr_vlog(log_importance_t verbosity, const char *format, va_list args) ATTRIB_PRINTF(2, 0); +const char *_strip_path(const char *filepath); #define wlr_log(verb, fmt, ...) \ - _wlr_log(verb, "[%s:%d] " fmt, __FILE__ + strlen(WLR_SRC_DIR) + 1, __LINE__, ##__VA_ARGS__) + _wlr_log(verb, "[%s:%d] " fmt, _strip_path(__FILE__), __LINE__, ##__VA_ARGS__) #define wlr_vlog(verb, fmt, args) \ - _wlr_vlog(verb, "[%s:%d] " fmt, __FILE__ + strlen(WLR_SRC_DIR) + 1, __LINE__, args) + _wlr_vlog(verb, "[%s:%d] " fmt, _strip_path(__FILE__), __LINE__, args) #define wlr_log_errno(verb, fmt, ...) \ wlr_log(verb, fmt ": %s", ##__VA_ARGS__, strerror(errno)) From e9609e9adf2883a1cf2b766adf5363f25f8f0833 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 19 Jun 2017 14:02:25 -0400 Subject: [PATCH 2/5] Allocate framebuffers for hardware cursors Still doesn't fix cursors though --- backend/drm/drm.c | 4 ++++ example/pointer.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 00b45bce..befbfb94 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -296,6 +296,10 @@ static void wlr_drm_cursor_bo_update(struct wlr_output_state *output, wlr_log(L_ERROR, "Failed to create cursor bo"); return; } + if (!get_fb_for_bo(state->fd, output->cursor_bo[i])) { + wlr_log(L_ERROR, "Failed to create cursor fb"); + return; + } } } diff --git a/example/pointer.c b/example/pointer.c index d97d253e..ddb665a1 100644 --- a/example/pointer.c +++ b/example/pointer.c @@ -94,8 +94,9 @@ static void handle_pointer_axis(struct pointer_state *pstate, static void handle_output_add(struct output_state *ostate) { struct wlr_output *wlr_output = ostate->output; + int width = 16, height = 16; if (!wlr_output_set_cursor(wlr_output, cat_tex.pixel_data, - cat_tex.width * 4, cat_tex.width, cat_tex.height)) { + width * 4, width, height)) { fprintf(stderr, "Failed to set cursor\n"); return; } From 24147225745b8a78af5db43c065c2ad84f0a115e Mon Sep 17 00:00:00 2001 From: nyorain Date: Mon, 19 Jun 2017 20:17:40 +0200 Subject: [PATCH 3/5] Make log:_strip_path more efficient --- common/log.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/common/log.c b/common/log.c index 1a4a28a8..90eedf4c 100644 --- a/common/log.c +++ b/common/log.c @@ -65,22 +65,13 @@ void _wlr_log(log_importance_t verbosity, const char *fmt, ...) { // '../backend/wayland/backend.c' will both be stripped to // 'backend/wayland/backend.c' const char *_strip_path(const char *filepath) { - const char *srcit = WLR_SRC_DIR; - const char *fileit = filepath; - - // remove WLR_SRC_DIR prefix - while(*fileit != '\0' && *srcit != '\0' && *fileit == *srcit) { - ++fileit; - ++srcit; - } - if(fileit != filepath) { - ++fileit; + static int srclen = strlen(WLR_SRC_DIR) + 1; + if(*filepath == '.') { + while(*filepath == '.' || *filepath == '/') { + ++filepath; + } + } else { + filepath += srclen; } - - // remove relative prefix - while(*fileit == '.' || *fileit == '/') { - ++fileit; - } - - return fileit; + return filepath; } From ecb04afcadc96cc8d39749311e4c1c412bebf4a9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 19 Jun 2017 14:49:07 -0400 Subject: [PATCH 4/5] Implement tablet pads --- backend/CMakeLists.txt | 1 + backend/libinput/events.c | 14 +++++- backend/libinput/tablet_pad.c | 95 +++++++++++++++++++++++++++++++++++ example/shared.c | 24 +++++++++ example/shared.h | 11 ++++ example/tablet.c | 41 +++++++++++---- include/backend/libinput.h | 9 ++++ include/types.h | 8 +++ include/wlr/types.h | 52 ++++++++++++++++++- types/CMakeLists.txt | 1 + types/wlr_tablet_pad.c | 25 +++++++++ 11 files changed, 268 insertions(+), 13 deletions(-) create mode 100644 backend/libinput/tablet_pad.c create mode 100644 types/wlr_tablet_pad.c diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index 6ffa2042..9594c318 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -20,6 +20,7 @@ add_library(wlr-backend libinput/pointer.c libinput/touch.c libinput/tablet_tool.c + libinput/tablet_pad.c multi/backend.c backend.c diff --git a/backend/libinput/events.c b/backend/libinput/events.c index 8ebec63b..2e7cc541 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -91,7 +91,10 @@ static void handle_device_added(struct wlr_backend_state *state, wl_signal_emit(&state->backend->events.input_add, wlr_device); } if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_PAD)) { - // TODO + struct wlr_input_device *wlr_device = allocate_device(state, + device, devices, WLR_INPUT_DEVICE_TABLET_PAD); + wlr_device->tablet_pad = wlr_libinput_tablet_pad_create(device); + wl_signal_emit(&state->backend->events.input_add, wlr_device); } if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_GESTURE)) { // TODO @@ -169,6 +172,15 @@ void wlr_libinput_event(struct wlr_backend_state *state, case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: handle_tablet_tool_button(event, device); break; + case LIBINPUT_EVENT_TABLET_PAD_BUTTON: + handle_tablet_pad_button(event, device); + break; + case LIBINPUT_EVENT_TABLET_PAD_RING: + handle_tablet_pad_ring(event, device); + break; + case LIBINPUT_EVENT_TABLET_PAD_STRIP: + handle_tablet_pad_strip(event, device); + break; default: wlr_log(L_DEBUG, "Unknown libinput event %d", event_type); break; diff --git a/backend/libinput/tablet_pad.c b/backend/libinput/tablet_pad.c new file mode 100644 index 00000000..ee7c82f8 --- /dev/null +++ b/backend/libinput/tablet_pad.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include +#include +#include "backend/libinput.h" +#include "common/log.h" +#include "types.h" + +struct wlr_tablet_pad *wlr_libinput_tablet_pad_create( + struct libinput_device *device) { + assert(device); + return wlr_tablet_pad_create(NULL, NULL); +} + +void handle_tablet_pad_button(struct libinput_event *event, + struct libinput_device *device) { + struct wlr_input_device *dev = + get_appropriate_device(WLR_INPUT_DEVICE_TABLET_PAD, device); + if (!dev) { + wlr_log(L_DEBUG, "Got a tablet pad event for a device with no tablet pad?"); + return; + } + struct libinput_event_tablet_pad *pevent = + libinput_event_get_tablet_pad_event(event); + struct wlr_tablet_pad_button *wlr_event = + calloc(1, sizeof(struct wlr_tablet_pad_button)); + wlr_event->time_sec = libinput_event_tablet_pad_get_time(pevent); + wlr_event->time_usec = libinput_event_tablet_pad_get_time_usec(pevent); + wlr_event->button = libinput_event_tablet_pad_get_button_number(pevent); + switch (libinput_event_tablet_pad_get_button_state(pevent)) { + case LIBINPUT_BUTTON_STATE_PRESSED: + wlr_event->state = WLR_BUTTON_PRESSED; + break; + case LIBINPUT_BUTTON_STATE_RELEASED: + wlr_event->state = WLR_BUTTON_RELEASED; + break; + } + wl_signal_emit(&dev->tablet_pad->events.button, wlr_event); +} + +void handle_tablet_pad_ring(struct libinput_event *event, + struct libinput_device *device) { + struct wlr_input_device *dev = + get_appropriate_device(WLR_INPUT_DEVICE_TABLET_PAD, device); + if (!dev) { + wlr_log(L_DEBUG, "Got a tablet pad event for a device with no tablet pad?"); + return; + } + struct libinput_event_tablet_pad *pevent = + libinput_event_get_tablet_pad_event(event); + struct wlr_tablet_pad_ring *wlr_event = + calloc(1, sizeof(struct wlr_tablet_pad_ring)); + wlr_event->time_sec = libinput_event_tablet_pad_get_time(pevent); + wlr_event->time_usec = libinput_event_tablet_pad_get_time_usec(pevent); + wlr_event->ring = libinput_event_tablet_pad_get_ring_number(pevent); + wlr_event->position = libinput_event_tablet_pad_get_ring_position(pevent); + switch (libinput_event_tablet_pad_get_ring_source(pevent)) { + case LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN: + wlr_event->source = WLR_TABLET_PAD_RING_SOURCE_UNKNOWN; + break; + case LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER: + wlr_event->source = WLR_TABLET_PAD_RING_SOURCE_FINGER; + break; + } + wl_signal_emit(&dev->tablet_pad->events.ring, wlr_event); +} + +void handle_tablet_pad_strip(struct libinput_event *event, + struct libinput_device *device) { + struct wlr_input_device *dev = + get_appropriate_device(WLR_INPUT_DEVICE_TABLET_PAD, device); + if (!dev) { + wlr_log(L_DEBUG, "Got a tablet pad event for a device with no tablet pad?"); + return; + } + struct libinput_event_tablet_pad *pevent = + libinput_event_get_tablet_pad_event(event); + struct wlr_tablet_pad_strip *wlr_event = + calloc(1, sizeof(struct wlr_tablet_pad_strip)); + wlr_event->time_sec = libinput_event_tablet_pad_get_time(pevent); + wlr_event->time_usec = libinput_event_tablet_pad_get_time_usec(pevent); + wlr_event->strip = libinput_event_tablet_pad_get_strip_number(pevent); + wlr_event->position = libinput_event_tablet_pad_get_strip_position(pevent); + switch (libinput_event_tablet_pad_get_strip_source(pevent)) { + case LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN: + wlr_event->source = WLR_TABLET_PAD_STRIP_SOURCE_UNKNOWN; + break; + case LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER: + wlr_event->source = WLR_TABLET_PAD_STRIP_SOURCE_FINGER; + break; + } + wl_signal_emit(&dev->tablet_pad->events.strip, wlr_event); +} diff --git a/example/shared.c b/example/shared.c index 88f2b05f..56cb89af 100644 --- a/example/shared.c +++ b/example/shared.c @@ -211,6 +211,25 @@ static void tablet_tool_add(struct wlr_input_device *device, wl_list_insert(&state->tablet_tools, &tstate->link); } +static void tablet_pad_button_notify(struct wl_listener *listener, void *data) { + struct wlr_tablet_pad_button *event = data; + struct tablet_pad_state *pstate = wl_container_of(listener, pstate, button); + if (pstate->compositor->pad_button_cb) { + pstate->compositor->pad_button_cb(pstate, event->button, event->state); + } +} + +static void tablet_pad_add(struct wlr_input_device *device, + struct compositor_state *state) { + struct tablet_pad_state *pstate = calloc(sizeof(struct tablet_pad_state), 1); + pstate->device = device; + pstate->compositor = state; + wl_list_init(&pstate->button.link); + pstate->button.notify = tablet_pad_button_notify; + wl_signal_add(&device->tablet_pad->events.button, &pstate->button); + wl_list_insert(&state->tablet_pads, &pstate->link); +} + static void input_add_notify(struct wl_listener *listener, void *data) { struct wlr_input_device *device = data; struct compositor_state *state = wl_container_of(listener, state, input_add); @@ -226,6 +245,10 @@ static void input_add_notify(struct wl_listener *listener, void *data) { break; case WLR_INPUT_DEVICE_TABLET_TOOL: tablet_tool_add(device, state); + break; + case WLR_INPUT_DEVICE_TABLET_PAD: + tablet_pad_add(device, state); + break; default: break; } @@ -391,6 +414,7 @@ void compositor_init(struct compositor_state *state) { wl_list_init(&state->pointers); wl_list_init(&state->touch); wl_list_init(&state->tablet_tools); + wl_list_init(&state->tablet_pads); wl_list_init(&state->input_add.link); state->input_add.notify = input_add_notify; wl_list_init(&state->input_remove.link); diff --git a/example/shared.h b/example/shared.h index df456c91..173a5719 100644 --- a/example/shared.h +++ b/example/shared.h @@ -61,6 +61,14 @@ struct tablet_tool_state { void *data; }; +struct tablet_pad_state { + struct compositor_state *compositor; + struct wlr_input_device *device; + struct wl_listener button; + struct wl_list link; + void *data; +}; + struct compositor_state { void (*output_add_cb)(struct output_state *s); void (*keyboard_add_cb)(struct keyboard_state *s); @@ -91,6 +99,8 @@ struct compositor_state { enum wlr_tablet_tool_tip_state state); void (*tool_button_cb)(struct tablet_tool_state *s, uint32_t button, enum wlr_button_state state); + void (*pad_button_cb)(struct tablet_pad_state *s, + uint32_t button, enum wlr_button_state state); struct wl_display *display; struct wl_event_loop *event_loop; @@ -101,6 +111,7 @@ struct compositor_state { struct wl_list pointers; struct wl_list touch; struct wl_list tablet_tools; + struct wl_list tablet_pads; struct wl_listener input_add; struct wl_listener input_remove; diff --git a/example/tablet.c b/example/tablet.c index f2497d59..3c5b583e 100644 --- a/example/tablet.c +++ b/example/tablet.c @@ -21,13 +21,14 @@ struct sample_state { struct wlr_renderer *renderer; - bool proximity, tap; + bool proximity, tap, button; double distance; double pressure; double x_mm, y_mm; double width_mm, height_mm; struct wl_list link; float tool_color[4]; + float pad_color[4]; }; static void handle_output_frame(struct output_state *output, struct timespec *ts) { @@ -41,11 +42,10 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts wlr_renderer_begin(sample->renderer, wlr_output); float matrix[16], view[16]; - float pad_color[4] = { 0.75, 0.75, 0.75, 1.0 }; float distance = 0.8f * (1 - sample->distance); float tool_color[4] = { distance, distance, distance, 1 }; - for (size_t i = 0; i < 4; ++i) { - tool_color[i] *= sample->tool_color[i]; + for (size_t i = 0; sample->button && i < 4; ++i) { + tool_color[i] = sample->tool_color[i]; } float scale = 4; @@ -57,7 +57,7 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts wlr_matrix_scale(&view, pad_width, pad_height, 1); wlr_matrix_mul(&matrix, &view, &view); wlr_matrix_mul(&wlr_output->transform_matrix, &view, &matrix); - wlr_render_colored_quad(sample->renderer, &pad_color, &matrix); + wlr_render_colored_quad(sample->renderer, &sample->pad_color, &matrix); if (sample->proximity) { wlr_matrix_translate(&matrix, @@ -110,12 +110,31 @@ static void handle_tool_button(struct tablet_tool_state *tstate, uint32_t button, enum wlr_button_state state) { struct sample_state *sample = tstate->compositor->data; if (state == WLR_BUTTON_RELEASED) { - float default_color[4] = { 1, 1, 1, 1 }; - memcpy(sample->tool_color, default_color, 4); + sample->button = false; } else { + sample->button = true; for (size_t i = 0; i < 3; ++i) { - if (button % 3 != i) { - sample->tool_color[button % 3] = 0; + if (button % 3 == i) { + sample->tool_color[i] = 0; + } else { + sample->tool_color[i] = 1; + } + } + } +} + +static void handle_pad_button(struct tablet_pad_state *pstate, + uint32_t button, enum wlr_button_state state) { + struct sample_state *sample = pstate->compositor->data; + float default_color[4] = { 0.75, 0.75, 0.75, 1.0 }; + if (state == WLR_BUTTON_RELEASED) { + memcpy(sample->pad_color, default_color, sizeof(default_color)); + } else { + for (size_t i = 0; i < 3; ++i) { + if (button % 3 == i) { + sample->pad_color[i] = 0; + } else { + sample->pad_color[i] = 1; } } } @@ -123,7 +142,8 @@ static void handle_tool_button(struct tablet_tool_state *tstate, int main(int argc, char *argv[]) { struct sample_state state = { - .tool_color = { 1, 1, 1, 1 } + .tool_color = { 1, 1, 1, 1 }, + .pad_color = { 0.75, 0.75, 0.75, 1.0 } }; struct compositor_state compositor; @@ -133,6 +153,7 @@ int main(int argc, char *argv[]) { compositor.tool_axis_cb = handle_tool_axis; compositor.tool_proximity_cb = handle_tool_proximity; compositor.tool_button_cb = handle_tool_button; + compositor.pad_button_cb = handle_pad_button; state.renderer = wlr_gles3_renderer_init(); diff --git a/include/backend/libinput.h b/include/backend/libinput.h index 80f57177..89286ab8 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -68,4 +68,13 @@ void handle_tablet_tool_tip(struct libinput_event *event, void handle_tablet_tool_button(struct libinput_event *event, struct libinput_device *device); +struct wlr_tablet_pad *wlr_libinput_tablet_pad_create( + struct libinput_device *device); +void handle_tablet_pad_button(struct libinput_event *event, + struct libinput_device *device); +void handle_tablet_pad_ring(struct libinput_event *event, + struct libinput_device *device); +void handle_tablet_pad_strip(struct libinput_event *event, + struct libinput_device *device); + #endif diff --git a/include/types.h b/include/types.h index e2930a9f..2063c3f5 100644 --- a/include/types.h +++ b/include/types.h @@ -53,6 +53,14 @@ struct wlr_tablet_tool *wlr_tablet_tool_create(struct wlr_tablet_tool_impl *impl struct wlr_tablet_tool_state *state); void wlr_tablet_tool_destroy(struct wlr_tablet_tool *tool); +struct wlr_tablet_pad_impl { + void (*destroy)(struct wlr_tablet_pad_state *pad); +}; + +struct wlr_tablet_pad *wlr_tablet_pad_create(struct wlr_tablet_pad_impl *impl, + struct wlr_tablet_pad_state *state); +void wlr_tablet_pad_destroy(struct wlr_tablet_pad *pad); + struct wlr_input_device_impl { void (*destroy)(struct wlr_input_device_state *state); }; diff --git a/include/wlr/types.h b/include/wlr/types.h index 3afc361e..2ca73cc2 100644 --- a/include/wlr/types.h +++ b/include/wlr/types.h @@ -254,8 +254,55 @@ struct wlr_tablet_tool_button { enum wlr_button_state state; }; -// TODO: tablet pad -// TODO: switch +// NOTE: the wlr tablet pad implementation does not currently support tablets +// with more than one mode. I don't own any such hardware so I cannot test it +// and it is too complicated to make a meaningful implementation of blindly. +struct wlr_tablet_pad_impl; +struct wlr_tablet_pad_state; + +struct wlr_tablet_pad { + struct wlr_tablet_pad_impl *impl; + struct wlr_tablet_pad_state *state; + + struct { + struct wl_signal button; + struct wl_signal ring; + struct wl_signal strip; + } events; +}; + +struct wlr_tablet_pad_button { + uint32_t time_sec; + uint64_t time_usec; + uint32_t button; + enum wlr_button_state state; +}; + +enum wlr_tablet_pad_ring_source { + WLR_TABLET_PAD_RING_SOURCE_UNKNOWN, + WLR_TABLET_PAD_RING_SOURCE_FINGER, +}; + +struct wlr_tablet_pad_ring { + uint32_t time_sec; + uint64_t time_usec; + enum wlr_tablet_pad_ring_source source; + uint32_t ring; + double position; +}; + +enum wlr_tablet_pad_strip_source { + WLR_TABLET_PAD_STRIP_SOURCE_UNKNOWN, + WLR_TABLET_PAD_STRIP_SOURCE_FINGER, +}; + +struct wlr_tablet_pad_strip { + uint32_t time_sec; + uint64_t time_usec; + enum wlr_tablet_pad_strip_source source; + uint32_t strip; + double position; +}; enum wlr_input_device_type { WLR_INPUT_DEVICE_KEYBOARD, @@ -284,6 +331,7 @@ struct wlr_input_device { struct wlr_pointer *pointer; struct wlr_touch *touch; struct wlr_tablet_tool *tablet_tool; + struct wlr_tablet_pad *tablet_pad; }; }; diff --git a/types/CMakeLists.txt b/types/CMakeLists.txt index b10966ec..58f8a651 100644 --- a/types/CMakeLists.txt +++ b/types/CMakeLists.txt @@ -10,6 +10,7 @@ add_library(wlr-types wlr_pointer.c wlr_touch.c wlr_tablet_tool.c + wlr_tablet_pad.c ) target_link_libraries(wlr-types diff --git a/types/wlr_tablet_pad.c b/types/wlr_tablet_pad.c new file mode 100644 index 00000000..3143345f --- /dev/null +++ b/types/wlr_tablet_pad.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include +#include "types.h" + +struct wlr_tablet_pad *wlr_tablet_pad_create(struct wlr_tablet_pad_impl *impl, + struct wlr_tablet_pad_state *state) { + struct wlr_tablet_pad *pad = calloc(1, sizeof(struct wlr_tablet_pad)); + pad->impl = impl; + pad->state = state; + wl_signal_init(&pad->events.button); + wl_signal_init(&pad->events.ring); + wl_signal_init(&pad->events.strip); + return pad; +} + +void wlr_tablet_pad_destroy(struct wlr_tablet_pad *pad) { + if (!pad) return; + if (pad->impl) { + pad->impl->destroy(pad->state); + } + free(pad); +} From 632a04f1b7dea35f46a2fa478bf53869854a1b5e Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 19 Jun 2017 15:15:37 -0400 Subject: [PATCH 5/5] Implement keyboard LEDs --- backend/libinput/keyboard.c | 23 ++++++++++++++++++++++- example/shared.c | 19 +++++++++++++++++++ example/shared.h | 1 + include/types.h | 1 + include/wlr/types.h | 10 ++++++++++ types/wlr_keyboard.c | 6 ++++++ 6 files changed, 59 insertions(+), 1 deletion(-) diff --git a/backend/libinput/keyboard.c b/backend/libinput/keyboard.c index 9ad41a78..f94f0103 100644 --- a/backend/libinput/keyboard.c +++ b/backend/libinput/keyboard.c @@ -8,11 +8,32 @@ #include "common/log.h" #include "types.h" +struct wlr_keyboard_state { + struct libinput_device *device; +}; + +static void wlr_libinput_keyboard_set_leds(struct wlr_keyboard_state *kbstate, uint32_t leds) { + libinput_device_led_update(kbstate->device, leds); +} + +static void wlr_libinput_keyboard_destroy(struct wlr_keyboard_state *kbstate) { + libinput_device_unref(kbstate->device); + free(kbstate); +} + +struct wlr_keyboard_impl impl = { + .destroy = wlr_libinput_keyboard_destroy, + .led_update = wlr_libinput_keyboard_set_leds +}; + struct wlr_keyboard *wlr_libinput_keyboard_create( struct libinput_device *device) { assert(device); + struct wlr_keyboard_state *kbstate = calloc(1, sizeof(struct wlr_keyboard_state)); + kbstate->device = device; + libinput_device_ref(device); libinput_device_led_update(device, 0); - return wlr_keyboard_create(NULL, NULL); + return wlr_keyboard_create(&impl, kbstate); } void handle_keyboard_key(struct libinput_event *event, diff --git a/example/shared.c b/example/shared.c index 56cb89af..be1bdee7 100644 --- a/example/shared.c +++ b/example/shared.c @@ -12,6 +12,16 @@ #include #include "shared.h" +static void keyboard_led_update(struct keyboard_state *kbstate) { + uint32_t leds = 0; + for (uint32_t i = 0; i < WLR_LED_LAST; ++i) { + if (xkb_state_led_index_is_active(kbstate->xkb_state, kbstate->leds[i])) { + leds |= (1 << i); + } + } + wlr_keyboard_led_update(kbstate->device->keyboard, leds); +} + static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct wlr_keyboard_key *event = data; struct keyboard_state *kbstate = wl_container_of(listener, kbstate, key); @@ -33,6 +43,7 @@ static void keyboard_key_notify(struct wl_listener *listener, void *data) { } xkb_state_update_key(kbstate->xkb_state, keycode, event->state == WLR_KEY_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP); + keyboard_led_update(kbstate); } static void keyboard_add(struct wlr_input_device *device, struct compositor_state *state) { @@ -68,6 +79,14 @@ static void keyboard_add(struct wlr_input_device *device, struct compositor_stat fprintf(stderr, "Failed to create XKB state\n"); exit(1); } + const char *led_names[3] = { + XKB_LED_NAME_NUM, + XKB_LED_NAME_CAPS, + XKB_LED_NAME_SCROLL + }; + for (uint32_t i = 0; i < 3; ++i) { + kbstate->leds[i] = xkb_map_led_get_index(kbstate->keymap, led_names[i]); + } } static void pointer_motion_notify(struct wl_listener *listener, void *data) { diff --git a/example/shared.h b/example/shared.h index 173a5719..6d533443 100644 --- a/example/shared.h +++ b/example/shared.h @@ -25,6 +25,7 @@ struct keyboard_state { struct wl_list link; struct xkb_keymap *keymap; struct xkb_state *xkb_state; + xkb_led_index_t leds[WLR_LED_LAST]; void *data; }; diff --git a/include/types.h b/include/types.h index 2063c3f5..54aa5606 100644 --- a/include/types.h +++ b/include/types.h @@ -23,6 +23,7 @@ void wlr_output_free(struct wlr_output *output); struct wlr_keyboard_impl { void (*destroy)(struct wlr_keyboard_state *state); + void (*led_update)(struct wlr_keyboard_state *state, uint32_t leds); }; struct wlr_keyboard *wlr_keyboard_create(struct wlr_keyboard_impl *impl, diff --git a/include/wlr/types.h b/include/wlr/types.h index 2ca73cc2..1d2abab5 100644 --- a/include/wlr/types.h +++ b/include/wlr/types.h @@ -53,18 +53,28 @@ void wlr_output_destroy(struct wlr_output *output); void wlr_output_effective_resolution(struct wlr_output *output, int *width, int *height); +enum WLR_KEYBOARD_LED { + WLR_LED_NUM_LOCK = 1, + WLR_LED_CAPS_LOCK = 2, + WLR_LED_SCROLL_LOCK = 4, + WLR_LED_LAST +}; + struct wlr_keyboard_state; struct wlr_keyboard_impl; struct wlr_keyboard { struct wlr_keyboard_state *state; struct wlr_keyboard_impl *impl; + uint32_t leds; struct { struct wl_signal key; } events; }; +void wlr_keyboard_led_update(struct wlr_keyboard *keyboard, uint32_t leds); + enum wlr_key_state { WLR_KEY_RELEASED, WLR_KEY_PRESSED, diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c index 32728c78..c2ad5c49 100644 --- a/types/wlr_keyboard.c +++ b/types/wlr_keyboard.c @@ -21,3 +21,9 @@ void wlr_keyboard_destroy(struct wlr_keyboard *kb) { } free(kb); } + +void wlr_keyboard_led_update(struct wlr_keyboard *kb, uint32_t leds) { + if (kb->impl) { + kb->impl->led_update(kb->state, leds); + } +}