diff options
author | emersion <contact@emersion.fr> | 2017-10-29 20:03:56 +0100 |
---|---|---|
committer | emersion <contact@emersion.fr> | 2017-10-31 12:30:57 +0100 |
commit | 044173d1dfbce7bdc3ae134a829f2bb0d88d208b (patch) | |
tree | 187beb42d2dadb9c37f00d5382b5a09ff0a9b550 /examples | |
parent | c3b09f73da0d1fc4815f4b085ca07e30d175f549 (diff) |
Add multi-pointer example
Diffstat (limited to 'examples')
-rw-r--r-- | examples/meson.build | 2 | ||||
-rw-r--r-- | examples/multi-pointer.c | 202 | ||||
-rw-r--r-- | examples/pointer.c | 22 |
3 files changed, 215 insertions, 11 deletions
diff --git a/examples/meson.build b/examples/meson.build index a29a3310..3402441b 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -8,6 +8,8 @@ executable('simple', 'simple.c', dependencies: wlroots, link_with: lib_shared) executable('pointer', 'pointer.c', dependencies: wlroots, link_with: lib_shared) executable('touch', 'touch.c', dependencies: wlroots, link_with: lib_shared) executable('tablet', 'tablet.c', dependencies: wlroots, link_with: lib_shared) +executable('multi-pointer', 'multi-pointer.c', dependencies: wlroots, + link_with: lib_shared) executable( 'rotation', diff --git a/examples/multi-pointer.c b/examples/multi-pointer.c new file mode 100644 index 00000000..c3a02cc7 --- /dev/null +++ b/examples/multi-pointer.c @@ -0,0 +1,202 @@ +#define _POSIX_C_SOURCE 199309L +#define _XOPEN_SOURCE 500 +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <string.h> +#include <unistd.h> +#include <math.h> +#include <assert.h> +#include <wayland-server.h> +#include <wayland-server-protocol.h> +#include <xkbcommon/xkbcommon.h> +#include <GLES2/gl2.h> +#include <wlr/render/matrix.h> +#include <wlr/render/gles2.h> +#include <wlr/render.h> +#include <wlr/backend.h> +#include <wlr/backend/session.h> +#include <wlr/types/wlr_keyboard.h> +#include <wlr/types/wlr_output_layout.h> +#include <wlr/xcursor.h> +#include <wlr/types/wlr_cursor.h> +#include <wlr/util/log.h> +#include <wlr/types/wlr_list.h> +#include "shared.h" +#include "config.h" +#include "cat.h" + +struct sample_state; + +struct sample_cursor { + struct sample_state *state; + struct wlr_input_device *device; + struct wlr_cursor *cursor; + struct wl_list link; + + struct wl_listener cursor_motion; + struct wl_listener cursor_motion_absolute; + struct wl_listener cursor_button; + struct wl_listener cursor_axis; +}; + +struct sample_state { + struct compositor_state *compositor; + struct example_config *config; + struct wlr_xcursor *xcursor; + float default_color[4]; + float clear_color[4]; + struct wlr_output_layout *layout; + struct wl_list cursors; // sample_cursor::link +}; + +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_output_make_current(wlr_output); + + glClearColor(sample->clear_color[0], sample->clear_color[1], + sample->clear_color[2], sample->clear_color[3]); + glClear(GL_COLOR_BUFFER_BIT); + + wlr_output_swap_buffers(wlr_output); +} + +static void handle_output_add(struct output_state *ostate) { + struct sample_state *sample = ostate->compositor->data; + + struct output_config *o_config = + example_config_get_output(sample->config, ostate->output); + + if (o_config) { + wlr_output_transform(ostate->output, o_config->transform); + wlr_output_layout_add(sample->layout, ostate->output, o_config->x, + o_config->y); + } else { + wlr_output_layout_add_auto(sample->layout, ostate->output); + } + + struct sample_cursor *cursor; + wl_list_for_each(cursor, &sample->cursors, link) { + example_config_configure_cursor(sample->config, cursor->cursor, + sample->compositor); + + // TODO the cursor must be set depending on which surface it is + // displayed over which should happen in the compositor. + struct wlr_xcursor_image *image = sample->xcursor->images[0]; + wlr_cursor_set_image(cursor->cursor, image->buffer, image->width, + image->width, image->height, image->hotspot_x, image->hotspot_y); + + wlr_cursor_warp(cursor->cursor, NULL, cursor->cursor->x, + cursor->cursor->y); + } +} + +static void handle_output_remove(struct output_state *ostate) { + struct sample_state *sample = ostate->compositor->data; + + wlr_output_layout_remove(sample->layout, ostate->output); + + struct sample_cursor *cursor; + wl_list_for_each(cursor, &sample->cursors, link) { + example_config_configure_cursor(sample->config, cursor->cursor, + sample->compositor); + } +} + +static void handle_cursor_motion(struct wl_listener *listener, void *data) { + struct sample_cursor *cursor = + wl_container_of(listener, cursor, cursor_motion); + struct wlr_event_pointer_motion *event = data; + wlr_cursor_move(cursor->cursor, event->device, event->delta_x, + event->delta_y); +} + +static void handle_cursor_motion_absolute(struct wl_listener *listener, + void *data) { + struct sample_cursor *cursor = + wl_container_of(listener, cursor, cursor_motion_absolute); + struct wlr_event_pointer_motion_absolute *event = data; + wlr_cursor_warp_absolute(cursor->cursor, event->device, + event->x_mm / event->width_mm, event->y_mm / event->height_mm); +} + +static void handle_input_add(struct compositor_state *state, + struct wlr_input_device *device) { + struct sample_state *sample = state->data; + + if (device->type != WLR_INPUT_DEVICE_POINTER) { + return; + } + + struct sample_cursor *cursor = calloc(1, sizeof(struct sample_cursor)); + cursor->state = sample; + + cursor->cursor = wlr_cursor_create(); + wlr_cursor_attach_output_layout(cursor->cursor, sample->layout); + wlr_cursor_map_to_region(cursor->cursor, sample->config->cursor.mapped_box); + + wl_signal_add(&cursor->cursor->events.motion, &cursor->cursor_motion); + cursor->cursor_motion.notify = handle_cursor_motion; + wl_signal_add(&cursor->cursor->events.motion_absolute, + &cursor->cursor_motion_absolute); + cursor->cursor_motion_absolute.notify = handle_cursor_motion_absolute; + + wlr_cursor_attach_input_device(cursor->cursor, device); + example_config_configure_cursor(sample->config, cursor->cursor, + sample->compositor); + + struct wlr_xcursor_image *image = sample->xcursor->images[0]; + wlr_cursor_set_image(cursor->cursor, image->buffer, image->width, + image->width, image->height, image->hotspot_x, image->hotspot_y); + + wl_list_insert(&sample->cursors, &cursor->link); +} + +int main(int argc, char *argv[]) { + struct sample_state state = { + .default_color = { 0.25f, 0.25f, 0.25f, 1 }, + .clear_color = { 0.25f, 0.25f, 0.25f, 1 }, + }; + + wl_list_init(&state.cursors); + + state.config = parse_args(argc, argv); + state.layout = wlr_output_layout_create(); + + struct compositor_state compositor = { 0 }; + compositor.data = &state; + compositor.output_add_cb = handle_output_add; + compositor.output_remove_cb = handle_output_remove; + compositor.output_frame_cb = handle_output_frame; + compositor.input_add_cb = handle_input_add; + + state.compositor = &compositor; + + struct wlr_xcursor_theme *theme = wlr_xcursor_theme_load("default", 16); + if (!theme) { + wlr_log(L_ERROR, "Failed to load cursor theme"); + return 1; + } + state.xcursor = wlr_xcursor_theme_get_cursor(theme, "left_ptr"); + if (!state.xcursor) { + wlr_log(L_ERROR, "Failed to load left_ptr cursor"); + return 1; + } + + compositor_init(&compositor); + if (!wlr_backend_start(compositor.backend)) { + wlr_log(L_ERROR, "Failed to start backend"); + wlr_backend_destroy(compositor.backend); + exit(1); + } + wl_display_run(compositor.display); + compositor_fini(&compositor); + + wlr_xcursor_theme_destroy(theme); + example_config_destroy(state.config); + wlr_output_layout_destroy(state.layout); +} diff --git a/examples/pointer.c b/examples/pointer.c index 77f5192f..83122421 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -60,7 +60,7 @@ struct touch_point { }; static void warp_to_touch(struct sample_state *sample, - struct wlr_input_device *dev) { + struct wlr_input_device *dev) { if (sample->touch_points->length == 0) { return; } @@ -77,7 +77,7 @@ static void warp_to_touch(struct sample_state *sample, } static void handle_output_frame(struct output_state *output, - struct timespec *ts) { + struct timespec *ts) { struct compositor_state *state = output->compositor; struct sample_state *sample = state->data; struct wlr_output *wlr_output = output->output; @@ -127,7 +127,7 @@ static void handle_output_remove(struct output_state *ostate) { } static void handle_input_add(struct compositor_state *state, - struct wlr_input_device *device) { + struct wlr_input_device *device) { struct sample_state *sample = state->data; if (device->type == WLR_INPUT_DEVICE_POINTER || @@ -141,16 +141,16 @@ static void handle_input_add(struct compositor_state *state, static void handle_cursor_motion(struct wl_listener *listener, void *data) { struct sample_state *sample = - wl_container_of(listener, sample, cursor_motion); + wl_container_of(listener, sample, cursor_motion); struct wlr_event_pointer_motion *event = data; wlr_cursor_move(sample->cursor, event->device, event->delta_x, - event->delta_y); + event->delta_y); } static void handle_cursor_motion_absolute(struct wl_listener *listener, - void *data) { + void *data) { struct sample_state *sample = - wl_container_of(listener, sample, cursor_motion_absolute); + wl_container_of(listener, sample, cursor_motion_absolute); struct wlr_event_pointer_motion_absolute *event = data; sample->cur_x = event->x_mm; @@ -162,7 +162,7 @@ static void handle_cursor_motion_absolute(struct wl_listener *listener, static void handle_cursor_button(struct wl_listener *listener, void *data) { struct sample_state *sample = - wl_container_of(listener, sample, cursor_button); + wl_container_of(listener, sample, cursor_button); struct wlr_event_pointer_button *event = data; float (*color)[4]; @@ -179,7 +179,7 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { static void handle_cursor_axis(struct wl_listener *listener, void *data) { struct sample_state *sample = - wl_container_of(listener, sample, cursor_axis); + wl_container_of(listener, sample, cursor_axis); struct wlr_event_pointer_axis *event = data; for (size_t i = 0; i < 3; ++i) { @@ -226,7 +226,7 @@ static void handle_touch_down(struct wl_listener *listener, void *data) { static void handle_touch_motion(struct wl_listener *listener, void *data) { struct sample_state *sample = - wl_container_of(listener, sample, touch_motion); + wl_container_of(listener, sample, touch_motion); struct wlr_event_touch_motion *event = data; for (size_t i = 0; i < sample->touch_points->length; ++i) { struct touch_point *point = sample->touch_points->items[i]; @@ -246,7 +246,7 @@ static void handle_touch_cancel(struct wl_listener *listener, void *data) { static void handle_tablet_tool_axis(struct wl_listener *listener, void *data) { struct sample_state *sample = - wl_container_of(listener, sample, tablet_tool_axis); + wl_container_of(listener, sample, tablet_tool_axis); struct wlr_event_tablet_tool_axis *event = data; if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X) && (event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) { |