diff options
author | Leon Henrik Plickat <leonhenrik.plickat@stud.uni-goettingen.de> | 2020-09-25 14:41:47 +0200 |
---|---|---|
committer | Leon Henrik Plickat <leonhenrik.plickat@stud.uni-goettingen.de> | 2020-09-25 14:41:47 +0200 |
commit | 0984e60ec573f3a71cc880f8e9c3ccc047b7b2d6 (patch) | |
tree | 82868f2e3a302a66a8a4f56086ad062ba5800e1a /src | |
parent | fbb75017a893a039c0227d33df2be9a11c079fd5 (diff) | |
download | wlclock-0984e60ec573f3a71cc880f8e9c3ccc047b7b2d6.tar.gz wlclock-0984e60ec573f3a71cc880f8e9c3ccc047b7b2d6.tar.bz2 |
Draw clock hands
Diffstat (limited to 'src')
-rw-r--r-- | src/render.c | 91 | ||||
-rw-r--r-- | src/render.h | 3 | ||||
-rw-r--r-- | src/surface.c | 86 | ||||
-rw-r--r-- | src/surface.h | 11 | ||||
-rw-r--r-- | src/wlclock.c | 8 | ||||
-rw-r--r-- | src/wlclock.h | 1 |
6 files changed, 166 insertions, 34 deletions
diff --git a/src/render.c b/src/render.c index eb23b7a..7d189ec 100644 --- a/src/render.c +++ b/src/render.c @@ -121,11 +121,10 @@ static void draw_clock_face (cairo_t *cairo, struct Wlclock_dimensions *dimensio double cx = scale * (dimensions->center_x + (dimensions->center_size / 2)); double cy = scale * (dimensions->center_y + (dimensions->center_size / 2)); - double or = scale * 0.9 * dimensions->center_size / 2; + double or = scale * 0.9 * dimensions->center_size / 2; /* Radii mimick xclock. */ double ir = scale * 0.85 * dimensions->center_size / 2; double bir = scale * 0.8 * dimensions->center_size / 2; - double phi; - double phi_step = 2 * PI / 60; + double phi, phi_step = 2 * PI / 60; cairo_save(cairo); for (int i = 0; i < 60; i++) @@ -143,6 +142,51 @@ static void draw_clock_face (cairo_t *cairo, struct Wlclock_dimensions *dimensio cairo_restore(cairo); } +static int hour_two_pseudo_min (int hour) +{ + if ( hour > 12 ) + hour -= 12; + return hour * 5; +} + +static void draw_clock_hands (cairo_t *cairo, int32_t size, int32_t scale, struct Wlclock *clock) +{ + double cxy = scale * size / 2; + double mr = scale * 0.6 * size / 2; /* Radii mimick xclock. */ + double hr = scale * 0.4 * size / 2; + double ir = scale * 0.075 * size / 2; + double tip_phi, back_phi_1, back_phi_2, phi_step = 2 * PI / 60; + struct tm tm = *localtime(&clock->now); + + cairo_save(cairo); + + /* Minutes */ + tip_phi = phi_step * (tm.tm_min + 45); + back_phi_1 = phi_step * (tm.tm_min + 45 + 20); + back_phi_2 = phi_step * (tm.tm_min + 45 + 40); + cairo_move_to(cairo, cxy + mr * cos(tip_phi), cxy + mr * sin(tip_phi)); + cairo_line_to(cairo, cxy + ir * cos(back_phi_1), cxy + ir * sin(back_phi_1)); + cairo_line_to(cairo, cxy + ir * cos(back_phi_2), cxy + ir * sin(back_phi_2)); + cairo_line_to(cairo, cxy + mr * cos(tip_phi), cxy + mr * sin(tip_phi)); + + /* Hours */ + // TODO optinally make hour hand progress between to hours intstead of instantly snapping + int pseudo_min = hour_two_pseudo_min(tm.tm_hour); + tip_phi = phi_step * (pseudo_min + 45); + back_phi_1 = phi_step * (pseudo_min + 45 + 20); + back_phi_2 = phi_step * (pseudo_min + 45 + 40); + cairo_move_to(cairo, cxy + hr * cos(tip_phi), cxy + hr * sin(tip_phi)); + cairo_line_to(cairo, cxy + ir * cos(back_phi_1), cxy + ir * sin(back_phi_1)); + cairo_line_to(cairo, cxy + ir * cos(back_phi_2), cxy + ir * sin(back_phi_2)); + cairo_line_to(cairo, cxy + hr * cos(tip_phi), cxy + hr * sin(tip_phi)); + + cairo_close_path(cairo); + colour_set_cairo_source(cairo, &clock->clock_colour); + cairo_fill(cairo); + + cairo_restore(cairo); +} + static void clear_buffer (cairo_t *cairo) { cairo_save(cairo); @@ -151,29 +195,54 @@ static void clear_buffer (cairo_t *cairo) cairo_restore(cairo); } -void render_surface_frame (struct Wlclock_surface *surface) +void render_background_frame (struct Wlclock_surface *surface) { struct Wlclock_output *output = surface->output; struct Wlclock *clock = output->clock; uint32_t scale = output->scale; - clocklog(clock, 2, "[render] Render frame: global_name=%d\n", output->global_name); + clocklog(clock, 2, "[render] Render background frame: global_name=%d\n", + output->global_name); /* Get new/next buffer. */ - if (! next_buffer(&surface->current_buffer, clock->shm, surface->buffers, + if (! next_buffer(&surface->current_background_buffer, clock->shm, + surface->background_buffers, surface->dimensions.w * scale, surface->dimensions.h * scale)) return; - cairo_t *cairo = surface->current_buffer->cairo; + cairo_t *cairo = surface->current_background_buffer->cairo; clear_buffer(cairo); draw_background(cairo, &surface->dimensions, scale, clock); draw_clock_face(cairo, &surface->dimensions, scale, clock); - // TODO draw clock hands to subsurface + wl_surface_set_buffer_scale(surface->background_surface, scale); + wl_surface_attach(surface->background_surface, surface->current_background_buffer->buffer, 0, 0); + wl_surface_damage_buffer(surface->background_surface, 0, 0, INT32_MAX, INT32_MAX); +} + +void render_hands_frame (struct Wlclock_surface *surface) +{ + struct Wlclock_output *output = surface->output; + struct Wlclock *clock = output->clock; + uint32_t scale = output->scale; + clocklog(clock, 2, "[render] Render hands frame: global_name=%d\n", + output->global_name); + + /* Get new/next buffer. */ + if (! next_buffer(&surface->current_hands_buffer, clock->shm, + surface->hands_buffers, + surface->dimensions.center_size * scale, + surface->dimensions.center_size * scale)) + return; + + cairo_t *cairo = surface->current_hands_buffer->cairo; + clear_buffer(cairo); + + draw_clock_hands(cairo, surface->dimensions.center_size, scale, clock); - wl_surface_set_buffer_scale(surface->surface, scale); - wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0); - wl_surface_damage_buffer(surface->surface, 0, 0, INT32_MAX, INT32_MAX); + wl_surface_set_buffer_scale(surface->hands_surface, scale); + wl_surface_attach(surface->hands_surface, surface->current_hands_buffer->buffer, 0, 0); + wl_surface_damage_buffer(surface->hands_surface, 0, 0, INT32_MAX, INT32_MAX); } diff --git a/src/render.h b/src/render.h index ca4e54b..ed82de9 100644 --- a/src/render.h +++ b/src/render.h @@ -3,6 +3,7 @@ struct Wlclock_surface; -void render_surface_frame (struct Wlclock_surface *surface); +void render_background_frame (struct Wlclock_surface *surface); +void render_hands_frame (struct Wlclock_surface *surface); #endif diff --git a/src/surface.c b/src/surface.c index 19bd2d7..da3666d 100644 --- a/src/surface.c +++ b/src/surface.c @@ -96,10 +96,21 @@ static int32_t get_exclusive_zone (struct Wlclock_surface *surface) return surface->output->clock->exclusive_zone; } +static void configure_subsurface (struct Wlclock_surface *surface) +{ + clocklog(surface->output->clock, 1, "[surface] Configuring sub surface: global_name=%d\n", + surface->output->global_name); + wl_subsurface_set_position(surface->subsurface, + surface->dimensions.center_x, surface->dimensions.center_y); + struct wl_region *region = wl_compositor_create_region(surface->output->clock->compositor); + wl_surface_set_input_region(surface->hands_surface, region); + wl_region_destroy(region); +} + static void configure_layer_surface (struct Wlclock_surface *surface) { struct Wlclock *clock = surface->output->clock; - clocklog(clock, 1, "[surface] Configuring surface: global_name=%d\n", + clocklog(clock, 1, "[surface] Configuring layer surface: global_name=%d\n", surface->output->global_name); zwlr_layer_surface_v1_set_size(surface->layer_surface, surface->dimensions.w, surface->dimensions.h); @@ -112,7 +123,7 @@ static void configure_layer_surface (struct Wlclock_surface *surface) if (! clock->input) { struct wl_region *region = wl_compositor_create_region(clock->compositor); - wl_surface_set_input_region(surface->surface, region); + wl_surface_set_input_region(surface->background_surface, region); wl_region_destroy(region); } } @@ -129,20 +140,21 @@ bool create_surface (struct Wlclock_output *output) return false; } - output->surface = surface; - surface->dimensions = clock->dimensions; - surface->output = output; - surface->surface = NULL; - surface->layer_surface = NULL; - surface->configured = false; + output->surface = surface; + surface->dimensions = clock->dimensions; + surface->output = output; + surface->background_surface = NULL; + surface->hands_surface = NULL; + surface->layer_surface = NULL; + surface->configured = false; - if ( NULL == (surface->surface = wl_compositor_create_surface(clock->compositor)) ) + if ( NULL == (surface->background_surface = wl_compositor_create_surface(clock->compositor)) ) { - clocklog(NULL, 0, "ERROR: Compositor did not create wl_surface.\n"); + clocklog(NULL, 0, "ERROR: Compositor did not create wl_surface (background).\n"); return false; } if ( NULL == (surface->layer_surface = zwlr_layer_shell_v1_get_layer_surface( - clock->layer_shell, surface->surface, + clock->layer_shell, surface->background_surface, output->wl_output, clock->layer, clock->namespace)) ) { @@ -150,10 +162,25 @@ bool create_surface (struct Wlclock_output *output) return false; } + if ( NULL == (surface->hands_surface = wl_compositor_create_surface(clock->compositor)) ) + { + clocklog(NULL, 0, "ERROR: Compositor did not create wl_surface (hands).\n"); + return false; + } + if ( NULL == (surface->subsurface = wl_subcompositor_get_subsurface( + clock->subcompositor, surface->hands_surface, + surface->background_surface)) ) + { + clocklog(NULL, 0, "ERROR: Compositor did not create wl_subsurface.\n"); + return false; + } + configure_layer_surface(surface); + configure_subsurface(surface); zwlr_layer_surface_v1_add_listener(surface->layer_surface, &layer_surface_listener, surface); - wl_surface_commit(surface->surface); + wl_surface_commit(surface->background_surface); + wl_surface_commit(surface->hands_surface); return true; } @@ -164,10 +191,16 @@ void destroy_surface (struct Wlclock_surface *surface) return; if ( surface->layer_surface != NULL ) zwlr_layer_surface_v1_destroy(surface->layer_surface); - if ( surface->surface != NULL ) - wl_surface_destroy(surface->surface); - finish_buffer(&surface->buffers[0]); - finish_buffer(&surface->buffers[1]); + 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); } @@ -185,8 +218,11 @@ void update_surface (struct Wlclock_surface *surface) if ( surface == NULL || ! surface->configured ) return; configure_layer_surface(surface); - render_surface_frame(surface); - wl_surface_commit(surface->surface); + configure_subsurface(surface); + render_background_frame(surface); + render_hands_frame(surface); + wl_surface_commit(surface->background_surface); + wl_surface_commit(surface->hands_surface); } void update_all_surfaces (struct Wlclock *clock) @@ -197,3 +233,17 @@ void update_all_surfaces (struct Wlclock *clock) if ( op->surface != NULL ) update_surface(op->surface); } + +void update_all_hands (struct Wlclock *clock) +{ + clocklog(clock, 1, "[surface] Updating all hands.\n"); + struct Wlclock_output *op, *tmp; + wl_list_for_each_safe(op, tmp, &clock->outputs, link) + if ( op->surface != NULL ) + { + render_hands_frame(op->surface); + wl_surface_commit(op->surface->hands_surface); + wl_surface_commit(op->surface->background_surface); + } +} + diff --git a/src/surface.h b/src/surface.h index 0f6ce48..d2dcb25 100644 --- a/src/surface.h +++ b/src/surface.h @@ -15,12 +15,16 @@ struct Wlclock_output; struct Wlclock_surface { struct Wlclock_output *output; - struct wl_surface *surface; + struct wl_surface *background_surface; + struct wl_surface *hands_surface; + struct wl_subsurface *subsurface; struct zwlr_layer_surface_v1 *layer_surface; struct Wlclock_dimensions dimensions; - struct Wlclock_buffer buffers[2]; - struct Wlclock_buffer *current_buffer; + struct Wlclock_buffer background_buffers[2]; + struct Wlclock_buffer *current_background_buffer; + struct Wlclock_buffer hands_buffers[2]; + struct Wlclock_buffer *current_hands_buffer; bool configured; }; @@ -29,5 +33,6 @@ void destroy_surface (struct Wlclock_surface *surface); void destroy_all_surfaces (struct Wlclock *clock); void update_surface (struct Wlclock_surface *surface); void update_all_surfaces (struct Wlclock *clock); +void update_all_hands (struct Wlclock *clock); #endif diff --git a/src/wlclock.c b/src/wlclock.c index 9397ca0..8d23cdb 100644 --- a/src/wlclock.c +++ b/src/wlclock.c @@ -33,6 +33,12 @@ static void registry_handle_global (void *data, struct wl_registry *registry, clocklog(clock, 2, "[main] Get wl_compositor.\n"); clock->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 4); } + if (! strcmp(interface, wl_subcompositor_interface.name)) + { + clocklog(clock, 2, "[main] Get wl_subcompositor.\n"); + clock->subcompositor = wl_registry_bind(registry, name, + &wl_subcompositor_interface, 1); + } else if (! strcmp(interface, wl_shm_interface.name)) { clocklog(clock, 2, "[main] Get wl_shm.\n"); @@ -500,7 +506,7 @@ static void clock_run (struct Wlclock *clock) if ( ret == 0 ) { clock->now = time(NULL); - // TODO update clock hands + update_all_hands(clock); continue; } else if ( ret < 0 ) diff --git a/src/wlclock.h b/src/wlclock.h index ec8f981..d76bd86 100644 --- a/src/wlclock.h +++ b/src/wlclock.h @@ -26,6 +26,7 @@ struct Wlclock struct wl_display *display; struct wl_registry *registry; struct wl_compositor *compositor; + struct wl_subcompositor *subcompositor; struct wl_shm *shm; struct zwlr_layer_shell_v1 *layer_shell; struct zxdg_output_manager_v1 *xdg_output_manager; |