diff --git a/glonkers.c b/glonkers.c index f45ebba..ada49cf 100644 --- a/glonkers.c +++ b/glonkers.c @@ -60,9 +60,9 @@ int main(int argc, char *argv[]) { while (running) { double time = time_since_start(); - struct event event; - wait_for_event(&state, &event); + struct event event = wait_for_event(&state); if (event.type == EVENT_DRAW) { + printf("drawing!!!!\n"); int width = event.data.draw.width; int height = event.data.draw.height; render(&renderer, width, height, time, shader_path, 0); diff --git a/wayland.c b/wayland.c index 0bb46aa..0e75104 100644 --- a/wayland.c +++ b/wayland.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "wayland.h" /// Starting values. @@ -47,6 +48,7 @@ static void xdg_toplevel_configure ( while (next->data.xdg_toplevel != xdg_toplevel) { next = next->next; } next->data.width = width; next->data.height = height; + printf("🧟🧟🧟\n"); wl_egl_window_resize(next->data.egl_window, width, height, 0, 0); } @@ -76,6 +78,7 @@ static void zwlr_layer_surface_v1_configure(void *data, struct zwlr_layer_surfac 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); + printf("🐍🐍🐍🐍\n"); } static void zwlr_layer_surface_v1_closed(void *data, struct zwlr_layer_surface_v1 * zwlr_layer_surface_v1) { @@ -88,6 +91,43 @@ static const struct zwlr_layer_surface_v1_listener zwlr_layer_surface_v1_listene .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) { + printf("FRAME CALLBACK 🐷🐷\n"); + + /* Destroy this callback */ + wl_callback_destroy(cb); + + struct surface *surface = data; + surface->dirty = true; + //struct client_state *state = surface->state; + + /* Request another frame */ + // TODO make sure this is done after the frame has been handled. + //cb = wl_surface_frame(surface->wl_surface); + //wl_callback_add_listener(cb, &wl_surface_frame_listener, surface); + + ///* Update scroll amount at 24 pixels per second */ + //if (state->last_frame != 0) { + // int elapsed = time - state->last_frame; + // state->offset += elapsed / 1000.0 * 24; + //} + + ///* Submit a frame for this event */ + //struct wl_buffer *buffer = draw_frame(state); + //wl_surface_attach(state->wl_surface, buffer, 0, 0); + //wl_surface_damage_buffer(state->wl_surface, 0, 0, INT32_MAX, INT32_MAX); + //wl_surface_commit(state->wl_surface); + + //state->last_frame = time; +} + +static const struct wl_callback_listener wl_surface_frame_listener = { + .done = wl_surface_frame_done, +}; + static void registry_handle_global( void *data, struct wl_registry *registry, @@ -126,10 +166,17 @@ static void registry_handle_global( .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); @@ -159,18 +206,29 @@ static void registry_handle_global( 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); } } @@ -253,6 +311,7 @@ static void egl_init(struct client_state *state) { // EGL window struct surface_list *next = state->surface_list; 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) { @@ -295,9 +354,6 @@ void wayland_init(struct client_state *state, int output_type) { } egl_init(state); - - // TODO fix frame callbacks for all surfaces - } /// Swaps front/backbuffers and dispatches pending wayland commands. @@ -320,7 +376,29 @@ void commit(struct client_state *state) { } } -void wait_for_event(struct client_state *state, struct event event) { - wl_display_dispatch(state->wl_display); +struct event wait_for_event(struct client_state *state) { + for (;;) { + // before dispatch: check that there is nothing elese to do + // check for dirty surface + struct surface_list *next = state->surface_list; + printf("listtttt\n"); + while (next != NULL) { + if (next->data.dirty) { + printf("dirty\n"); + struct event event = { + .type = EVENT_DRAW, + .data = { + .draw = { + .width = next->data.width, + .height = next->data.height, + } + } + }; + return event; + } + next = next->next; + } + wl_display_dispatch(state->wl_display); + } } diff --git a/wayland.h b/wayland.h index d423984..da4cbdd 100644 --- a/wayland.h +++ b/wayland.h @@ -8,9 +8,15 @@ /// A desktop layer (wallpaper) #define OUTPUT_LAYER 1 +#define DEFAULT_WIDTH 400 +#define DEFAULT_HEIGHT 400 + struct surface { int width, height; + /// Wating to be redrawn. + bool dirty; + struct wl_surface *wl_surface; struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; @@ -43,7 +49,8 @@ struct client_state { EGLContext egl_context; }; -#define EVENT_DRAW 0 +#define EVENT_NONE 0 +#define EVENT_DRAW 1 struct event { int type; @@ -58,5 +65,5 @@ struct event { void wayland_init(struct client_state *state, int output_type); void commit(struct client_state *state); /// Provide pointer to be filled. -void wait_for_event(struct client_state *state, struct event event); +struct event wait_for_event(struct client_state *state);