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;