From 411078815953ef0a29e61b49868e646ad899fb01 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Sat, 19 Aug 2017 21:48:20 +0200 Subject: move wl_compositor into wlroots as wlr_compositor --- examples/compositor.c | 191 ++++++++++++++++++++++++++++++++++++ examples/compositor.h | 20 ---- examples/compositor/main.c | 190 ----------------------------------- examples/compositor/wl_compositor.c | 72 -------------- examples/meson.build | 7 +- include/wlr/types/wlr_compositor.h | 21 ++++ types/meson.build | 1 + types/wlr_compositor.c | 77 +++++++++++++++ 8 files changed, 291 insertions(+), 288 deletions(-) create mode 100644 examples/compositor.c delete mode 100644 examples/compositor.h delete mode 100644 examples/compositor/main.c delete mode 100644 examples/compositor/wl_compositor.c create mode 100644 include/wlr/types/wlr_compositor.h create mode 100644 types/wlr_compositor.c diff --git a/examples/compositor.c b/examples/compositor.c new file mode 100644 index 00000000..54ab5d5f --- /dev/null +++ b/examples/compositor.c @@ -0,0 +1,191 @@ +#define _POSIX_C_SOURCE 199309L +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wlr/types/wlr_compositor.h" +#include +#include +#include "shared.h" + +// TODO: move to common header? +int os_create_anonymous_file(off_t size); + +struct sample_state { + struct wlr_renderer *renderer; + struct wlr_compositor compositor; + struct wlr_wl_shell *wl_shell; + struct wlr_seat *wl_seat; + struct wlr_xdg_shell_v6 *xdg_shell; + struct wlr_data_device_manager *data_device_manager; + struct wl_resource *focus; + struct wl_listener keyboard_bound; + int keymap_fd; + size_t keymap_size; + uint32_t serial; +}; + +/* + * Convert timespec to milliseconds + */ +static inline int64_t timespec_to_msec(const struct timespec *a) { + return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; +} + +static void output_frame_handle_surface(struct sample_state *sample, + struct wlr_output *wlr_output, struct timespec *ts, + struct wl_resource *_res) { + struct wlr_surface *surface = wl_resource_get_user_data(_res); + float matrix[16]; + float transform[16]; + wlr_surface_flush_damage(surface); + if (surface->texture->valid) { + wlr_matrix_translate(&transform, 200, 200, 0); + wlr_surface_get_matrix(surface, &matrix, + &wlr_output->transform_matrix, &transform); + wlr_render_with_matrix(sample->renderer, surface->texture, &matrix); + + struct wlr_frame_callback *cb, *cnext; + wl_list_for_each_safe(cb, cnext, &surface->frame_callback_list, link) { + wl_callback_send_done(cb->resource, timespec_to_msec(ts)); + wl_resource_destroy(cb->resource); + } + } +} +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); + wlr_renderer_begin(sample->renderer, wlr_output); + + struct wlr_wl_shell_surface *wl_shell_surface; + wl_list_for_each(wl_shell_surface, &sample->wl_shell->surfaces, link) { + output_frame_handle_surface(sample, wlr_output, ts, wl_shell_surface->surface); + } + struct wlr_xdg_surface_v6 *xdg_surface; + wl_list_for_each(xdg_surface, &sample->xdg_shell->surfaces, link) { + output_frame_handle_surface(sample, wlr_output, ts, xdg_surface->surface); + } + + wlr_renderer_end(sample->renderer); + wlr_output_swap_buffers(wlr_output); +} + +static void handle_keyboard_key(struct keyboard_state *keyboard, uint32_t keycode, + xkb_keysym_t sym, enum wlr_key_state key_state) { + struct compositor_state *state = keyboard->compositor; + struct sample_state *sample = state->data; + + struct wl_resource *res = NULL; + struct wlr_seat_handle *seat_handle = NULL; + wl_list_for_each(res, &sample->compositor.surfaces, link) { + break; + } + + if (res) { + seat_handle = wlr_seat_handle_for_client(sample->wl_seat, + wl_resource_get_client(res)); + } + + if (res != sample->focus && seat_handle && seat_handle->keyboard) { + struct wl_array keys; + wl_array_init(&keys); + wl_keyboard_send_enter(seat_handle->keyboard, ++sample->serial, res, &keys); + sample->focus = res; + } + + if (seat_handle && seat_handle->keyboard) { + uint32_t depressed = xkb_state_serialize_mods(keyboard->xkb_state, + XKB_STATE_MODS_DEPRESSED); + uint32_t latched = xkb_state_serialize_mods(keyboard->xkb_state, + XKB_STATE_MODS_LATCHED); + uint32_t locked = xkb_state_serialize_mods(keyboard->xkb_state, + XKB_STATE_MODS_LOCKED); + uint32_t group = xkb_state_serialize_layout(keyboard->xkb_state, + XKB_STATE_LAYOUT_EFFECTIVE); + wl_keyboard_send_modifiers(seat_handle->keyboard, ++sample->serial, depressed, + latched, locked, group); + wl_keyboard_send_key(seat_handle->keyboard, ++sample->serial, 0, keycode, key_state); + } +} + +static void handle_keyboard_bound(struct wl_listener *listener, void *data) { + struct wlr_seat_handle *handle = data; + struct sample_state *state = wl_container_of(listener, state, keyboard_bound); + + wl_keyboard_send_keymap(handle->keyboard, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, + state->keymap_fd, state->keymap_size); + + if (wl_resource_get_version(handle->keyboard) >= 2) { + wl_keyboard_send_repeat_info(handle->keyboard, 25, 600); + } +} + +int main() { + struct sample_state state = { 0 }; + struct compositor_state compositor = { 0, + .data = &state, + .output_frame_cb = handle_output_frame, + .keyboard_key_cb = handle_keyboard_key + }; + compositor_init(&compositor); + + state.renderer = wlr_gles2_renderer_create(compositor.backend); + if (!state.renderer) { + wlr_log(L_ERROR, "Could not start compositor, OOM"); + exit(EXIT_FAILURE); + } + wl_display_init_shm(compositor.display); + wlr_compositor_init(&state.compositor, compositor.display, state.renderer); + state.wl_shell = wlr_wl_shell_create(compositor.display); + state.xdg_shell = wlr_xdg_shell_v6_create(compositor.display); + state.data_device_manager = wlr_data_device_manager_create(compositor.display); + + state.wl_seat = wlr_seat_create(compositor.display, "seat0"); + state.keyboard_bound.notify = handle_keyboard_bound; + wl_signal_add(&state.wl_seat->events.keyboard_bound, &state.keyboard_bound); + wlr_seat_set_capabilities(state.wl_seat, WL_SEAT_CAPABILITY_KEYBOARD + | WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_TOUCH); + + struct keyboard_state *kbstate; + wl_list_for_each(kbstate, &compositor.keyboards, link) { + char *keymap = xkb_keymap_get_as_string(kbstate->keymap, + XKB_KEYMAP_FORMAT_TEXT_V1); + state.keymap_size = strlen(keymap); + state.keymap_fd = os_create_anonymous_file(state.keymap_size); + void *ptr = mmap(NULL, state.keymap_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, state.keymap_fd, 0); + strcpy(ptr, keymap); + free(keymap); + break; + } + + wl_display_run(compositor.display); + + close(state.keymap_fd); + wlr_seat_destroy(state.wl_seat); + wlr_data_device_manager_destroy(state.data_device_manager); + wlr_xdg_shell_v6_destroy(state.xdg_shell); + wlr_wl_shell_destroy(state.wl_shell); + wlr_compositor_finish(&state.compositor); + wlr_renderer_destroy(state.renderer); + compositor_fini(&compositor); +} diff --git a/examples/compositor.h b/examples/compositor.h deleted file mode 100644 index b382cc7f..00000000 --- a/examples/compositor.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _EXAMPLE_COMPOSITOR_H -#define _EXAMPLE_COMPOSITOR_H -#include -#include - -struct wl_compositor_state { - struct wl_global *wl_global; - struct wl_list wl_resources; - struct wlr_renderer *renderer; - struct wl_list surfaces; - struct wl_listener destroy_surface_listener; -}; - -void wl_compositor_init(struct wl_display *display, - struct wl_compositor_state *state, struct wlr_renderer *renderer); - -struct wlr_surface; -void wl_compositor_surface_destroyed(struct wl_compositor_state *compositor, - struct wlr_surface *surface); -#endif diff --git a/examples/compositor/main.c b/examples/compositor/main.c deleted file mode 100644 index 4c6e213d..00000000 --- a/examples/compositor/main.c +++ /dev/null @@ -1,190 +0,0 @@ -#define _POSIX_C_SOURCE 199309L -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "shared.h" -#include "compositor.h" - -// TODO: move to common header? -int os_create_anonymous_file(off_t size); - -struct sample_state { - struct wlr_renderer *renderer; - struct wl_compositor_state compositor; - struct wlr_wl_shell *wl_shell; - struct wlr_seat *wl_seat; - struct wlr_xdg_shell_v6 *xdg_shell; - struct wlr_data_device_manager *data_device_manager; - struct wl_resource *focus; - struct wl_listener keyboard_bound; - int keymap_fd; - size_t keymap_size; - uint32_t serial; -}; - -/* - * Convert timespec to milliseconds - */ -static inline int64_t timespec_to_msec(const struct timespec *a) { - return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; -} - -static void output_frame_handle_surface(struct sample_state *sample, - struct wlr_output *wlr_output, struct timespec *ts, - struct wl_resource *_res) { - struct wlr_surface *surface = wl_resource_get_user_data(_res); - float matrix[16]; - float transform[16]; - wlr_surface_flush_damage(surface); - if (surface->texture->valid) { - wlr_matrix_translate(&transform, 200, 200, 0); - wlr_surface_get_matrix(surface, &matrix, - &wlr_output->transform_matrix, &transform); - wlr_render_with_matrix(sample->renderer, surface->texture, &matrix); - - struct wlr_frame_callback *cb, *cnext; - wl_list_for_each_safe(cb, cnext, &surface->frame_callback_list, link) { - wl_callback_send_done(cb->resource, timespec_to_msec(ts)); - wl_resource_destroy(cb->resource); - } - } -} -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); - wlr_renderer_begin(sample->renderer, wlr_output); - - struct wlr_wl_shell_surface *wl_shell_surface; - wl_list_for_each(wl_shell_surface, &sample->wl_shell->surfaces, link) { - output_frame_handle_surface(sample, wlr_output, ts, wl_shell_surface->surface); - } - struct wlr_xdg_surface_v6 *xdg_surface; - wl_list_for_each(xdg_surface, &sample->xdg_shell->surfaces, link) { - output_frame_handle_surface(sample, wlr_output, ts, xdg_surface->surface); - } - - wlr_renderer_end(sample->renderer); - wlr_output_swap_buffers(wlr_output); -} - -static void handle_keyboard_key(struct keyboard_state *keyboard, uint32_t keycode, - xkb_keysym_t sym, enum wlr_key_state key_state) { - struct compositor_state *state = keyboard->compositor; - struct sample_state *sample = state->data; - - struct wl_resource *res = NULL; - struct wlr_seat_handle *seat_handle = NULL; - wl_list_for_each(res, &sample->compositor.surfaces, link) { - break; - } - - if (res) { - seat_handle = wlr_seat_handle_for_client(sample->wl_seat, - wl_resource_get_client(res)); - } - - if (res != sample->focus && seat_handle && seat_handle->keyboard) { - struct wl_array keys; - wl_array_init(&keys); - wl_keyboard_send_enter(seat_handle->keyboard, ++sample->serial, res, &keys); - sample->focus = res; - } - - if (seat_handle && seat_handle->keyboard) { - uint32_t depressed = xkb_state_serialize_mods(keyboard->xkb_state, - XKB_STATE_MODS_DEPRESSED); - uint32_t latched = xkb_state_serialize_mods(keyboard->xkb_state, - XKB_STATE_MODS_LATCHED); - uint32_t locked = xkb_state_serialize_mods(keyboard->xkb_state, - XKB_STATE_MODS_LOCKED); - uint32_t group = xkb_state_serialize_layout(keyboard->xkb_state, - XKB_STATE_LAYOUT_EFFECTIVE); - wl_keyboard_send_modifiers(seat_handle->keyboard, ++sample->serial, depressed, - latched, locked, group); - wl_keyboard_send_key(seat_handle->keyboard, ++sample->serial, 0, keycode, key_state); - } -} - -static void handle_keyboard_bound(struct wl_listener *listener, void *data) { - struct wlr_seat_handle *handle = data; - struct sample_state *state = wl_container_of(listener, state, keyboard_bound); - - wl_keyboard_send_keymap(handle->keyboard, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, - state->keymap_fd, state->keymap_size); - - if (wl_resource_get_version(handle->keyboard) >= 2) { - wl_keyboard_send_repeat_info(handle->keyboard, 25, 600); - } -} - -int main() { - struct sample_state state = { 0 }; - struct compositor_state compositor = { 0, - .data = &state, - .output_frame_cb = handle_output_frame, - .keyboard_key_cb = handle_keyboard_key - }; - compositor_init(&compositor); - - state.renderer = wlr_gles2_renderer_create(compositor.backend); - if (!state.renderer) { - wlr_log(L_ERROR, "Could not start compositor, OOM"); - exit(EXIT_FAILURE); - } - wl_display_init_shm(compositor.display); - wl_compositor_init(compositor.display, &state.compositor, state.renderer); - state.wl_shell = wlr_wl_shell_create(compositor.display); - state.xdg_shell = wlr_xdg_shell_v6_create(compositor.display); - state.data_device_manager = wlr_data_device_manager_create(compositor.display); - - state.wl_seat = wlr_seat_create(compositor.display, "seat0"); - state.keyboard_bound.notify = handle_keyboard_bound; - wl_signal_add(&state.wl_seat->events.keyboard_bound, &state.keyboard_bound); - wlr_seat_set_capabilities(state.wl_seat, WL_SEAT_CAPABILITY_KEYBOARD - | WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_TOUCH); - - struct keyboard_state *kbstate; - wl_list_for_each(kbstate, &compositor.keyboards, link) { - char *keymap = xkb_keymap_get_as_string(kbstate->keymap, - XKB_KEYMAP_FORMAT_TEXT_V1); - state.keymap_size = strlen(keymap); - state.keymap_fd = os_create_anonymous_file(state.keymap_size); - void *ptr = mmap(NULL, state.keymap_size, - PROT_READ | PROT_WRITE, - MAP_SHARED, state.keymap_fd, 0); - strcpy(ptr, keymap); - free(keymap); - break; - } - - wl_display_run(compositor.display); - - close(state.keymap_fd); - wlr_seat_destroy(state.wl_seat); - wlr_data_device_manager_destroy(state.data_device_manager); - wlr_xdg_shell_v6_destroy(state.xdg_shell); - wlr_wl_shell_destroy(state.wl_shell); - wlr_renderer_destroy(state.renderer); - compositor_fini(&compositor); -} diff --git a/examples/compositor/wl_compositor.c b/examples/compositor/wl_compositor.c deleted file mode 100644 index 0bab345d..00000000 --- a/examples/compositor/wl_compositor.c +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "compositor.h" - -static void destroy_surface_listener(struct wl_listener *listener, void *data) { - wl_list_remove(wl_resource_get_link(data)); -} - -static void wl_compositor_create_surface(struct wl_client *client, - struct wl_resource *resource, uint32_t id) { - struct wl_compositor_state *state = wl_resource_get_user_data(resource); - struct wl_resource *surface_resource = wl_resource_create(client, - &wl_surface_interface, wl_resource_get_version(resource), id); - struct wlr_surface *surface = wlr_surface_create(surface_resource, state->renderer); - surface->compositor_data = state; - surface->compositor_listener.notify = &destroy_surface_listener; - wl_resource_add_destroy_listener(surface_resource, &surface->compositor_listener); - - wl_list_insert(&state->surfaces, wl_resource_get_link(surface_resource)); -} - -static void wl_compositor_create_region(struct wl_client *client, - struct wl_resource *resource, uint32_t id) { - wlr_region_create(client, resource, id); -} - -struct wl_compositor_interface wl_compositor_impl = { - .create_surface = wl_compositor_create_surface, - .create_region = wl_compositor_create_region -}; - -static void wl_compositor_destroy(struct wl_resource *resource) { - struct wl_compositor_state *state = wl_resource_get_user_data(resource); - struct wl_resource *_resource = NULL; - wl_resource_for_each(_resource, &state->wl_resources) { - if (_resource == resource) { - struct wl_list *link = wl_resource_get_link(_resource); - wl_list_remove(link); - break; - } - } -} - -static void wl_compositor_bind(struct wl_client *wl_client, void *_state, - uint32_t version, uint32_t id) { - struct wl_compositor_state *state = _state; - assert(wl_client && state); - if (version > 4) { - wlr_log(L_ERROR, "Client requested unsupported wl_compositor version, disconnecting"); - wl_client_destroy(wl_client); - return; - } - struct wl_resource *wl_resource = wl_resource_create( - wl_client, &wl_compositor_interface, version, id); - wl_resource_set_implementation(wl_resource, &wl_compositor_impl, - state, wl_compositor_destroy); - wl_list_insert(&state->wl_resources, wl_resource_get_link(wl_resource)); -} - -void wl_compositor_init(struct wl_display *display, - struct wl_compositor_state *state, struct wlr_renderer *renderer) { - struct wl_global *wl_global = wl_global_create(display, - &wl_compositor_interface, 4, state, wl_compositor_bind); - state->wl_global = wl_global; - state->renderer = renderer; - wl_list_init(&state->wl_resources); - wl_list_init(&state->surfaces); -} diff --git a/examples/meson.build b/examples/meson.build index e2c0189c..d4d96984 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -9,11 +9,6 @@ executable('touch', 'touch.c', dependencies: wlroots, link_with: lib_shared) executable('tablet', 'tablet.c', dependencies: wlroots, link_with: lib_shared) executable('output-layout', 'output-layout.c', dependencies: wlroots, link_with: lib_shared) -compositor_src = [ - 'compositor/main.c', - 'compositor/wl_compositor.c', -] - -executable('compositor', compositor_src, +executable('compositor', 'compositor.c', dependencies: wlroots, link_with: lib_shared) diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h new file mode 100644 index 00000000..47abeeac --- /dev/null +++ b/include/wlr/types/wlr_compositor.h @@ -0,0 +1,21 @@ +#ifndef _EXAMPLE_COMPOSITOR_H +#define _EXAMPLE_COMPOSITOR_H +#include +#include + +struct wlr_compositor { + struct wl_global *wl_global; + struct wl_list wl_resources; + struct wlr_renderer *renderer; + struct wl_list surfaces; + struct wl_listener destroy_surface_listener; +}; + +void wlr_compositor_finish(struct wlr_compositor *wlr_compositor); +void wlr_compositor_init(struct wlr_compositor *wlr_compositor, + struct wl_display *display, struct wlr_renderer *renderer); + +struct wlr_surface; +void wl_compositor_surface_destroyed(struct wlr_compositor *wlr_compositor, + struct wlr_surface *surface); +#endif diff --git a/types/meson.build b/types/meson.build index 82175f6d..83b4647c 100644 --- a/types/meson.build +++ b/types/meson.build @@ -14,6 +14,7 @@ lib_wlr_types = static_library('wlr_types', files( 'wlr_touch.c', 'wlr_xdg_shell_v6.c', 'wlr_wl_shell.c', + 'wlr_compositor.c', ), include_directories: wlr_inc, dependencies: [wayland_server, pixman, wlr_protos]) diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c new file mode 100644 index 00000000..e3b2199e --- /dev/null +++ b/types/wlr_compositor.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include + +static void destroy_surface_listener(struct wl_listener *listener, void *data) { + wl_list_remove(wl_resource_get_link(data)); +} + +static void wl_compositor_create_surface(struct wl_client *client, + struct wl_resource *resource, uint32_t id) { + struct wlr_compositor *compositor = wl_resource_get_user_data(resource); + struct wl_resource *surface_resource = wl_resource_create(client, + &wl_surface_interface, wl_resource_get_version(resource), id); + struct wlr_surface *surface = wlr_surface_create(surface_resource, + compositor->renderer); + surface->compositor_data = compositor; + surface->compositor_listener.notify = &destroy_surface_listener; + wl_resource_add_destroy_listener(surface_resource, &surface->compositor_listener); + + wl_list_insert(&compositor->surfaces, wl_resource_get_link(surface_resource)); +} + +static void wl_compositor_create_region(struct wl_client *client, + struct wl_resource *resource, uint32_t id) { + wlr_region_create(client, resource, id); +} + +struct wl_compositor_interface wl_compositor_impl = { + .create_surface = wl_compositor_create_surface, + .create_region = wl_compositor_create_region +}; + +static void wl_compositor_destroy(struct wl_resource *resource) { + struct wlr_compositor *compositor = wl_resource_get_user_data(resource); + struct wl_resource *_resource = NULL; + wl_resource_for_each(_resource, &compositor->wl_resources) { + if (_resource == resource) { + struct wl_list *link = wl_resource_get_link(_resource); + wl_list_remove(link); + break; + } + } +} + +static void wl_compositor_bind(struct wl_client *wl_client, void *_compositor, + uint32_t version, uint32_t id) { + struct wlr_compositor *compositor = _compositor; + assert(wl_client && compositor); + if (version > 4) { + wlr_log(L_ERROR, "Client requested unsupported wl_compositor version, disconnecting"); + wl_client_destroy(wl_client); + return; + } + struct wl_resource *wl_resource = wl_resource_create( + wl_client, &wl_compositor_interface, version, id); + wl_resource_set_implementation(wl_resource, &wl_compositor_impl, + compositor, wl_compositor_destroy); + wl_list_insert(&compositor->wl_resources, wl_resource_get_link(wl_resource)); +} + +void wlr_compositor_finish(struct wlr_compositor *compositor) { + wl_global_destroy(compositor->wl_global); +} + +void wlr_compositor_init(struct wlr_compositor *compositor, + struct wl_display *display, struct wlr_renderer *renderer) { + struct wl_global *wl_global = wl_global_create(display, + &wl_compositor_interface, 4, compositor, wl_compositor_bind); + compositor->wl_global = wl_global; + compositor->renderer = renderer; + wl_list_init(&compositor->wl_resources); + wl_list_init(&compositor->surfaces); +} -- cgit v1.2.3