From 5dd96c077238b314162570655ea970ba6c2f8693 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 12 Jun 2017 21:53:41 -0400 Subject: Incorporate XKBCommon into example --- example/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'example/CMakeLists.txt') diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index e8f7ec72..bf9efd64 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -1,6 +1,7 @@ include_directories( ${DRM_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} + ${XKBCOMMON_INCLUDE_DIRS} ) add_executable(simple @@ -10,6 +11,7 @@ add_executable(simple target_link_libraries(simple wlr-backend wlr-session + ${XKBCOMMON_LIBRARIES} ) add_executable(rotation @@ -21,4 +23,5 @@ target_link_libraries(rotation wlr-backend wlr-session wlr-render + ${XKBCOMMON_LIBRARIES} ) -- cgit v1.2.3 From 0dbfe56c892f400a015c37d1f3574c8f9c985030 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 13 Jun 2017 10:13:11 -0400 Subject: Simplify examples --- example/CMakeLists.txt | 2 + example/rotation.c | 269 +++++++++++-------------------------------------- example/shared.c | 203 +++++++++++++++++++++++++++++++++++++ example/shared.h | 61 +++++++++++ example/simple.c | 219 +++++----------------------------------- 5 files changed, 349 insertions(+), 405 deletions(-) create mode 100644 example/shared.c create mode 100644 example/shared.h (limited to 'example/CMakeLists.txt') diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index bf9efd64..f659e5bb 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -6,6 +6,7 @@ include_directories( add_executable(simple simple.c + shared.c ) target_link_libraries(simple @@ -16,6 +17,7 @@ target_link_libraries(simple add_executable(rotation rotation.c + shared.c cat.c ) diff --git a/example/rotation.c b/example/rotation.c index 24c9f494..2634ea03 100644 --- a/example/rotation.c +++ b/example/rotation.c @@ -16,32 +16,17 @@ #include #include #include +#include "shared.h" #include "cat.h" -struct state { +struct sample_state { struct wl_list config; - struct xkb_keymap *keymap; - struct xkb_state *xkb_state; - bool exit; - - struct wl_list keyboards; - struct wl_listener input_add; - struct wl_listener input_remove; - - struct wl_list outputs; - struct wl_listener output_add; - struct wl_listener output_remove; - + // TODO: Move renderer into shared struct wlr_renderer *renderer; struct wlr_surface *cat_texture; }; -struct output_state { - struct timespec last_frame; - struct wl_list link; - struct wlr_output *output; - struct state *state; - struct wl_listener frame; +struct output_data { float x_offs, y_offs; float x_vel, y_vel; }; @@ -52,176 +37,93 @@ struct output_config { struct wl_list link; }; -struct keyboard_state { - struct state *state; - struct wlr_input_device *device; - struct wl_listener key; - struct wl_list link; -}; - -static void output_frame(struct wl_listener *listener, void *data) { - struct output_state *ostate = wl_container_of(listener, ostate, frame); - struct wlr_output *output = ostate->output; - struct state *s = ostate->state; +static void handle_output_frame(struct output_state *output, struct timespec *ts) { + struct compositor_state *state = output->compositor; + struct sample_state *sample = state->data; + struct output_data *odata = output->data; + struct wlr_output *wlr_output = output->output; int32_t width, height; - wlr_output_effective_resolution(output, &width, &height); + wlr_output_effective_resolution(wlr_output, &width, &height); - wlr_renderer_begin(s->renderer, output); + wlr_renderer_begin(sample->renderer, wlr_output); float matrix[16]; - for (int y = -128 + (int)ostate->y_offs; y < height; y += 128) { - for (int x = -128 + (int)ostate->x_offs; x < width; x += 128) { - wlr_surface_get_matrix(s->cat_texture, &matrix, - &output->transform_matrix, x, y); - wlr_render_with_matrix(s->renderer, s->cat_texture, &matrix); + for (int y = -128 + (int)odata->y_offs; y < height; y += 128) { + for (int x = -128 + (int)odata->x_offs; x < width; x += 128) { + wlr_surface_get_matrix(sample->cat_texture, &matrix, + &wlr_output->transform_matrix, x, y); + wlr_render_with_matrix(sample->renderer, + sample->cat_texture, &matrix); } } - wlr_renderer_end(s->renderer); + wlr_renderer_end(sample->renderer); - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - long ms = (now.tv_sec - ostate->last_frame.tv_sec) * 1000 + - (now.tv_nsec - ostate->last_frame.tv_nsec) / 1000000; + long ms = (ts->tv_sec - output->last_frame.tv_sec) * 1000 + + (ts->tv_nsec - output->last_frame.tv_nsec) / 1000000; float seconds = ms / 1000.0f; - ostate->x_offs += ostate->x_vel * seconds; - ostate->y_offs += ostate->y_vel * seconds; - if (ostate->x_offs > 128) ostate->x_offs = 0; - if (ostate->y_offs > 128) ostate->y_offs = 0; - ostate->last_frame = now; + odata->x_offs += odata->x_vel * seconds; + odata->y_offs += odata->y_vel * seconds; + if (odata->x_offs > 128) odata->x_offs = 0; + if (odata->y_offs > 128) odata->y_offs = 0; } -static void output_add(struct wl_listener *listener, void *data) { - struct wlr_output *output = data; - struct state *state = wl_container_of(listener, state, output_add); - - fprintf(stderr, "Output '%s' added\n", output->name); - wlr_output_set_mode(output, output->modes->items[0]); - - struct output_state *ostate = calloc(1, sizeof(struct output_state)); - - clock_gettime(CLOCK_MONOTONIC, &ostate->last_frame); - ostate->output = output; - ostate->state = state; - ostate->frame.notify = output_frame; - ostate->x_offs = ostate->y_offs = 0; - ostate->x_vel = ostate->y_vel = 128; +static void handle_output_add(struct output_state *output) { + struct output_data *odata = calloc(1, sizeof(struct output_data)); + odata->x_offs = odata->y_offs = 0; + odata->x_vel = odata->y_vel = 128; + output->data = odata; + struct sample_state *state = output->compositor->data; struct output_config *conf; wl_list_for_each(conf, &state->config, link) { - if (strcmp(conf->name, output->name) == 0) { - wlr_output_transform(ostate->output, conf->transform); + if (strcmp(conf->name, output->output->name) == 0) { + wlr_output_transform(output->output, conf->transform); break; } } - - wl_list_init(&ostate->frame.link); - wl_signal_add(&output->events.frame, &ostate->frame); - wl_list_insert(&state->outputs, &ostate->link); } -static void output_remove(struct wl_listener *listener, void *data) { - struct wlr_output *output = data; - struct state *state = wl_container_of(listener, state, output_remove); - struct output_state *ostate; - - wl_list_for_each(ostate, &state->outputs, link) { - if (ostate->output == output) { - wl_list_remove(&ostate->link); - wl_list_remove(&ostate->frame.link); - free(ostate); - break; - } - } +static void handle_output_remove(struct output_state *output) { + free(output->data); } -static void update_velocities(struct state *state, float x_diff, float y_diff) { - struct output_state *ostate; - wl_list_for_each(ostate, &state->outputs, link) { - ostate->x_vel += x_diff; - ostate->y_vel += y_diff; +static void update_velocities(struct compositor_state *state, + float x_diff, float y_diff) { + struct output_state *output; + wl_list_for_each(output, &state->outputs, link) { + struct output_data *odata = output->data; + odata->x_vel += x_diff; + odata->y_vel += y_diff; } } -static void handle_keysym(struct state *state, xkb_keysym_t sym, - enum wlr_key_state key_state) { - char name[64]; - int l = xkb_keysym_get_name(sym, name, sizeof(name)); - if (l != -1 && l != sizeof(name)) { - fprintf(stderr, "Key event: %s %s\n", name, - key_state == WLR_KEY_PRESSED ? "pressed" : "released"); - } +static void handle_keyboard_key(struct keyboard_state *kbstate, + xkb_keysym_t sym, enum wlr_key_state key_state) { // NOTE: It may be better to simply refer to our key state during each frame // and make this change in pixels/sec^2 + // Also, key repeat if (key_state == WLR_KEY_PRESSED) { switch (sym) { case XKB_KEY_Escape: - state->exit = true; + kbstate->compositor->exit = true; break; case XKB_KEY_Left: - update_velocities(state, -16, 0); + update_velocities(kbstate->compositor, -16, 0); break; case XKB_KEY_Right: - update_velocities(state, 16, 0); + update_velocities(kbstate->compositor, 16, 0); break; case XKB_KEY_Up: - update_velocities(state, 0, -16); + update_velocities(kbstate->compositor, 0, -16); break; case XKB_KEY_Down: - update_velocities(state, 0, 16); - break; - } - } -} - -static void keyboard_key(struct wl_listener *listener, void *data) { - struct wlr_keyboard_key *event = data; - struct keyboard_state *kbstate = wl_container_of(listener, kbstate, key); - uint32_t keycode = event->keycode + 8; - const xkb_keysym_t *syms; - int nsyms = xkb_state_key_get_syms(kbstate->state->xkb_state, keycode, &syms); - for (int i = 0; i < nsyms; ++i) { - handle_keysym(kbstate->state, syms[i], event->state); - } - xkb_state_update_key(kbstate->state->xkb_state, keycode, - event->state == WLR_KEY_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP); -} - -void input_add(struct wl_listener *listener, void *data) { - struct wlr_input_device *device = data; - struct state *state = wl_container_of(listener, state, input_add); - if (device->type != WLR_INPUT_DEVICE_KEYBOARD) { - return; - } - struct keyboard_state *kbstate = calloc(sizeof(struct keyboard_state), 1); - kbstate->device = device; - kbstate->state = state; - wl_list_init(&kbstate->key.link); - kbstate->key.notify = keyboard_key; - wl_signal_add(&device->keyboard->events.key, &kbstate->key); - wl_list_insert(&state->keyboards, &kbstate->link); -} - -void input_remove(struct wl_listener *listener, void *data) { - struct wlr_input_device *device = data; - struct state *state = wl_container_of(listener, state, input_add); - if (device->type != WLR_INPUT_DEVICE_KEYBOARD) { - return; - } - struct keyboard_state *kbstate = NULL, *_kbstate; - wl_list_for_each(_kbstate, &state->keyboards, link) { - if (_kbstate->device == device) { - kbstate = kbstate; + update_velocities(kbstate->compositor, 0, 16); break; } } - if (!kbstate) { - return; // We are unfamiliar with this keyboard - } - wl_list_remove(&kbstate->link); - wl_list_remove(&kbstate->key.link); } static void usage(const char *name, int ret) { @@ -291,82 +193,27 @@ static void parse_args(int argc, char *argv[], struct wl_list *config) { } int main(int argc, char *argv[]) { - struct state state = { - .exit = false, - .input_add = { .notify = input_add }, - .input_remove = { .notify = input_remove }, - .output_add = { .notify = output_add }, - .output_remove = { .notify = output_remove } - }; - - struct xkb_rule_names rules; - memset(&rules, 0, sizeof(rules)); - rules.rules = getenv("XKB_DEFAULT_RULES"); - rules.model = getenv("XKB_DEFAULT_MODEL"); - rules.layout = getenv("XKB_DEFAULT_LAYOUT"); - rules.variant = getenv("XKB_DEFAULT_VARIANT"); - rules.options = getenv("XKB_DEFAULT_OPTIONS"); - struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - if (!context) { - fprintf(stderr, "Failed to create XKB context\n"); - return 1; - } - state.keymap = - xkb_map_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - if (!state.keymap) { - fprintf(stderr, "Failed to create XKB keymap\n"); - return 1; - } - xkb_context_unref(context); - state.xkb_state = xkb_state_new(state.keymap); - - wl_list_init(&state.keyboards); - wl_list_init(&state.input_add.link); - wl_list_init(&state.input_remove.link); - - wl_list_init(&state.outputs); + struct sample_state state = { 0 }; + struct compositor_state compositor; wl_list_init(&state.config); - wl_list_init(&state.output_add.link); - wl_list_init(&state.output_remove.link); - parse_args(argc, argv, &state.config); - struct wl_display *display = wl_display_create(); - struct wl_event_loop *event_loop = wl_display_get_event_loop(display); - - struct wlr_session *session = wlr_session_start(display); - if (!session) { - return 1; - } - - struct wlr_backend *wlr = wlr_backend_autocreate(display, session); - if (!wlr) { - return 1; - } - - wl_signal_add(&wlr->events.input_add, &state.input_add); - wl_signal_add(&wlr->events.input_remove, &state.input_remove); - wl_signal_add(&wlr->events.output_add, &state.output_add); - wl_signal_add(&wlr->events.output_remove, &state.output_remove); - if (!wlr || !wlr_backend_init(wlr)) { - printf("Failed to initialize backend, bailing out\n"); - return 1; - } + compositor_init(&compositor); + compositor.output_add_cb = handle_output_add; + compositor.output_remove_cb = handle_output_remove; + compositor.output_frame_cb = handle_output_frame; + compositor.keyboard_key_cb = handle_keyboard_key; state.renderer = wlr_gles3_renderer_init(); state.cat_texture = wlr_render_surface_init(state.renderer); wlr_surface_attach_pixels(state.cat_texture, GL_RGB, cat_tex.width, cat_tex.height, cat_tex.pixel_data); - while (!state.exit) { - wl_event_loop_dispatch(event_loop, 0); - } + compositor.data = &state; + compositor_run(&compositor); - wlr_backend_destroy(wlr); - wlr_session_finish(session); wlr_surface_destroy(state.cat_texture); wlr_renderer_destroy(state.renderer); - wl_display_destroy(display); struct output_config *ptr, *tmp; wl_list_for_each_safe(ptr, tmp, &state.config, link) { diff --git a/example/shared.c b/example/shared.c new file mode 100644 index 00000000..58266214 --- /dev/null +++ b/example/shared.c @@ -0,0 +1,203 @@ +#define _POSIX_C_SOURCE 199309L +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "shared.h" + +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); + uint32_t keycode = event->keycode + 8; + enum wlr_key_state key_state = event->state; + const xkb_keysym_t *syms; + int nsyms = xkb_state_key_get_syms(kbstate->xkb_state, keycode, &syms); + for (int i = 0; i < nsyms; ++i) { + xkb_keysym_t sym = syms[i]; + char name[64]; + int l = xkb_keysym_get_name(sym, name, sizeof(name)); + if (l != -1 && l != sizeof(name)) { + fprintf(stderr, "Key event: %s %s\n", name, + key_state == WLR_KEY_PRESSED ? "pressed" : "released"); + } + if (kbstate->compositor->keyboard_key_cb) { + kbstate->compositor->keyboard_key_cb(kbstate, sym, key_state); + } + } + xkb_state_update_key(kbstate->xkb_state, keycode, + event->state == WLR_KEY_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP); +} + +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); + if (device->type != WLR_INPUT_DEVICE_KEYBOARD) { + return; + } + struct keyboard_state *kbstate = calloc(sizeof(struct keyboard_state), 1); + kbstate->device = device; + kbstate->compositor = state; + wl_list_init(&kbstate->key.link); + kbstate->key.notify = keyboard_key_notify; + wl_signal_add(&device->keyboard->events.key, &kbstate->key); + wl_list_insert(&state->keyboards, &kbstate->link); + + struct xkb_rule_names rules; + memset(&rules, 0, sizeof(rules)); + rules.rules = getenv("XKB_DEFAULT_RULES"); + rules.model = getenv("XKB_DEFAULT_MODEL"); + rules.layout = getenv("XKB_DEFAULT_LAYOUT"); + rules.variant = getenv("XKB_DEFAULT_VARIANT"); + rules.options = getenv("XKB_DEFAULT_OPTIONS"); + struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!context) { + fprintf(stderr, "Failed to create XKB context\n"); + exit(1); + } + kbstate->keymap = xkb_map_new_from_names( + context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + if (!kbstate->keymap) { + fprintf(stderr, "Failed to create XKB keymap\n"); + exit(1); + } + xkb_context_unref(context); + kbstate->xkb_state = xkb_state_new(kbstate->keymap); + if (!kbstate->xkb_state) { + fprintf(stderr, "Failed to create XKB state\n"); + exit(1); + } +} + +static void input_remove_notify(struct wl_listener *listener, void *data) { + struct wlr_input_device *device = data; + struct compositor_state *state = wl_container_of(listener, state, input_add); + if (device->type != WLR_INPUT_DEVICE_KEYBOARD) { + return; + } + struct keyboard_state *kbstate = NULL, *_kbstate; + wl_list_for_each(_kbstate, &state->keyboards, link) { + if (_kbstate->device == device) { + kbstate = kbstate; + break; + } + } + if (!kbstate) { + return; // We are unfamiliar with this keyboard + } + wl_list_remove(&kbstate->link); + wl_list_remove(&kbstate->key.link); +} + +static void output_frame_notify(struct wl_listener *listener, void *data) { + struct output_state *output = wl_container_of(listener, output, frame); + struct compositor_state *compositor = output->compositor; + + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + if (compositor->output_frame_cb) { + compositor->output_frame_cb(output, &now); + } + + output->last_frame = now; + compositor->last_frame = now; +} + +static void output_add_notify(struct wl_listener *listener, void *data) { + struct wlr_output *output = data; + struct compositor_state *state = wl_container_of(listener, state, output_add); + fprintf(stderr, "Output '%s' added\n", output->name); + fprintf(stderr, "%s %s %"PRId32"mm x %"PRId32"mm\n", output->make, output->model, + output->phys_width, output->phys_height); + wlr_output_set_mode(output, output->modes->items[0]); + struct output_state *ostate = calloc(1, sizeof(struct output_state)); + clock_gettime(CLOCK_MONOTONIC, &ostate->last_frame); + ostate->output = output; + ostate->compositor = state; + ostate->frame.notify = output_frame_notify; + wl_list_init(&ostate->frame.link); + wl_signal_add(&output->events.frame, &ostate->frame); + wl_list_insert(&state->outputs, &ostate->link); + if (state->output_add_cb) { + state->output_add_cb(ostate); + } +} + +static void output_remove_notify(struct wl_listener *listener, void *data) { + struct wlr_output *output = data; + struct compositor_state *state = wl_container_of(listener, state, output_remove); + struct output_state *ostate = NULL, *_ostate; + wl_list_for_each(_ostate, &state->outputs, link) { + if (_ostate->output == output) { + ostate = _ostate; + break; + } + } + if (!ostate) { + return; // We are unfamiliar with this output + } + if (state->output_remove_cb) { + state->output_remove_cb(ostate); + } + wl_list_remove(&ostate->link); + wl_list_remove(&ostate->frame.link); +} + +void compositor_init(struct compositor_state *state) { + memset(state, 0, sizeof(struct compositor_state)); + + state->display = wl_display_create(); + state->event_loop = wl_display_get_event_loop(state->display); + state->session = wlr_session_start(state->display); + if (!state->session + || !state->display + || !state->event_loop) { + exit(1); + } + + wl_list_init(&state->keyboards); + wl_list_init(&state->input_add.link); + state->input_add.notify = input_add_notify; + wl_list_init(&state->input_remove.link); + state->input_remove.notify = input_remove_notify; + + wl_list_init(&state->outputs); + wl_list_init(&state->output_add.link); + state->output_add.notify = output_add_notify; + wl_list_init(&state->output_remove.link); + state->output_remove.notify = output_remove_notify; + + struct wlr_backend *wlr = wlr_backend_autocreate( + state->display, state->session); + if (!wlr) { + exit(1); + } + wl_signal_add(&wlr->events.input_add, &state->input_add); + wl_signal_add(&wlr->events.input_remove, &state->input_remove); + wl_signal_add(&wlr->events.output_add, &state->output_add); + wl_signal_add(&wlr->events.output_remove, &state->output_remove); + state->backend = wlr; + + clock_gettime(CLOCK_MONOTONIC, &state->last_frame); +} + +void compositor_run(struct compositor_state *state) { + if (!wlr_backend_init(state->backend)) { + fprintf(stderr, "Failed to initialize backend\n"); + exit(1); + } + + while (!state->exit) { + wl_event_loop_dispatch(state->event_loop, 0); + } + + wlr_backend_destroy(state->backend); + wlr_session_finish(state->session); + wl_display_destroy(state->display); +} diff --git a/example/shared.h b/example/shared.h new file mode 100644 index 00000000..bafbee16 --- /dev/null +++ b/example/shared.h @@ -0,0 +1,61 @@ +#ifndef _EXAMPLE_SHARED_H +#define _EXAMPLE_SHARED_H +#define _POSIX_C_SOURCE 199309L +#include +#include +#include +#include +#include +#include +#include + +struct output_state { + struct compositor_state *compositor; + struct wlr_output *output; + struct wl_listener frame; + struct timespec last_frame; + struct wl_list link; + void *data; +}; + +struct keyboard_state { + struct compositor_state *compositor; + struct wlr_input_device *device; + struct wl_listener key; + struct wl_list link; + struct xkb_keymap *keymap; + struct xkb_state *xkb_state; + void *data; +}; + +struct compositor_state { + void (*output_add_cb)(struct output_state *s); + void (*keyboard_add_cb)(struct keyboard_state *s); + void (*output_frame_cb)(struct output_state *s, struct timespec *ts); + void (*output_remove_cb)(struct output_state *s); + void (*keyboard_remove_cb)(struct keyboard_state *s); + void (*keyboard_key_cb)(struct keyboard_state *s, xkb_keysym_t sym, + enum wlr_key_state key_state); + + struct wl_display *display; + struct wl_event_loop *event_loop; + struct wlr_backend *backend; + struct wlr_session *session; + + struct wl_list keyboards; + struct wl_listener input_add; + struct wl_listener input_remove; + + struct timespec last_frame; + struct wl_listener output_add; + struct wl_listener output_remove; + struct wl_list outputs; + + bool exit; + void *data; +}; + +void compositor_init(struct compositor_state *state); +void compositor_run(struct compositor_state *state); + +#endif diff --git a/example/simple.c b/example/simple.c index 331a0d08..5a5a1300 100644 --- a/example/simple.c +++ b/example/simple.c @@ -10,220 +10,51 @@ #include #include #include +#include "shared.h" -struct state { +struct sample_state { float color[3]; int dec; - bool exit; - struct timespec last_frame; - struct xkb_keymap *keymap; - struct xkb_state *xkb_state; - - struct wl_list keyboards; - struct wl_listener input_add; - struct wl_listener input_remove; - - struct wl_listener output_add; - struct wl_listener output_remove; - struct wl_list outputs; -}; - -struct output_state { - struct state *state; - struct wlr_output *output; - struct wl_listener frame; - struct wl_list link; -}; - -struct keyboard_state { - struct state *state; - struct wlr_input_device *device; - struct wl_listener key; - struct wl_list link; }; -void output_frame(struct wl_listener *listener, void *data) { - struct output_state *ostate = wl_container_of(listener, ostate, frame); - struct state *s = ostate->state; - - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); +void handle_output_frame(struct output_state *output, struct timespec *ts) { + struct compositor_state *state = output->compositor; + struct sample_state *sample = state->data; - long ms = (now.tv_sec - s->last_frame.tv_sec) * 1000 + - (now.tv_nsec - s->last_frame.tv_nsec) / 1000000; - int inc = (s->dec + 1) % 3; + long ms = (ts->tv_sec - state->last_frame.tv_sec) * 1000 + + (ts->tv_nsec - state->last_frame.tv_nsec) / 1000000; + int inc = (sample->dec + 1) % 3; - s->color[inc] += ms / 2000.0f; - s->color[s->dec] -= ms / 2000.0f; + sample->color[inc] += ms / 2000.0f; + sample->color[sample->dec] -= ms / 2000.0f; - if (s->color[s->dec] < 0.0f) { - s->color[inc] = 1.0f; - s->color[s->dec] = 0.0f; - s->dec = inc; + if (sample->color[sample->dec] < 0.0f) { + sample->color[inc] = 1.0f; + sample->color[sample->dec] = 0.0f; + sample->dec = inc; } - s->last_frame = now; - - glClearColor(s->color[0], s->color[1], s->color[2], 1.0); + glClearColor(sample->color[0], sample->color[1], sample->color[2], 1.0); glClear(GL_COLOR_BUFFER_BIT); } -void output_add(struct wl_listener *listener, void *data) { - struct wlr_output *output = data; - struct state *state = wl_container_of(listener, state, output_add); - fprintf(stderr, "Output '%s' added\n", output->name); - fprintf(stderr, "%s %s %"PRId32"mm x %"PRId32"mm\n", output->make, output->model, - output->phys_width, output->phys_height); - wlr_output_set_mode(output, output->modes->items[0]); - struct output_state *ostate = calloc(1, sizeof(struct output_state)); - ostate->output = output; - ostate->state = state; - ostate->frame.notify = output_frame; - wl_list_init(&ostate->frame.link); - wl_signal_add(&output->events.frame, &ostate->frame); - wl_list_insert(&state->outputs, &ostate->link); -} - -void output_remove(struct wl_listener *listener, void *data) { - struct wlr_output *output = data; - struct state *state = wl_container_of(listener, state, output_remove); - struct output_state *ostate = NULL, *_ostate; - wl_list_for_each(_ostate, &state->outputs, link) { - if (_ostate->output == output) { - ostate = _ostate; - break; - } - } - if (!ostate) { - return; // We are unfamiliar with this output - } - wl_list_remove(&ostate->link); - wl_list_remove(&ostate->frame.link); -} - -static void handle_keysym(struct state *state, xkb_keysym_t sym, - enum wlr_key_state key_state) { - char name[64]; - int l = xkb_keysym_get_name(sym, name, sizeof(name)); - if (l != -1 && l != sizeof(name)) { - fprintf(stderr, "Key event: %s %s\n", name, - key_state == WLR_KEY_PRESSED ? "pressed" : "released"); - } +static void handle_keyboard_key(struct keyboard_state *kbstate, + xkb_keysym_t sym, enum wlr_key_state key_state) { if (sym == XKB_KEY_Escape) { - state->exit = true; - } -} - -static void keyboard_key(struct wl_listener *listener, void *data) { - struct wlr_keyboard_key *event = data; - struct keyboard_state *kbstate = wl_container_of(listener, kbstate, key); - uint32_t keycode = event->keycode + 8; - const xkb_keysym_t *syms; - int nsyms = xkb_state_key_get_syms(kbstate->state->xkb_state, keycode, &syms); - for (int i = 0; i < nsyms; ++i) { - handle_keysym(kbstate->state, syms[i], event->state); - } - xkb_state_update_key(kbstate->state->xkb_state, keycode, - event->state == WLR_KEY_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP); -} - -void input_add(struct wl_listener *listener, void *data) { - struct wlr_input_device *device = data; - struct state *state = wl_container_of(listener, state, input_add); - if (device->type != WLR_INPUT_DEVICE_KEYBOARD) { - return; - } - struct keyboard_state *kbstate = calloc(sizeof(struct keyboard_state), 1); - kbstate->device = device; - kbstate->state = state; - wl_list_init(&kbstate->key.link); - kbstate->key.notify = keyboard_key; - wl_signal_add(&device->keyboard->events.key, &kbstate->key); - wl_list_insert(&state->keyboards, &kbstate->link); -} - -void input_remove(struct wl_listener *listener, void *data) { - struct wlr_input_device *device = data; - struct state *state = wl_container_of(listener, state, input_add); - if (device->type != WLR_INPUT_DEVICE_KEYBOARD) { - return; + kbstate->compositor->exit = true; } - struct keyboard_state *kbstate = NULL, *_kbstate; - wl_list_for_each(_kbstate, &state->keyboards, link) { - if (_kbstate->device == device) { - kbstate = kbstate; - break; - } - } - if (!kbstate) { - return; // We are unfamiliar with this keyboard - } - wl_list_remove(&kbstate->link); - wl_list_remove(&kbstate->key.link); } int main() { - struct state state = { + struct sample_state state = { .color = { 1.0, 0.0, 0.0 }, .dec = 0, - .exit = false, - .input_add = { .notify = input_add }, - .input_remove = { .notify = input_remove }, - .output_add = { .notify = output_add }, - .output_remove = { .notify = output_remove }, }; + struct compositor_state compositor; - struct xkb_rule_names rules; - memset(&rules, 0, sizeof(rules)); - rules.rules = getenv("XKB_DEFAULT_RULES"); - rules.model = getenv("XKB_DEFAULT_MODEL"); - rules.layout = getenv("XKB_DEFAULT_LAYOUT"); - rules.variant = getenv("XKB_DEFAULT_VARIANT"); - rules.options = getenv("XKB_DEFAULT_OPTIONS"); - struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - if (!context) { - fprintf(stderr, "Failed to create XKB context\n"); - return 1; - } - state.keymap = - xkb_map_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - if (!state.keymap) { - fprintf(stderr, "Failed to create XKB keymap\n"); - return 1; - } - xkb_context_unref(context); - state.xkb_state = xkb_state_new(state.keymap); - - wl_list_init(&state.keyboards); - wl_list_init(&state.input_add.link); - wl_list_init(&state.input_remove.link); - - wl_list_init(&state.outputs); - wl_list_init(&state.output_remove.link); - wl_list_init(&state.output_remove.link); - clock_gettime(CLOCK_MONOTONIC, &state.last_frame); - - struct wl_display *display = wl_display_create(); - struct wl_event_loop *event_loop = wl_display_get_event_loop(display); - - struct wlr_session *session = wlr_session_start(display); - if (!session) { - return 1; - } - - struct wlr_backend *wlr = wlr_backend_autocreate(display, session); - wl_signal_add(&wlr->events.input_add, &state.input_add); - wl_signal_add(&wlr->events.input_remove, &state.input_remove); - wl_signal_add(&wlr->events.output_add, &state.output_add); - wl_signal_add(&wlr->events.output_remove, &state.output_remove); - if (!wlr || !wlr_backend_init(wlr)) { - return 1; - } - - while (!state.exit) { - wl_event_loop_dispatch(event_loop, 0); - } - - wlr_backend_destroy(wlr); - wl_display_destroy(display); + compositor_init(&compositor); + compositor.output_frame_cb = handle_output_frame; + compositor.keyboard_key_cb = handle_keyboard_key; + compositor.data = &state; + compositor_run(&compositor); } -- cgit v1.2.3 From 2f9fd72fdcf9249ed16bcc029a86e734ae1487a1 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 13 Jun 2017 12:21:36 -0400 Subject: Add pointer example --- example/CMakeLists.txt | 13 ++++++++ example/pointer.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++ example/shared.c | 82 +++++++++++++++++++++++++++++++++++++++++++------- example/shared.h | 13 ++++++++ 4 files changed, 174 insertions(+), 11 deletions(-) create mode 100644 example/pointer.c (limited to 'example/CMakeLists.txt') diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index f659e5bb..ef11a822 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -27,3 +27,16 @@ target_link_libraries(rotation wlr-render ${XKBCOMMON_LIBRARIES} ) + +add_executable(pointer + pointer.c + shared.c + cat.c +) + +target_link_libraries(pointer + wlr-backend + wlr-session + wlr-render + ${XKBCOMMON_LIBRARIES} +) diff --git a/example/pointer.c b/example/pointer.c new file mode 100644 index 00000000..969fb721 --- /dev/null +++ b/example/pointer.c @@ -0,0 +1,77 @@ +#define _POSIX_C_SOURCE 199309L +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "shared.h" +#include "cat.h" + +struct sample_state { + struct wlr_renderer *renderer; + struct wlr_surface *cat_texture; + int cur_x, cur_y; +}; + +static void handle_output_frame(struct output_state *output, struct timespec *ts) { + struct compositor_state *state = output->compositor; + struct sample_state *sample = state->data; + struct wlr_output *wlr_output = output->output; + + wlr_renderer_begin(sample->renderer, wlr_output); + + float matrix[16]; + wlr_surface_get_matrix(sample->cat_texture, &matrix, + &wlr_output->transform_matrix, sample->cur_x, sample->cur_y); + wlr_render_with_matrix(sample->renderer, + sample->cat_texture, &matrix); + + wlr_renderer_end(sample->renderer); +} + +static void handle_keyboard_key(struct keyboard_state *kbstate, + xkb_keysym_t sym, enum wlr_key_state key_state) { + if (sym == XKB_KEY_Escape) { + kbstate->compositor->exit = true; + } +} + +static void handle_pointer_motion(struct pointer_state *pstate, + double d_x, double d_y) { + struct sample_state *state = pstate->compositor->data; + state->cur_x += d_x; + state->cur_y += d_y; +} + +int main(int argc, char *argv[]) { + struct sample_state state = { 0 }; + struct compositor_state compositor; + + compositor_init(&compositor); + compositor.output_frame_cb = handle_output_frame; + compositor.pointer_motion_cb = handle_pointer_motion; + compositor.keyboard_key_cb = handle_keyboard_key; + + state.renderer = wlr_gles3_renderer_init(); + state.cat_texture = wlr_render_surface_init(state.renderer); + wlr_surface_attach_pixels(state.cat_texture, GL_RGB, + cat_tex.width, cat_tex.height, cat_tex.pixel_data); + + compositor.data = &state; + compositor_run(&compositor); + + wlr_surface_destroy(state.cat_texture); + wlr_renderer_destroy(state.renderer); +} diff --git a/example/shared.c b/example/shared.c index 58266214..4657b7fe 100644 --- a/example/shared.c +++ b/example/shared.c @@ -35,12 +35,7 @@ static void keyboard_key_notify(struct wl_listener *listener, void *data) { event->state == WLR_KEY_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP); } -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); - if (device->type != WLR_INPUT_DEVICE_KEYBOARD) { - return; - } +static void keyboard_add(struct wlr_input_device *device, struct compositor_state *state) { struct keyboard_state *kbstate = calloc(sizeof(struct keyboard_state), 1); kbstate->device = device; kbstate->compositor = state; @@ -75,26 +70,90 @@ static void input_add_notify(struct wl_listener *listener, void *data) { } } -static void input_remove_notify(struct wl_listener *listener, void *data) { +static void pointer_motion_notify(struct wl_listener *listener, void *data) { + struct wlr_pointer_motion *event = data; + struct pointer_state *pstate = wl_container_of(listener, pstate, motion); + if (pstate->compositor->pointer_motion_cb) { + pstate->compositor->pointer_motion_cb(pstate, event->delta_x, event->delta_y); + } +} + +static void pointer_add(struct wlr_input_device *device, struct compositor_state *state) { + struct pointer_state *pstate = calloc(sizeof(struct pointer_state), 1); + pstate->device = device; + pstate->compositor = state; + wl_list_init(&pstate->motion.link); + wl_list_init(&pstate->motion_absolute.link); + wl_list_init(&pstate->button.link); + wl_list_init(&pstate->axis.link); + pstate->motion.notify = pointer_motion_notify; + wl_signal_add(&device->pointer->events.motion, &pstate->motion); + wl_list_insert(&state->pointers, &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); - if (device->type != WLR_INPUT_DEVICE_KEYBOARD) { - return; + switch (device->type) { + case WLR_INPUT_DEVICE_KEYBOARD: + keyboard_add(device, state); + break; + case WLR_INPUT_DEVICE_POINTER: + pointer_add(device, state); + break; + default: + break; } +} + +static void keyboard_remove(struct wlr_input_device *device, struct compositor_state *state) { struct keyboard_state *kbstate = NULL, *_kbstate; wl_list_for_each(_kbstate, &state->keyboards, link) { if (_kbstate->device == device) { - kbstate = kbstate; + kbstate = _kbstate; break; } } if (!kbstate) { - return; // We are unfamiliar with this keyboard + return; } wl_list_remove(&kbstate->link); wl_list_remove(&kbstate->key.link); } +static void pointer_remove(struct wlr_input_device *device, struct compositor_state *state) { + struct pointer_state *pstate = NULL, *_pstate; + wl_list_for_each(_pstate, &state->pointers, link) { + if (_pstate->device == device) { + pstate = _pstate; + break; + } + } + if (!pstate) { + return; + } + wl_list_remove(&pstate->link); + //wl_list_remove(&pstate->motion.link); + wl_list_remove(&pstate->motion_absolute.link); + //wl_list_remove(&pstate->button.link); + //wl_list_remove(&pstate->axis.link); +} + +static void input_remove_notify(struct wl_listener *listener, void *data) { + struct wlr_input_device *device = data; + struct compositor_state *state = wl_container_of(listener, state, input_add); + switch (device->type) { + case WLR_INPUT_DEVICE_KEYBOARD: + keyboard_remove(device, state); + break; + case WLR_INPUT_DEVICE_POINTER: + pointer_remove(device, state); + break; + default: + break; + } +} + static void output_frame_notify(struct wl_listener *listener, void *data) { struct output_state *output = wl_container_of(listener, output, frame); struct compositor_state *compositor = output->compositor; @@ -162,6 +221,7 @@ void compositor_init(struct compositor_state *state) { } wl_list_init(&state->keyboards); + wl_list_init(&state->pointers); 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 bafbee16..2c093414 100644 --- a/example/shared.h +++ b/example/shared.h @@ -28,6 +28,17 @@ struct keyboard_state { void *data; }; +struct pointer_state { + struct compositor_state *compositor; + struct wlr_input_device *device; + struct wl_listener motion; + struct wl_listener motion_absolute; + struct wl_listener button; + struct wl_listener axis; + 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); @@ -36,6 +47,7 @@ struct compositor_state { void (*keyboard_remove_cb)(struct keyboard_state *s); void (*keyboard_key_cb)(struct keyboard_state *s, xkb_keysym_t sym, enum wlr_key_state key_state); + void (*pointer_motion_cb)(struct pointer_state *s, double d_x, double d_y); struct wl_display *display; struct wl_event_loop *event_loop; @@ -43,6 +55,7 @@ struct compositor_state { struct wlr_session *session; struct wl_list keyboards; + struct wl_list pointers; struct wl_listener input_add; struct wl_listener input_remove; -- cgit v1.2.3 From 3f24f8a1bee10fb3aadf8c57ca107fe5aaa7cffa Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 14 Jun 2017 14:50:09 -0400 Subject: Flesh out touch events and add demo --- backend/libinput/events.c | 15 ++++++ backend/libinput/touch.c | 78 +++++++++++++++++++++++++++++ example/CMakeLists.txt | 13 +++++ example/shared.c | 86 ++++++++++++++++++++++++++++++-- example/shared.h | 18 +++++++ example/touch.c | 122 +++++++++++++++++++++++++++++++++++++++++++++ include/backend/libinput.h | 2 - include/wlr/types.h | 29 ++++++++++- types/wlr_touch.c | 1 - 9 files changed, 356 insertions(+), 8 deletions(-) create mode 100644 example/touch.c (limited to 'example/CMakeLists.txt') diff --git a/backend/libinput/events.c b/backend/libinput/events.c index 4af8082f..f8413dae 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -139,6 +139,21 @@ void wlr_libinput_event(struct wlr_backend_state *state, case LIBINPUT_EVENT_POINTER_AXIS: handle_pointer_axis(event, device); break; + case LIBINPUT_EVENT_TOUCH_DOWN: + handle_touch_down(event, device); + break; + case LIBINPUT_EVENT_TOUCH_UP: + handle_touch_up(event, device); + break; + case LIBINPUT_EVENT_TOUCH_MOTION: + handle_touch_motion(event, device); + break; + case LIBINPUT_EVENT_TOUCH_CANCEL: + handle_touch_cancel(event, device); + break; + case LIBINPUT_EVENT_TOUCH_FRAME: + // no-op (at least for now) + break; default: wlr_log(L_DEBUG, "Unknown libinput event %d", event_type); break; diff --git a/backend/libinput/touch.c b/backend/libinput/touch.c index 55e8609a..02c9cfef 100644 --- a/backend/libinput/touch.c +++ b/backend/libinput/touch.c @@ -13,3 +13,81 @@ struct wlr_touch *wlr_libinput_touch_create( assert(device); return wlr_touch_create(NULL, NULL); } + +void handle_touch_down(struct libinput_event *event, + struct libinput_device *device) { + struct wlr_input_device *dev = + get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, device); + if (!dev) { + wlr_log(L_DEBUG, "Got a touch event for a device with no touch?"); + return; + } + struct libinput_event_touch *tevent = + libinput_event_get_touch_event(event); + struct wlr_touch_down *wlr_event = + calloc(1, sizeof(struct wlr_touch_down)); + wlr_event->time_sec = libinput_event_touch_get_time(tevent); + wlr_event->time_usec = libinput_event_touch_get_time_usec(tevent); + wlr_event->slot = libinput_event_touch_get_slot(tevent); + wlr_event->x_mm = libinput_event_touch_get_x(tevent); + wlr_event->y_mm = libinput_event_touch_get_y(tevent); + libinput_device_get_size(device, &wlr_event->width_mm, &wlr_event->height_mm); + wl_signal_emit(&dev->touch->events.down, wlr_event); +} + +void handle_touch_up(struct libinput_event *event, + struct libinput_device *device) { + struct wlr_input_device *dev = + get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, device); + if (!dev) { + wlr_log(L_DEBUG, "Got a touch event for a device with no touch?"); + return; + } + struct libinput_event_touch *tevent = + libinput_event_get_touch_event(event); + struct wlr_touch_up *wlr_event = + calloc(1, sizeof(struct wlr_touch_up)); + wlr_event->time_sec = libinput_event_touch_get_time(tevent); + wlr_event->time_usec = libinput_event_touch_get_time_usec(tevent); + wlr_event->slot = libinput_event_touch_get_slot(tevent); + wl_signal_emit(&dev->touch->events.up, wlr_event); +} + +void handle_touch_motion(struct libinput_event *event, + struct libinput_device *device) { + struct wlr_input_device *dev = + get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, device); + if (!dev) { + wlr_log(L_DEBUG, "Got a touch event for a device with no touch?"); + return; + } + struct libinput_event_touch *tevent = + libinput_event_get_touch_event(event); + struct wlr_touch_motion *wlr_event = + calloc(1, sizeof(struct wlr_touch_motion)); + wlr_event->time_sec = libinput_event_touch_get_time(tevent); + wlr_event->time_usec = libinput_event_touch_get_time_usec(tevent); + wlr_event->slot = libinput_event_touch_get_slot(tevent); + wlr_event->x_mm = libinput_event_touch_get_x(tevent); + wlr_event->y_mm = libinput_event_touch_get_y(tevent); + libinput_device_get_size(device, &wlr_event->width_mm, &wlr_event->height_mm); + wl_signal_emit(&dev->touch->events.motion, wlr_event); +} + +void handle_touch_cancel(struct libinput_event *event, + struct libinput_device *device) { + struct wlr_input_device *dev = + get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, device); + if (!dev) { + wlr_log(L_DEBUG, "Got a touch event for a device with no touch?"); + return; + } + struct libinput_event_touch *tevent = + libinput_event_get_touch_event(event); + struct wlr_touch_cancel *wlr_event = + calloc(1, sizeof(struct wlr_touch_cancel)); + wlr_event->time_sec = libinput_event_touch_get_time(tevent); + wlr_event->time_usec = libinput_event_touch_get_time_usec(tevent); + wlr_event->slot = libinput_event_touch_get_slot(tevent); + wl_signal_emit(&dev->touch->events.cancel, wlr_event); +} diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index ef11a822..a6085392 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -40,3 +40,16 @@ target_link_libraries(pointer wlr-render ${XKBCOMMON_LIBRARIES} ) + +add_executable(touch + touch.c + shared.c + cat.c +) + +target_link_libraries(touch + wlr-backend + wlr-session + wlr-render + ${XKBCOMMON_LIBRARIES} +) diff --git a/example/shared.c b/example/shared.c index 6de16074..2592c924 100644 --- a/example/shared.c +++ b/example/shared.c @@ -114,6 +114,59 @@ static void pointer_add(struct wlr_input_device *device, struct compositor_state wl_list_insert(&state->pointers, &pstate->link); } +static void touch_down_notify(struct wl_listener *listener, void *data) { + struct wlr_touch_down *event = data; + struct touch_state *tstate = wl_container_of(listener, tstate, down); + if (tstate->compositor->touch_down_cb) { + tstate->compositor->touch_down_cb(tstate, event->slot, + event->x_mm, event->y_mm, event->width_mm, event->height_mm); + } +} + +static void touch_motion_notify(struct wl_listener *listener, void *data) { + struct wlr_touch_motion *event = data; + struct touch_state *tstate = wl_container_of(listener, tstate, motion); + if (tstate->compositor->touch_motion_cb) { + tstate->compositor->touch_motion_cb(tstate, event->slot, + event->x_mm, event->y_mm, event->width_mm, event->height_mm); + } +} + +static void touch_up_notify(struct wl_listener *listener, void *data) { + struct wlr_touch_up *event = data; + struct touch_state *tstate = wl_container_of(listener, tstate, up); + if (tstate->compositor->touch_up_cb) { + tstate->compositor->touch_up_cb(tstate, event->slot); + } +} + +static void touch_cancel_notify(struct wl_listener *listener, void *data) { + struct wlr_touch_cancel *event = data; + struct touch_state *tstate = wl_container_of(listener, tstate, cancel); + if (tstate->compositor->touch_cancel_cb) { + tstate->compositor->touch_cancel_cb(tstate, event->slot); + } +} + +static void touch_add(struct wlr_input_device *device, struct compositor_state *state) { + struct touch_state *tstate = calloc(sizeof(struct touch_state), 1); + tstate->device = device; + tstate->compositor = state; + wl_list_init(&tstate->down.link); + wl_list_init(&tstate->motion.link); + wl_list_init(&tstate->up.link); + wl_list_init(&tstate->cancel.link); + tstate->down.notify = touch_down_notify; + tstate->motion.notify = touch_motion_notify; + tstate->up.notify = touch_up_notify; + tstate->cancel.notify = touch_cancel_notify; + wl_signal_add(&device->touch->events.down, &tstate->down); + wl_signal_add(&device->touch->events.motion, &tstate->motion); + wl_signal_add(&device->touch->events.up, &tstate->up); + wl_signal_add(&device->touch->events.cancel, &tstate->cancel); + wl_list_insert(&state->touch, &tstate->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); @@ -124,6 +177,9 @@ static void input_add_notify(struct wl_listener *listener, void *data) { case WLR_INPUT_DEVICE_POINTER: pointer_add(device, state); break; + case WLR_INPUT_DEVICE_TOUCH: + touch_add(device, state); + break; default: break; } @@ -156,10 +212,28 @@ static void pointer_remove(struct wlr_input_device *device, struct compositor_st return; } wl_list_remove(&pstate->link); - //wl_list_remove(&pstate->motion.link); - wl_list_remove(&pstate->motion_absolute.link); - //wl_list_remove(&pstate->button.link); - //wl_list_remove(&pstate->axis.link); + wl_list_remove(&pstate->motion.link); + //wl_list_remove(&pstate->motion_absolute.link); + wl_list_remove(&pstate->button.link); + wl_list_remove(&pstate->axis.link); +} + +static void touch_remove(struct wlr_input_device *device, struct compositor_state *state) { + struct touch_state *tstate = NULL, *_tstate; + wl_list_for_each(_tstate, &state->touch, link) { + if (_tstate->device == device) { + tstate = _tstate; + break; + } + } + if (!tstate) { + return; + } + wl_list_remove(&tstate->link); + wl_list_remove(&tstate->down.link); + wl_list_remove(&tstate->motion.link); + wl_list_remove(&tstate->up.link); + wl_list_remove(&tstate->cancel.link); } static void input_remove_notify(struct wl_listener *listener, void *data) { @@ -172,6 +246,9 @@ static void input_remove_notify(struct wl_listener *listener, void *data) { case WLR_INPUT_DEVICE_POINTER: pointer_remove(device, state); break; + case WLR_INPUT_DEVICE_TOUCH: + touch_remove(device, state); + break; default: break; } @@ -245,6 +322,7 @@ void compositor_init(struct compositor_state *state) { wl_list_init(&state->keyboards); wl_list_init(&state->pointers); + wl_list_init(&state->touch); 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 7f0dade5..d09bcd0e 100644 --- a/example/shared.h +++ b/example/shared.h @@ -39,6 +39,17 @@ struct pointer_state { void *data; }; +struct touch_state { + struct compositor_state *compositor; + struct wlr_input_device *device; + struct wl_listener down; + struct wl_listener up; + struct wl_listener motion; + struct wl_listener cancel; + 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); @@ -55,6 +66,12 @@ struct compositor_state { enum wlr_axis_source source, enum wlr_axis_orientation orientation, double delta); + void (*touch_down_cb)(struct touch_state *s, int32_t slot, + double x, double y, double width, double height); + void (*touch_motion_cb)(struct touch_state *s, int32_t slot, + double x, double y, double width, double height); + void (*touch_up_cb)(struct touch_state *s, int32_t slot); + void (*touch_cancel_cb)(struct touch_state *s, int32_t slot); struct wl_display *display; struct wl_event_loop *event_loop; @@ -63,6 +80,7 @@ struct compositor_state { struct wl_list keyboards; struct wl_list pointers; + struct wl_list touch; struct wl_listener input_add; struct wl_listener input_remove; diff --git a/example/touch.c b/example/touch.c new file mode 100644 index 00000000..7f4f3800 --- /dev/null +++ b/example/touch.c @@ -0,0 +1,122 @@ +#define _POSIX_C_SOURCE 199309L +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "shared.h" +#include "cat.h" + +struct sample_state { + struct wlr_renderer *renderer; + struct wlr_surface *cat_texture; + list_t *touch_points; +}; + +struct touch_point { + int32_t slot; + double x, y; +}; + +static void handle_output_frame(struct output_state *output, struct timespec *ts) { + struct compositor_state *state = output->compositor; + struct sample_state *sample = state->data; + struct wlr_output *wlr_output = output->output; + + int32_t width, height; + wlr_output_effective_resolution(wlr_output, &width, &height); + wlr_renderer_begin(sample->renderer, wlr_output); + + float matrix[16]; + for (size_t i = 0; i < sample->touch_points->length; ++i) { + struct touch_point *p = sample->touch_points->items[i]; + wlr_surface_get_matrix(sample->cat_texture, &matrix, + &wlr_output->transform_matrix, + (int)(p->x * width) - sample->cat_texture->width / 2, + (int)(p->y * height) - sample->cat_texture->height / 2); + wlr_render_with_matrix(sample->renderer, + sample->cat_texture, &matrix); + } + + wlr_renderer_end(sample->renderer); +} + +static void handle_keyboard_key(struct keyboard_state *kbstate, + xkb_keysym_t sym, enum wlr_key_state key_state) { + if (sym == XKB_KEY_Escape) { + kbstate->compositor->exit = true; + } +} + +static void handle_touch_down(struct touch_state *tstate, int32_t slot, + double x, double y, double width, double height) { + struct sample_state *sample = tstate->compositor->data; + struct touch_point *point = calloc(1, sizeof(struct touch_state)); + point->slot = slot; + point->x = x / width; + point->y = y / height; + list_add(sample->touch_points, point); +} + +static void handle_touch_up(struct touch_state *tstate, int32_t slot) { + struct sample_state *sample = tstate->compositor->data; + for (size_t i = 0; i < sample->touch_points->length; ++i) { + struct touch_point *point = sample->touch_points->items[i]; + if (point->slot == slot) { + list_del(sample->touch_points, i); + break; + } + } +} + +static void handle_touch_motion(struct touch_state *tstate, int32_t slot, + double x, double y, double width, double height) { + struct sample_state *sample = tstate->compositor->data; + for (size_t i = 0; i < sample->touch_points->length; ++i) { + struct touch_point *point = sample->touch_points->items[i]; + if (point->slot == slot) { + point->x = x / width; + point->y = y / height; + break; + } + } +} + +int main(int argc, char *argv[]) { + struct sample_state state = { + .touch_points = list_create() + }; + struct compositor_state compositor; + + compositor_init(&compositor); + compositor.output_frame_cb = handle_output_frame; + compositor.keyboard_key_cb = handle_keyboard_key; + compositor.touch_down_cb = handle_touch_down; + compositor.touch_up_cb = handle_touch_up; + compositor.touch_motion_cb = handle_touch_motion; + + state.renderer = wlr_gles3_renderer_init(); + state.cat_texture = wlr_render_surface_init(state.renderer); + wlr_surface_attach_pixels(state.cat_texture, GL_RGB, + cat_tex.width, cat_tex.height, cat_tex.pixel_data); + + compositor.data = &state; + compositor_run(&compositor); + + wlr_surface_destroy(state.cat_texture); + wlr_renderer_destroy(state.renderer); +} diff --git a/include/backend/libinput.h b/include/backend/libinput.h index dd24fbb0..2427ae5c 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -56,7 +56,5 @@ void handle_touch_motion(struct libinput_event *event, struct libinput_device *device); void handle_touch_cancel(struct libinput_event *event, struct libinput_device *device); -void handle_touch_frame(struct libinput_event *event, - struct libinput_device *device); #endif diff --git a/include/wlr/types.h b/include/wlr/types.h index b4d69ccb..4763013a 100644 --- a/include/wlr/types.h +++ b/include/wlr/types.h @@ -146,10 +146,37 @@ struct wlr_touch { struct wl_signal up; struct wl_signal motion; struct wl_signal cancel; - struct wl_signal frame; } events; }; +struct wlr_touch_down { + uint32_t time_sec; + uint64_t time_usec; + int32_t slot; + double x_mm, y_mm; + double width_mm, height_mm; +}; + +struct wlr_touch_up { + uint32_t time_sec; + uint64_t time_usec; + int32_t slot; +}; + +struct wlr_touch_motion { + uint32_t time_sec; + uint64_t time_usec; + int32_t slot; + double x_mm, y_mm; + double width_mm, height_mm; +}; + +struct wlr_touch_cancel { + uint32_t time_sec; + uint64_t time_usec; + int32_t slot; +}; + // TODO: tablet & tablet tool // TODO: gestures // TODO: switch diff --git a/types/wlr_touch.c b/types/wlr_touch.c index 9c8b4b94..0970f70f 100644 --- a/types/wlr_touch.c +++ b/types/wlr_touch.c @@ -13,7 +13,6 @@ struct wlr_touch *wlr_touch_create(struct wlr_touch_impl *impl, wl_signal_init(&touch->events.down); wl_signal_init(&touch->events.up); wl_signal_init(&touch->events.motion); - wl_signal_init(&touch->events.frame); wl_signal_init(&touch->events.cancel); return touch; } -- cgit v1.2.3 From 2443a070e75e33285b6d5ed0ce89c989956b9065 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 15 Jun 2017 15:31:13 -0400 Subject: Add colored quad and ellipse rendering primitives --- example/CMakeLists.txt | 12 +++++++ example/tablet.c | 63 +++++++++++++++++++++++++++++++++++ include/render/gles3.h | 3 ++ include/wlr/render.h | 10 ++++++ include/wlr/render/interface.h | 4 +++ render/gles3/renderer.c | 35 ++++++++++++++++++++ render/gles3/shaders.c | 75 +++++++++++++++++++++++++++++++----------- render/wlr_renderer.c | 10 ++++++ 8 files changed, 192 insertions(+), 20 deletions(-) create mode 100644 example/tablet.c (limited to 'example/CMakeLists.txt') diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index a6085392..fff2e49b 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -53,3 +53,15 @@ target_link_libraries(touch wlr-render ${XKBCOMMON_LIBRARIES} ) + +add_executable(tablet + tablet.c + shared.c +) + +target_link_libraries(tablet + wlr-backend + wlr-session + wlr-render + ${XKBCOMMON_LIBRARIES} +) diff --git a/example/tablet.c b/example/tablet.c new file mode 100644 index 00000000..9a498438 --- /dev/null +++ b/example/tablet.c @@ -0,0 +1,63 @@ +#define _POSIX_C_SOURCE 199309L +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "shared.h" +#include "cat.h" + +struct sample_state { + struct wlr_renderer *renderer; +}; + +static void handle_output_frame(struct output_state *output, struct timespec *ts) { + struct compositor_state *state = output->compositor; + struct sample_state *sample = state->data; + struct wlr_output *wlr_output = output->output; + + wlr_renderer_begin(sample->renderer, wlr_output); + + float matrix[16]; + float color[4] = { 0, 1.0, 0, 1.0 }; + wlr_matrix_scale(&matrix, 128, 128, 1); + wlr_matrix_mul(&wlr_output->transform_matrix, &matrix, &matrix); + wlr_render_colored_ellipse(sample->renderer, &color, &matrix); + + wlr_renderer_end(sample->renderer); +} + +static void handle_keyboard_key(struct keyboard_state *kbstate, + xkb_keysym_t sym, enum wlr_key_state key_state) { + if (sym == XKB_KEY_Escape) { + kbstate->compositor->exit = true; + } +} + +int main(int argc, char *argv[]) { + struct sample_state state = { 0 }; + struct compositor_state compositor; + + compositor_init(&compositor); + compositor.output_frame_cb = handle_output_frame; + compositor.keyboard_key_cb = handle_keyboard_key; + + state.renderer = wlr_gles3_renderer_init(); + + compositor.data = &state; + compositor_run(&compositor); + + wlr_renderer_destroy(state.renderer); +} diff --git a/include/render/gles3.h b/include/render/gles3.h index 5efb197e..9acc1088 100644 --- a/include/render/gles3.h +++ b/include/render/gles3.h @@ -13,6 +13,9 @@ struct wlr_surface_state { struct wlr_surface *gles3_surface_init(); +extern const GLchar quad_vertex_src[]; +extern const GLchar quad_fragment_src[]; +extern const GLchar ellipse_fragment_src[]; extern const GLchar vertex_src[]; extern const GLchar fragment_src_RGB[]; extern const GLchar fragment_src_RGBA[]; diff --git a/include/wlr/render.h b/include/wlr/render.h index 88aa615e..3c0bd04b 100644 --- a/include/wlr/render.h +++ b/include/wlr/render.h @@ -28,6 +28,16 @@ struct wlr_surface *wlr_render_surface_init(struct wlr_renderer *r); */ bool wlr_render_with_matrix(struct wlr_renderer *r, struct wlr_surface *surface, const float (*matrix)[16]); +/** + * Renders a solid quad in the specified color. + */ +void wlr_render_colored_quad(struct wlr_renderer *r, + const float (*color)[4], const float (*matrix)[16]); +/** + * Renders a solid ellipse in the specified color. + */ +void wlr_render_colored_ellipse(struct wlr_renderer *r, + const float (*color)[4], const float (*matrix)[16]); /** * Destroys this wlr_renderer. Surfaces must be destroyed separately. */ diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index 80471ac8..a934f49e 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -19,6 +19,10 @@ struct wlr_renderer_impl { struct wlr_surface *(*surface_init)(struct wlr_renderer_state *state); bool (*render_with_matrix)(struct wlr_renderer_state *state, struct wlr_surface *surface, const float (*matrix)[16]); + void (*render_quad)(struct wlr_renderer_state *state, + const float (*color)[4], const float (*matrix)[16]); + void (*render_ellipse)(struct wlr_renderer_state *state, + const float (*color)[4], const float (*matrix)[16]); void (*destroy)(struct wlr_renderer_state *state); }; diff --git a/render/gles3/renderer.c b/render/gles3/renderer.c index 74754d1b..b0056193 100644 --- a/render/gles3/renderer.c +++ b/render/gles3/renderer.c @@ -13,6 +13,8 @@ static struct { bool initialized; GLuint rgb, rgba; + GLuint quad; + GLuint ellipse; } shaders; static GLuint vao, vbo, ebo; @@ -28,6 +30,9 @@ static bool compile_shader(GLuint type, const GLchar *src, GLuint *shader) { GL_CALL(glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &loglen)); GLchar msg[loglen]; GL_CALL(glGetShaderInfoLog(*shader, loglen, &loglen, msg)); + wlr_log(L_ERROR, "Shader compilation failed"); + wlr_log(L_ERROR, "%s", msg); + exit(1); return false; } return true; @@ -60,6 +65,12 @@ static void init_default_shaders() { if (!compile_program(vertex_src, fragment_src_RGBA, &shaders.rgba)) { goto error; } + if (!compile_program(quad_vertex_src, quad_fragment_src, &shaders.quad)) { + goto error; + } + if (!compile_program(quad_vertex_src, ellipse_fragment_src, &shaders.ellipse)) { + goto error; + } return; error: wlr_log(L_ERROR, "Failed to set up default shaders!"); @@ -141,6 +152,28 @@ static bool wlr_gles3_render_surface(struct wlr_renderer_state *state, return true; } +static void wlr_gles3_render_quad(struct wlr_renderer_state *state, + const float (*color)[4], const float (*matrix)[16]) { + GL_CALL(glUseProgram(shaders.quad)); + GL_CALL(glBindVertexArray(vao)); + GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vbo)); + GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)); + GL_CALL(glUniformMatrix4fv(0, 1, GL_TRUE, *matrix)); + GL_CALL(glUniform4f(1, (*color)[0], (*color)[1], (*color)[2], (*color)[3])); + GL_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)); +} + +static void wlr_gles3_render_ellipse(struct wlr_renderer_state *state, + const float (*color)[4], const float (*matrix)[16]) { + GL_CALL(glUseProgram(shaders.ellipse)); + GL_CALL(glBindVertexArray(vao)); + GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vbo)); + GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)); + GL_CALL(glUniformMatrix4fv(0, 1, GL_TRUE, *matrix)); + GL_CALL(glUniform4f(1, (*color)[0], (*color)[1], (*color)[2], (*color)[3])); + GL_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)); +} + static void wlr_gles3_destroy(struct wlr_renderer_state *state) { // no-op } @@ -150,6 +183,8 @@ static struct wlr_renderer_impl wlr_renderer_impl = { .end = wlr_gles3_end, .surface_init = wlr_gles3_surface_init, .render_with_matrix = wlr_gles3_render_surface, + .render_quad = wlr_gles3_render_quad, + .render_ellipse = wlr_gles3_render_ellipse, .destroy = wlr_gles3_destroy }; diff --git a/render/gles3/shaders.c b/render/gles3/shaders.c index f53ef385..dd7f790f 100644 --- a/render/gles3/shaders.c +++ b/render/gles3/shaders.c @@ -1,28 +1,63 @@ #include "render/gles3.h" #include +// Colored quads +const GLchar quad_vertex_src[] = +"uniform mat4 proj;" +"uniform vec4 color;" +"attribute vec2 pos;" +"attribute vec2 texcoord;" +"varying vec4 v_color;" +"varying vec2 v_texcoord;" +"void main() {" +" gl_Position = proj * vec4(pos, 0.0, 1.0);" +" v_color = color;" +" v_texcoord = texcoord;" +"}"; + +const GLchar quad_fragment_src[] = +"precision mediump float;" +"varying vec4 v_color;" +"varying vec2 v_texcoord;" +"void main() {" +" gl_FragColor = v_color;" +"}"; + +// Colored ellipses (TODO) + +const GLchar ellipse_fragment_src[] = +"precision mediump float;" +"varying vec4 v_color;" +"varying vec2 v_texcoord;" +"void main() {" +" float l = length(v_texcoord - vec2(0.5, 0.5));" +" if (l > 0.5) discard;" +" gl_FragColor = v_color;" +"}"; + +// Textured quads const GLchar vertex_src[] = -"uniform mat4 proj;\n" -"attribute vec2 pos;\n" -"attribute vec2 texcoord;\n" -"varying vec2 v_texcoord;\n" -"void main() {\n" -" gl_Position = proj * vec4(pos, 0.0, 1.0);\n" -" v_texcoord = texcoord;\n" -"}\n"; +"uniform mat4 proj;" +"attribute vec2 pos;" +"attribute vec2 texcoord;" +"varying vec2 v_texcoord;" +"void main() {" +" gl_Position = proj * vec4(pos, 0.0, 1.0);" +" v_texcoord = texcoord;" +"}"; const GLchar fragment_src_RGB[] = -"precision mediump float;\n" -"varying vec2 v_texcoord;\n" -"uniform sampler2D tex;\n" -"void main() {\n" -" gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);\n" -"}\n"; +"precision mediump float;" +"varying vec2 v_texcoord;" +"uniform sampler2D tex;" +"void main() {" +" gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);" +"}"; const GLchar fragment_src_RGBA[] = -"precision mediump float;\n" -"varying vec2 v_texcoord;\n" -"uniform sampler2D tex;\n" -"void main() {\n" -" gl_FragColor = texture2D(tex, v_texcoord);\n" -"}\n"; +"precision mediump float;" +"varying vec2 v_texcoord;" +"uniform sampler2D tex;" +"void main() {" +" gl_FragColor = texture2D(tex, v_texcoord);" +"}"; diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 2fd2fd31..f48bb3eb 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -31,3 +31,13 @@ bool wlr_render_with_matrix(struct wlr_renderer *r, struct wlr_surface *surface, const float (*matrix)[16]) { return r->impl->render_with_matrix(r->state, surface, matrix); } + +void wlr_render_colored_quad(struct wlr_renderer *r, + const float (*color)[4], const float (*matrix)[16]) { + r->impl->render_quad(r->state, color, matrix); +} + +void wlr_render_colored_ellipse(struct wlr_renderer *r, + const float (*color)[4], const float (*matrix)[16]) { + r->impl->render_ellipse(r->state, color, matrix); +} -- cgit v1.2.3