#include #include #include #include #include #include #include #include #include #include #include"wlr-layer-shell-unstable-v1-protocol.h" #include"xdg-output-unstable-v1-protocol.h" #include"xdg-shell-protocol.h" #include"wlclock.h" #include"output.h" #include"misc.h" #include"surface.h" #include"buffer.h" #include"render.h" static void layer_surface_handle_configure (void *data, struct zwlr_layer_surface_v1 *layer_surface, uint32_t serial, uint32_t w, uint32_t h) { struct Wlclock_surface *surface = (struct Wlclock_surface *)data; clocklog(1, "[surface] Layer surface configure request: output=%d w=%d h=%d serial=%d\n", surface->output->global_name, w, h, serial); zwlr_layer_surface_v1_ack_configure(layer_surface, serial); bool dimensions_changed = false; if ( w != (uint32_t)surface->dimensions.w ) { surface->dimensions.w = w == 0 ? context.dimensions.w : (int32_t)w; dimensions_changed = true; } if ( h != (uint32_t)surface->dimensions.h ) { surface->dimensions.h = h == 0 ? context.dimensions.h : (int32_t)h; dimensions_changed = true; } if (dimensions_changed) { /* Try to fit into the space the compositor wants us to occupy * while also keeping the center square and not changing the * border sizes. */ int32_t size_a = (int32_t)w - context.border_left - context.border_right; int32_t size_b = (int32_t)h - context.border_top - context.border_bottom; surface->dimensions.center_size = size_a < size_b ? size_a : size_b; if ( surface->dimensions.center_size < 10 ) surface->dimensions.center_size = 10; zwlr_layer_surface_v1_set_size(surface->layer_surface, surface->dimensions.w, surface->dimensions.h); wl_subsurface_set_position(surface->subsurface, surface->dimensions.center_x, surface->dimensions.center_y); } if ( dimensions_changed || !surface->configured ) { surface->configured = true; render_background_frame(surface); render_hands_frame(surface); wl_surface_commit(surface->hands_surface); wl_surface_commit(surface->background_surface); } } static void layer_surface_handle_closed (void *data, struct zwlr_layer_surface_v1 *layer_surface) { struct Wlclock_surface *surface = (struct Wlclock_surface *)data; clocklog(1, "[surface] Layer surface has been closed: global_name=%d\n", surface->output->global_name); destroy_surface(surface); } const struct zwlr_layer_surface_v1_listener layer_surface_listener = { .configure = layer_surface_handle_configure, .closed = layer_surface_handle_closed }; static int32_t get_exclusive_zone (struct Wlclock_surface *surface) { if ( context.exclusive_zone == 1 ) switch (context.anchor) { case ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM: case ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP: return surface->dimensions.h; case ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT: case ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT: return surface->dimensions.w; default: return 0; } else return context.exclusive_zone; } bool create_surface (struct Wlclock_output *output) { clocklog(1, "[surface] Creating surface: global_name=%d\n", output->global_name); struct Wlclock_surface *surface = calloc(1, sizeof(struct Wlclock_surface)); if ( surface == NULL ) { clocklog(0, "ERROR: Could not allocate.\n"); return false; } output->surface = surface; surface->dimensions = context.dimensions; surface->output = output; surface->background_surface = NULL; surface->hands_surface = NULL; surface->layer_surface = NULL; surface->configured = false; if ( NULL == (surface->background_surface = wl_compositor_create_surface(context.compositor)) ) { clocklog(0, "ERROR: Compositor did not create wl_surface (background).\n"); return false; } if ( NULL == (surface->layer_surface = zwlr_layer_shell_v1_get_layer_surface( context.layer_shell, surface->background_surface, output->wl_output, context.layer, context.namespace)) ) { clocklog(0, "ERROR: Compositor did not create layer_surface.\n"); return false; } zwlr_layer_surface_v1_add_listener(surface->layer_surface, &layer_surface_listener, surface); if ( NULL == (surface->hands_surface = wl_compositor_create_surface(context.compositor)) ) { clocklog(0, "ERROR: Compositor did not create wl_surface (hands).\n"); return false; } if ( NULL == (surface->subsurface = wl_subcompositor_get_subsurface( context.subcompositor, surface->hands_surface, surface->background_surface)) ) { clocklog(0, "ERROR: Compositor did not create wl_subsurface.\n"); return false; } /* Set up layer surface. */ zwlr_layer_surface_v1_set_size(surface->layer_surface, surface->dimensions.w, surface->dimensions.h); zwlr_layer_surface_v1_set_anchor(surface->layer_surface, context.anchor); zwlr_layer_surface_v1_set_margin(surface->layer_surface, context.margin_top, context.margin_right, context.margin_bottom, context.margin_left); zwlr_layer_surface_v1_set_exclusive_zone(surface->layer_surface, get_exclusive_zone(surface)); if (! context.input) { struct wl_region *region = wl_compositor_create_region(context.compositor); wl_surface_set_input_region(surface->background_surface, region); wl_region_destroy(region); } /* Set up subsurface. */ wl_subsurface_set_position(surface->subsurface, surface->dimensions.center_x, surface->dimensions.center_y); struct wl_region *region = wl_compositor_create_region(context.compositor); wl_surface_set_input_region(surface->hands_surface, region); wl_region_destroy(region); wl_surface_commit(surface->hands_surface); wl_surface_commit(surface->background_surface); return true; } void destroy_surface (struct Wlclock_surface *surface) { if ( surface == NULL ) return; if ( surface->output != NULL ) surface->output->surface = NULL; if ( surface->layer_surface != NULL ) zwlr_layer_surface_v1_destroy(surface->layer_surface); if ( surface->subsurface != NULL ) wl_subsurface_destroy(surface->subsurface); if ( surface->background_surface != NULL ) wl_surface_destroy(surface->background_surface); if ( surface->hands_surface != NULL ) wl_surface_destroy(surface->hands_surface); finish_buffer(&surface->background_buffers[0]); finish_buffer(&surface->background_buffers[1]); finish_buffer(&surface->hands_buffers[0]); finish_buffer(&surface->hands_buffers[1]); free(surface); }