diff --git a/glonkers.c b/glonkers.c index 632deea..2acd567 100644 --- a/glonkers.c +++ b/glonkers.c @@ -14,31 +14,15 @@ int main(int argc, char *argv[]) { char *shader_path = NULL; int output_type = OUTPUT_WINDOW; - bool currently_reading_output = false; - char **output_list = NULL; - int output_count; // syntax: --window for a normal window or --layer for a wallpaper for (int i = 1; i < argc; i++) { if (strcmp("--window", argv[i]) == 0) { output_type = OUTPUT_WINDOW; - currently_reading_output = false; } else if (strcmp("--layer", argv[i]) == 0) { output_type = OUTPUT_LAYER; - currently_reading_output = false; } - else if (strcmp("--output", argv[i]) == 0) { - output_count = 0; - output_list = &argv[i + 1]; - currently_reading_output = true; - } - else if (strcmp("--", argv[i]) == 0) { - currently_reading_output = false; - } - else if (currently_reading_output) { - output_count++; - } - else if (!currently_reading_output) { + else { // path to fragment shader if (shader_path != NULL) { fprintf(stderr, "tried supplying '%s' as a shader file while one has already been selected\n", argv[i]); @@ -52,10 +36,9 @@ int main(int argc, char *argv[]) { return 1; } - struct client_state *state = wayland_init(output_type, output_list, output_count); + struct client_state *state = wayland_init(output_type); - bool renderer_initialized = false; - Renderer renderer; + Renderer renderer = new_renderer(); bool running = true; while (running) { @@ -64,10 +47,6 @@ int main(int argc, char *argv[]) { int width = event.data.draw.width; int height = event.data.draw.height; double time = event.data.draw.time / 1000.0; - if (!renderer_initialized) { - renderer = new_renderer(); - renderer_initialized = true; - } render(&renderer, width, height, time, shader_path, 0); swap_buffers(state, event.data.draw.surface); } diff --git a/wayland.c b/wayland.c index bca0a74..cf40a7c 100644 --- a/wayland.c +++ b/wayland.c @@ -36,9 +36,6 @@ struct surface_list { struct client_state { bool running; int output_type; - /// Names of enabled outputs, or NULL for every output. - char **output_list; - int output_list_len; /* Globals */ struct wl_display *wl_display; struct wl_registry *wl_registry; @@ -66,6 +63,302 @@ struct client_state { /// Starting values. int width = 700, height = 700; +static void wl_buffer_release(void *data, struct wl_buffer *wl_buffer) { + /* Sent by the compositor when it's no longer using this buffer */ + wl_buffer_destroy(wl_buffer); +} + +static const struct wl_buffer_listener wl_buffer_listener = { + .release = wl_buffer_release, +}; + +static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) { + struct client_state *state = data; + xdg_surface_ack_configure(xdg_surface, serial); +} + +static const struct xdg_surface_listener xdg_surface_listener = { + .configure = xdg_surface_configure, +}; + +static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) { + xdg_wm_base_pong(xdg_wm_base, serial); +} + +static const struct xdg_wm_base_listener xdg_wm_base_listener = { + .ping = xdg_wm_base_ping, +}; + +static void xdg_toplevel_configure ( + void *data, + struct xdg_toplevel *xdg_toplevel, + int32_t width, + int32_t height, + struct wl_array *states + ) { + + struct client_state *state = data; + // resize egl window + struct surface_list *next = state->surface_list; + + while (next->data.xdg_toplevel != xdg_toplevel) { next = next->next; } + next->data.width = width; + next->data.height = height; + wl_egl_window_resize(next->data.egl_window, width, height, 0, 0); + // draw new frame! + next->data.dirty = true; +} + +static void xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) { + struct client_state *state = data; + state->running = false; +} + +void xdg_toplevel_configure_bounds(void *data, struct xdg_toplevel *xdg_toplevel, int32_t w, int32_t h) { +} + +void xdg_toplevel_wm_capabilities(void *data, struct xdg_toplevel *xdg_toplevel, struct wl_array *capabilities) { +} + +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + .configure = xdg_toplevel_configure, + .close = xdg_toplevel_close, + .configure_bounds = xdg_toplevel_configure_bounds, + .wm_capabilities = xdg_toplevel_wm_capabilities, +}; + +static void zwlr_layer_surface_v1_configure(void *data, struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1, uint32_t serial, uint32_t width, uint32_t height) { + struct client_state *state = data; + struct surface_list *next = state->surface_list; + while (next->data.zwlr_layer_surface_v1 != zwlr_layer_surface_v1) { next = next->next; } + next->data.width = width; + next->data.height = height; + wl_egl_window_resize(next->data.egl_window, width, height, 0, 0); + zwlr_layer_surface_v1_ack_configure(zwlr_layer_surface_v1, serial); + // draw new frame! + next->data.dirty = true; +} + +static void zwlr_layer_surface_v1_closed(void *data, struct zwlr_layer_surface_v1 * zwlr_layer_surface_v1) { + struct client_state *state = data; + state->running = 0; +} + +static const struct zwlr_layer_surface_v1_listener zwlr_layer_surface_v1_listener = { + .configure = zwlr_layer_surface_v1_configure, + .closed = zwlr_layer_surface_v1_closed, +}; + +static const struct wl_callback_listener wl_surface_frame_listener; + +static void +wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) { + struct surface *surface = data; + surface->time = time; + + /* Destroy this callback */ + wl_callback_destroy(cb); + + surface->dirty = true; +} + +static const struct wl_callback_listener wl_surface_frame_listener = { + .done = wl_surface_frame_done, +}; + +void pointer_enter_handler ( + void *data, + struct wl_pointer *pointer, + uint32_t serial, + struct wl_surface *surface, + wl_fixed_t x, wl_fixed_t y ) +{ + struct client_state *state = data; + wl_pointer_set_cursor(pointer, serial, state->cursor_surface, + state->wl_cursor_image->hotspot_x, state->wl_cursor_image->hotspot_y); +} + +void pointer_leave_handler ( + void *data, + struct wl_pointer *pointer, + uint32_t serial, + struct wl_surface *surface +) { } + +void pointer_motion_handler ( + void *data, + struct wl_pointer *pointer, + uint32_t time, + wl_fixed_t x, + wl_fixed_t y +) { } + +void pointer_button_handler +( + void *data, + struct wl_pointer *pointer, + uint32_t serial, + uint32_t time, + uint32_t button, + uint32_t state +) { } + +void pointer_axis_handler +( + void *data, + struct wl_pointer *pointer, + uint32_t time, + uint32_t axis, + wl_fixed_t value +) { } + +const struct wl_pointer_listener wl_pointer_listener = { + .enter = pointer_enter_handler, + .leave = pointer_leave_handler, + .motion = pointer_motion_handler, + .button = pointer_button_handler, + .axis = pointer_axis_handler +}; + +static void registry_handle_global( + void *data, + struct wl_registry *registry, + uint32_t name, + const char *interface, + uint32_t version + ) { + printf("interface: '%s', version: %d, name: %d\n", + interface, version, name); + + struct client_state *state = data; + + if (strcmp(interface, wl_compositor_interface.name) == 0) { + state->wl_compositor = wl_registry_bind( + registry, name, &wl_compositor_interface, 4); + // Set up wl_surface + //state->wl_surface = wl_compositor_create_surface(state->wl_compositor); + } + if (strcmp(interface, wl_shm_interface.name) == 0) { + state->wl_shm = wl_registry_bind(registry, name, + &wl_shm_interface, 1); + } + if (strcmp(interface, wl_seat_interface.name) == 0) { + state->wl_seat = wl_registry_bind(registry, name, + &wl_seat_interface, 1); + state->wl_pointer = wl_seat_get_pointer(state->wl_seat); + wl_pointer_add_listener(state->wl_pointer, &wl_pointer_listener, state); + + struct wl_cursor_theme *cursor_theme = + wl_cursor_theme_load(NULL, 24, state->wl_shm); + struct wl_cursor *cursor = + wl_cursor_theme_get_cursor(cursor_theme, "left_ptr"); + state->wl_cursor_image = cursor->images[0]; + struct wl_buffer *cursor_buffer = + wl_cursor_image_get_buffer(state->wl_cursor_image); + + state->cursor_surface = wl_compositor_create_surface(state->wl_compositor); + wl_surface_attach(state->cursor_surface, cursor_buffer, 0, 0); + wl_surface_commit(state->cursor_surface); + } + if ((strcmp(interface, xdg_wm_base_interface.name) == 0) && (state->output_type == OUTPUT_WINDOW)) { + state->xdg_wm_base = wl_registry_bind( + registry, name, &xdg_wm_base_interface, 1); + xdg_wm_base_add_listener(state->xdg_wm_base, + &xdg_wm_base_listener, state); + + // create window + struct wl_surface *wl_surface = wl_compositor_create_surface(state->wl_compositor); + struct xdg_surface *xdg_surface = xdg_wm_base_get_xdg_surface( + state->xdg_wm_base, wl_surface); + xdg_surface_add_listener(xdg_surface, &xdg_surface_listener, state); + struct xdg_toplevel *xdg_toplevel = xdg_surface_get_toplevel(xdg_surface); + xdg_toplevel_set_title(xdg_toplevel, "GLONKERS! 🕴️"); + xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, state); + + // save all the pointers + struct surface surface = { + .wl_surface = wl_surface, + .xdg_surface = xdg_surface, + .xdg_toplevel = xdg_toplevel, + .dirty = false, + .width = DEFAULT_WIDTH, + .height = DEFAULT_HEIGHT, + }; + state->surface_list = malloc(sizeof(struct surface_list)); + state->surface_list->data = surface; + state->surface_list->next = NULL; + + // frame callback + struct wl_callback *cb = wl_surface_frame(wl_surface); + wl_callback_add_listener(cb, &wl_surface_frame_listener, &state->surface_list->data); + } + if ((strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) && (state->output_type == OUTPUT_LAYER)) { + state->zwlr_layer_shell_v1 = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 4); + } + if (strcmp(interface, wl_output_interface.name) == 0 && state->output_type == OUTPUT_LAYER) { + struct wl_output *wl_output = wl_registry_bind( + registry, name, &wl_output_interface, 4); + + struct wl_surface *wl_surface = wl_compositor_create_surface(state->wl_compositor); + + // wlr_layer_shell + int layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; + struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1 = + zwlr_layer_shell_v1_get_layer_surface( + state->zwlr_layer_shell_v1, + wl_surface, + wl_output, + layer, + "wallpaper" + ); + zwlr_layer_surface_v1_set_anchor(zwlr_layer_surface_v1, + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT); + zwlr_layer_surface_v1_set_size(zwlr_layer_surface_v1, 0, 0); + zwlr_layer_surface_v1_add_listener(zwlr_layer_surface_v1, &zwlr_layer_surface_v1_listener, state); + + struct surface surface = { + .wl_surface = wl_surface, + .zwlr_layer_surface_v1 = zwlr_layer_surface_v1, + .dirty = false, + .width = DEFAULT_WIDTH, + .height = DEFAULT_HEIGHT, + }; + // persistent pointer for the callback + struct surface *surface_location; + if (state->surface_list == NULL) { + state->surface_list = malloc(sizeof(struct surface_list)); + state->surface_list->data = surface; + state->surface_list->next = NULL; + surface_location = &state->surface_list->data; + } else { + struct surface_list *next = state->surface_list; + while (next->next != NULL) { next = next->next; } + next->next = malloc(sizeof(struct surface_list)); + next->next->data = surface; + next->next->next = NULL; + surface_location = &next->next->data; + } + + // frame callback + struct wl_callback *cb = wl_surface_frame(wl_surface); + wl_callback_add_listener(cb, &wl_surface_frame_listener, surface_location); + } +} + +static void registry_handle_global_remove( + void *data, + struct wl_registry *registry, + uint32_t name + ) { + // This space deliberately left blank +} + +static const struct wl_registry_listener wl_registry_listener = { + .global = registry_handle_global, + .global_remove = registry_handle_global_remove, +}; + static void egl_init(struct client_state *state) { EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, @@ -139,410 +432,57 @@ static void egl_init(struct client_state *state) { printf("Failed to create EGL context\n"); exit(1); } -} -void egl_init_surface(struct client_state *state, struct surface *surface) { - printf("Creating egl window of size: %dx%d\n", surface->width, surface->height); - surface->egl_window = wl_egl_window_create(surface->wl_surface, - surface->width, surface->height); - if (surface->egl_window == EGL_NO_SURFACE) { - fprintf(stderr, "Can't create egl window\n"); - exit(1); - } else { - fprintf(stderr, "Created egl window\n"); - } - - surface->egl_surface = - eglCreateWindowSurface(state->egl_display, - state->egl_config, - (unsigned long) surface->egl_window, NULL); - - if (eglMakeCurrent(state->egl_display, surface->egl_surface, - surface->egl_surface, state->egl_context)) { - fprintf(stderr, "Made current\n"); - } else { - fprintf(stderr, "Made current failed\n"); - } -} - -static const struct wl_callback_listener wl_surface_frame_listener; - -static void -wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) { - struct surface *surface = data; - surface->time = time; - - /* Destroy this callback */ - wl_callback_destroy(cb); - - surface->dirty = true; -} - -static const struct wl_callback_listener wl_surface_frame_listener = { - .done = wl_surface_frame_done, -}; - -static void zwlr_layer_surface_v1_configure(void *data, struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1, uint32_t serial, uint32_t width, uint32_t height) { - struct client_state *state = data; + // EGL window struct surface_list *next = state->surface_list; - while (next->data.zwlr_layer_surface_v1 != zwlr_layer_surface_v1) { next = next->next; } - next->data.width = width; - next->data.height = height; - wl_egl_window_resize(next->data.egl_window, width, height, 0, 0); - zwlr_layer_surface_v1_ack_configure(zwlr_layer_surface_v1, serial); - // draw new frame! - next->data.dirty = true; -} - -static void zwlr_layer_surface_v1_closed(void *data, struct zwlr_layer_surface_v1 * zwlr_layer_surface_v1) { - struct client_state *state = data; - state->running = 0; -} - -static const struct zwlr_layer_surface_v1_listener zwlr_layer_surface_v1_listener = { - .configure = zwlr_layer_surface_v1_configure, - .closed = zwlr_layer_surface_v1_closed, -}; - -void layer_new(struct client_state *state, struct wl_output *wl_output) { - struct wl_surface *wl_surface = wl_compositor_create_surface(state->wl_compositor); - - // wlr_layer_shell - int layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; - struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1 = - zwlr_layer_shell_v1_get_layer_surface( - state->zwlr_layer_shell_v1, - wl_surface, - wl_output, - layer, - "wallpaper" - ); - zwlr_layer_surface_v1_set_anchor(zwlr_layer_surface_v1, - ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP - | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT); - zwlr_layer_surface_v1_set_size(zwlr_layer_surface_v1, 0, 0); - zwlr_layer_surface_v1_add_listener(zwlr_layer_surface_v1, &zwlr_layer_surface_v1_listener, state); - - struct surface surface = { - .wl_surface = wl_surface, - .zwlr_layer_surface_v1 = zwlr_layer_surface_v1, - .dirty = false, - .width = DEFAULT_WIDTH, - .height = DEFAULT_HEIGHT, - }; - // persistent pointer for the callback - struct surface *surface_location; - if (state->surface_list == NULL) { - state->surface_list = malloc(sizeof(struct surface_list)); - state->surface_list->data = surface; - state->surface_list->next = NULL; - surface_location = &state->surface_list->data; - } else { - struct surface_list *next = state->surface_list; - while (next->next != NULL) { next = next->next; } - next->next = malloc(sizeof(struct surface_list)); - next->next->data = surface; - next->next->next = NULL; - surface_location = &next->next->data; - } - - // frame callback - struct wl_callback *cb = wl_surface_frame(wl_surface); - wl_callback_add_listener(cb, &wl_surface_frame_listener, surface_location); - egl_init_surface(state, surface_location); - wl_surface_commit(wl_surface); -} - - -static void wl_output_name(void *data, struct wl_output *wl_output, const char *name) { - struct client_state *state = data; - printf("output name: %s\n", name); - if (state->output_list != NULL) { - for (int i = 0; i < state->output_list_len; i++) { - if (strcmp(state->output_list[i], name) == 0) { - layer_new(state, wl_output); - } + while (next != NULL) { + printf("Creating egl window of size: %dx%d\n", next->data.width, next->data.height); + next->data.egl_window = wl_egl_window_create(next->data.wl_surface, + next->data.width, next->data.height); + if (next->data.egl_window == EGL_NO_SURFACE) { + fprintf(stderr, "Can't create egl window\n"); + exit(1); + } else { + fprintf(stderr, "Created egl window\n"); } - } else { - layer_new(state, wl_output); + + next->data.egl_surface = + eglCreateWindowSurface(state->egl_display, + state->egl_config, + (unsigned long) next->data.egl_window, NULL); + + if (eglMakeCurrent(state->egl_display, next->data.egl_surface, + next->data.egl_surface, state->egl_context)) { + fprintf(stderr, "Made current\n"); + } else { + fprintf(stderr, "Made current failed\n"); + } + + next = next->next; } } -static void wl_output_description(void *data, struct wl_output *wl_output, const char *description) { -} -static void wl_output_done(void *data, struct wl_output *wl_output) { -} -static void wl_output_geometry( - void *data, struct wl_output *wl_output, - int x, - int y, - int physical_width, - int physical_height, - int subpixel, - const char *make, - const char *model, - int transform - ) { -} -static void wl_output_mode(void *data, struct wl_output *wl_output, unsigned int mode, int width, int height, int refresh) { -} -static void wl_output_scale(void *data, struct wl_output *wl_output, int factor) { -} - -static const struct wl_output_listener wl_output_listener = { - .description = wl_output_description, - .done = wl_output_done, - .geometry = wl_output_geometry, - .mode = wl_output_mode, - .name = wl_output_name, - .scale = wl_output_scale, -}; - -static void wl_buffer_release(void *data, struct wl_buffer *wl_buffer) { - /* Sent by the compositor when it's no longer using this buffer */ - wl_buffer_destroy(wl_buffer); -} - -static const struct wl_buffer_listener wl_buffer_listener = { - .release = wl_buffer_release, -}; - -static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) { - struct client_state *state = data; - xdg_surface_ack_configure(xdg_surface, serial); -} - -static const struct xdg_surface_listener xdg_surface_listener = { - .configure = xdg_surface_configure, -}; - -static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) { - xdg_wm_base_pong(xdg_wm_base, serial); -} - -static const struct xdg_wm_base_listener xdg_wm_base_listener = { - .ping = xdg_wm_base_ping, -}; - -static void xdg_toplevel_configure ( - void *data, - struct xdg_toplevel *xdg_toplevel, - int32_t width, - int32_t height, - struct wl_array *states - ) { - - struct client_state *state = data; - // resize egl window - struct surface_list *next = state->surface_list; - - while (next->data.xdg_toplevel != xdg_toplevel) { next = next->next; } - next->data.width = width; - next->data.height = height; - wl_egl_window_resize(next->data.egl_window, width, height, 0, 0); - // draw new frame! - next->data.dirty = true; -} - -static void xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) { - struct client_state *state = data; - state->running = false; -} - -void xdg_toplevel_configure_bounds(void *data, struct xdg_toplevel *xdg_toplevel, int32_t w, int32_t h) { -} - -void xdg_toplevel_wm_capabilities(void *data, struct xdg_toplevel *xdg_toplevel, struct wl_array *capabilities) { -} - -static const struct xdg_toplevel_listener xdg_toplevel_listener = { - .configure = xdg_toplevel_configure, - .close = xdg_toplevel_close, - .configure_bounds = xdg_toplevel_configure_bounds, - .wm_capabilities = xdg_toplevel_wm_capabilities, -}; - -void pointer_enter_handler ( - void *data, - struct wl_pointer *pointer, - uint32_t serial, - struct wl_surface *surface, - wl_fixed_t x, wl_fixed_t y ) -{ - struct client_state *state = data; - wl_pointer_set_cursor(pointer, serial, state->cursor_surface, - state->wl_cursor_image->hotspot_x, state->wl_cursor_image->hotspot_y); -} - -void pointer_leave_handler ( - void *data, - struct wl_pointer *pointer, - uint32_t serial, - struct wl_surface *surface -) { } - -void pointer_motion_handler ( - void *data, - struct wl_pointer *pointer, - uint32_t time, - wl_fixed_t x, - wl_fixed_t y -) { } - -void pointer_button_handler -( - void *data, - struct wl_pointer *pointer, - uint32_t serial, - uint32_t time, - uint32_t button, - uint32_t state -) { } - -void pointer_axis_handler -( - void *data, - struct wl_pointer *pointer, - uint32_t time, - uint32_t axis, - wl_fixed_t value -) { } - -const struct wl_pointer_listener wl_pointer_listener = { - .enter = pointer_enter_handler, - .leave = pointer_leave_handler, - .motion = pointer_motion_handler, - .button = pointer_button_handler, - .axis = pointer_axis_handler -}; - -/// Creates a toplevel surface, and adds it as the only surface in the surface -/// list (TODO this is bad, make it generic - add it to the list instead). -void xdg_tolevel_new(struct client_state *state) { - // create window - struct wl_surface *wl_surface = wl_compositor_create_surface(state->wl_compositor); - struct xdg_surface *xdg_surface = xdg_wm_base_get_xdg_surface( - state->xdg_wm_base, wl_surface); - xdg_surface_add_listener(xdg_surface, &xdg_surface_listener, state); - struct xdg_toplevel *xdg_toplevel = xdg_surface_get_toplevel(xdg_surface); - xdg_toplevel_set_title(xdg_toplevel, "GLONKERS! 🕴️"); - xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, state); - - // save all the pointers - struct surface surface = { - .wl_surface = wl_surface, - .xdg_surface = xdg_surface, - .xdg_toplevel = xdg_toplevel, - .dirty = false, - .width = DEFAULT_WIDTH, - .height = DEFAULT_HEIGHT, - }; - state->surface_list = malloc(sizeof(struct surface_list)); - state->surface_list->data = surface; - state->surface_list->next = NULL; - - // frame callback - struct wl_callback *cb = wl_surface_frame(wl_surface); - wl_callback_add_listener(cb, &wl_surface_frame_listener, &state->surface_list->data); - egl_init_surface(state, &state->surface_list->data); - wl_surface_commit(wl_surface); -} - -static void registry_handle_global( - void *data, - struct wl_registry *registry, - uint32_t name, - const char *interface, - uint32_t version - ) { - printf("interface: '%s', version: %d, name: %d\n", - interface, version, name); - - struct client_state *state = data; - - if (strcmp(interface, wl_compositor_interface.name) == 0) { - state->wl_compositor = wl_registry_bind( - registry, name, &wl_compositor_interface, 4); - // Set up wl_surface - //state->wl_surface = wl_compositor_create_surface(state->wl_compositor); - } - if (strcmp(interface, wl_shm_interface.name) == 0) { - state->wl_shm = wl_registry_bind(registry, name, - &wl_shm_interface, 1); - } - if (strcmp(interface, wl_seat_interface.name) == 0) { - state->wl_seat = wl_registry_bind(registry, name, - &wl_seat_interface, 1); - state->wl_pointer = wl_seat_get_pointer(state->wl_seat); - wl_pointer_add_listener(state->wl_pointer, &wl_pointer_listener, state); - - struct wl_cursor_theme *cursor_theme = - wl_cursor_theme_load(NULL, 24, state->wl_shm); - struct wl_cursor *cursor = - wl_cursor_theme_get_cursor(cursor_theme, "left_ptr"); - state->wl_cursor_image = cursor->images[0]; - struct wl_buffer *cursor_buffer = - wl_cursor_image_get_buffer(state->wl_cursor_image); - - state->cursor_surface = wl_compositor_create_surface(state->wl_compositor); - wl_surface_attach(state->cursor_surface, cursor_buffer, 0, 0); - wl_surface_commit(state->cursor_surface); - } - if ((strcmp(interface, xdg_wm_base_interface.name) == 0) && (state->output_type == OUTPUT_WINDOW)) { - state->xdg_wm_base = wl_registry_bind( - registry, name, &xdg_wm_base_interface, 1); - xdg_wm_base_add_listener(state->xdg_wm_base, - &xdg_wm_base_listener, state); - } - if ((strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) && (state->output_type == OUTPUT_LAYER)) { - state->zwlr_layer_shell_v1 = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 4); - } - if (strcmp(interface, wl_output_interface.name) == 0 && state->output_type == OUTPUT_LAYER) { - struct wl_output *wl_output = wl_registry_bind( - registry, name, &wl_output_interface, 4); - wl_output_add_listener(wl_output, &wl_output_listener, state); - } -} - -static void registry_handle_global_remove( - void *data, - struct wl_registry *registry, - uint32_t name - ) { - // This space deliberately left blank -} - -static const struct wl_registry_listener wl_registry_listener = { - .global = registry_handle_global, - .global_remove = registry_handle_global_remove, -}; - /// Initializes wayland and creates an opengl context -struct client_state* wayland_init(int output_type, char *output_list[], int output_list_len) { - if (output_list != NULL) { - for (int i = 0; i < output_list_len; i++) { - printf("output name selected: %s\n", output_list[i]); - } - } +struct client_state* wayland_init(int output_type) { struct client_state *state = malloc(sizeof(struct client_state)); - state->output_list = output_list; - state->output_list_len = output_list_len; state->running = 1; state->output_type = output_type; state->wl_display = wl_display_connect(NULL); state->wl_registry = wl_display_get_registry(state->wl_display); state->surface_list = NULL; state->surface_list_next = NULL; - egl_init(state); wl_registry_add_listener(state->wl_registry, &wl_registry_listener, state); wl_display_roundtrip(state->wl_display); wl_seat_get_pointer(state->wl_seat); - if (state->output_type == OUTPUT_WINDOW) { - xdg_tolevel_new(state); + struct surface_list *next = state->surface_list; + while (next != NULL) { + wl_surface_commit(next->data.wl_surface); + next = next->next; } + egl_init(state); return state; } @@ -556,41 +496,39 @@ struct event wait_for_event(struct client_state *state) { struct event event = { .type = EVENT_EXIT }; return event; } - if (state->surface_list != NULL) { - while (true) { - if (next == NULL) { - next = state->surface_list; + while (true) { + if (next == NULL) { + next = state->surface_list; + } + + // do here + if (next->data.dirty) { + next->data.dirty = false; + state->surface_list_next = next->next; + + if (eglMakeCurrent(state->egl_display, next->data.egl_surface, + next->data.egl_surface, state->egl_context)) { + } else { + fprintf(stderr, "Made current failed\n"); } - - // do here - if (next->data.dirty) { - next->data.dirty = false; - state->surface_list_next = next->next; - - if (eglMakeCurrent(state->egl_display, next->data.egl_surface, - next->data.egl_surface, state->egl_context)) { - } else { - fprintf(stderr, "Made current failed\n"); - } - struct event event = { - .type = EVENT_DRAW, - .data = { - .draw = { - .width = next->data.width, - .height = next->data.height, - .time = next->data.time, - .surface = &next->data, - } + struct event event = { + .type = EVENT_DRAW, + .data = { + .draw = { + .width = next->data.width, + .height = next->data.height, + .time = next->data.time, + .surface = &next->data, } - }; - return event; - } - - next = next->next; - if (next == original) { - state->surface_list_next = next; - break; - } + } + }; + return event; + } + + next = next->next; + if (next == original) { + state->surface_list_next = next; + break; } } wl_display_dispatch(state->wl_display); diff --git a/wayland.h b/wayland.h index 21e7e57..8639a30 100644 --- a/wayland.h +++ b/wayland.h @@ -31,8 +31,7 @@ struct event { } data; }; -/// output_list: if not NULL, only select outputs should be drawn to -struct client_state* wayland_init(int output_type, char *output_list[], int output_list_len); +struct client_state* wayland_init(int output_type); void commit(struct client_state *state); struct event wait_for_event(struct client_state *state); void swap_buffers(struct client_state *state, struct surface *surface);