wio

a wayland wm stylised after plan9 rio - forked from git.sr.ht/~srcmpwn/wio
git clone git://src.gearsix.net/wio
Log | Files | Refs | Atom | Submodules | README | LICENSE

commit 8c9fb27c09c2645e5e97701940f6bdda42a49e29
parent 2f2483e29a1aa2e91556afc2c4f22af31d2d5e88
Author: Drew DeVault <sir@cmpwn.com>
Date:   Tue, 23 Apr 2019 22:38:26 -0400

Add menu renderer (not rigged up to code yet)

Diffstat:
Minclude/server.h | 6++++++
Mmain.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmeson.build | 2++
Moutput.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 154 insertions(+), 2 deletions(-)

diff --git a/include/server.h b/include/server.h @@ -37,6 +37,12 @@ struct wio_server { struct wl_listener cursor_axis; struct wl_listener new_xdg_surface; + + struct { + int x, y; + struct wlr_texture *active_textures[5]; + struct wlr_texture *inactive_textures[5]; + } menu; }; struct wio_output { diff --git a/main.c b/main.c @@ -1,9 +1,11 @@ #define _POSIX_C_SOURCE 200112L +#include <cairo/cairo.h> #include <stdlib.h> #include <time.h> #include <wayland-server.h> #include <wlr/backend.h> #include <wlr/render/wlr_renderer.h> +#include <wlr/render/wlr_texture.h> #include <wlr/types/wlr_compositor.h> #include <wlr/types/wlr_data_device.h> #include <wlr/types/wlr_seat.h> @@ -13,6 +15,54 @@ #include "server.h" #include "view.h" +static void gen_menu_textures(struct wio_server *server) { + struct wlr_renderer *renderer = server->renderer; + cairo_surface_t *surf = cairo_image_surface_create( + CAIRO_FORMAT_ARGB32, 128, 128); // numbers pulled from ass + cairo_t *cairo = cairo_create(surf); + cairo_select_font_face(cairo, "monospace", + CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cairo, 14); + cairo_set_source_rgb(cairo, 0, 0, 0); + + char *text[] = { "New", "Resize", "Move", "Delete", "Hide" }; + for (size_t i = 0; i < sizeof(text) / sizeof(text[0]); ++i) { + cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); + cairo_paint(cairo); + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + cairo_text_extents_t extents; + cairo_text_extents(cairo, text[i], &extents); + cairo_move_to(cairo, 0, extents.height); + cairo_show_text(cairo, text[i]); + cairo_surface_flush(surf); + unsigned char *data = cairo_image_surface_get_data(surf); + server->menu.inactive_textures[i] = wlr_texture_from_pixels(renderer, + WL_SHM_FORMAT_ARGB8888, + cairo_image_surface_get_stride(surf), + extents.width + 2, extents.height + 2, data); + } + + cairo_set_source_rgb(cairo, 1, 1, 1); + for (size_t i = 0; i < sizeof(text) / sizeof(text[0]); ++i) { + cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); + cairo_paint(cairo); + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + cairo_text_extents_t extents; + cairo_text_extents(cairo, text[i], &extents); + cairo_move_to(cairo, 0, extents.height); + cairo_show_text(cairo, text[i]); + cairo_surface_flush(surf); + unsigned char *data = cairo_image_surface_get_data(surf); + server->menu.active_textures[i] = wlr_texture_from_pixels(renderer, + WL_SHM_FORMAT_ARGB8888, + cairo_image_surface_get_stride(surf), + extents.width + 2, extents.height + 2, data); + } + + cairo_destroy(cairo); + cairo_surface_destroy(surf); +} + int main(int argc, char **argv) { struct wio_server server; @@ -64,6 +114,9 @@ int main(int argc, char **argv) { wl_signal_add(&server.xdg_shell->events.new_surface, &server.new_xdg_surface); + server.menu.x = server.menu.y = 10; + gen_menu_textures(&server); + const char *socket = wl_display_add_socket_auto(server.wl_display); if (!socket) { wlr_backend_destroy(server.backend); diff --git a/meson.build b/meson.build @@ -21,6 +21,7 @@ add_project_arguments( language: 'c', ) +cairo = dependency('cairo') wlroots = dependency('wlroots', fallback: ['wlroots', 'wlroots']) wayland_server = dependency('wayland-server') wayland_protos = dependency('wayland-protocols') @@ -42,6 +43,7 @@ executable( wio_sources, include_directories: [wio_inc], dependencies: [ + cairo, server_protos, wayland_server, wlroots, diff --git a/output.c b/output.c @@ -44,9 +44,96 @@ static void render_surface(struct wlr_surface *surface, wlr_surface_send_frame_done(surface, rdata->when); } +static void render_menu(struct wio_output *output) { + struct wio_server *server = output->server; + struct wlr_renderer *renderer = server->renderer; + + size_t ntextures = + sizeof(server->menu.inactive_textures) / + sizeof(server->menu.inactive_textures[0]); + const int border = 3, margin = 4; + int text_height = 0, text_width = 0; + for (size_t i = 0; i < ntextures; ++i) { + int width, height; + // Assumes inactive/active textures are the same size + // (they probably are) + wlr_texture_get_size( + server->menu.inactive_textures[i], &width, &height); + text_height += height + margin; + if (width >= text_width) { + text_width = width; + } + } + text_width += border * 2; + text_height += border * 2 - margin; + + double ox = 0, oy = 0; + //wlr_output_layout_output_coords( + // view->server->output_layout, output->wlr_output, &ox, &oy); + ox += server->menu.x, oy += server->menu.y; + int scale = output->wlr_output->scale; + + struct wlr_box bg_box = { + .x = ox * scale, + .y = oy * scale, + .width = text_width * scale, + .height = text_height * scale, + }; + wlr_render_rect(renderer, &bg_box, menu_unselected, + output->wlr_output->transform_matrix); + bg_box.height = border; + wlr_render_rect(renderer, &bg_box, menu_border, + output->wlr_output->transform_matrix); + bg_box.width += border; + bg_box.y = (oy + text_height) * scale; + wlr_render_rect(renderer, &bg_box, menu_border, + output->wlr_output->transform_matrix); + bg_box.y = oy * scale; + bg_box.height = text_height * scale; + bg_box.width = border; + wlr_render_rect(renderer, &bg_box, menu_border, + output->wlr_output->transform_matrix); + bg_box.x = (ox + text_width) * scale; + wlr_render_rect(renderer, &bg_box, menu_border, + output->wlr_output->transform_matrix); + + ox += margin; + oy += margin; + for (size_t i = 0; i < ntextures; ++i) { + int width, height; + struct wlr_texture *texture; + if (i == 0) { // TODO: if cursor is over this menu item + texture = server->menu.active_textures[i]; + wlr_texture_get_size(texture, &width, &height); + struct wlr_box box = { + .x = ox - 1 * scale, .y = oy - 1 * scale, + .width = (text_width - border) * scale, + .height = (height + margin) * scale, + }; + wlr_render_rect(renderer, &box, menu_selected, + output->wlr_output->transform_matrix); + } else { + texture = server->menu.inactive_textures[i]; + wlr_texture_get_size(texture, &width, &height); + } + struct wlr_box box = { + .x = (ox + (text_width / 2 - width / 2)) * scale, + .y = oy * scale, + .width = width * scale, + .height = height * scale, + }; + float matrix[9]; + wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, + output->wlr_output->transform_matrix); + wlr_render_texture_with_matrix(renderer, texture, matrix, 1); + oy += height + margin; + } +} + static void output_frame(struct wl_listener *listener, void *data) { struct wio_output *output = wl_container_of(listener, output, frame); - struct wlr_renderer *renderer = output->server->renderer; + struct wio_server *server = output->server; + struct wlr_renderer *renderer = server->renderer; struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -62,7 +149,7 @@ static void output_frame(struct wl_listener *listener, void *data) { wlr_renderer_clear(renderer, background); struct wio_view *view; - wl_list_for_each_reverse(view, &output->server->views, link) { + wl_list_for_each_reverse(view, &server->views, link) { if (!view->xdg_surface->mapped) { continue; } @@ -76,6 +163,10 @@ static void output_frame(struct wl_listener *listener, void *data) { render_surface, &rdata); } + if (server->menu.x != -1 && server->menu.y != -1) { + render_menu(output); + } + wlr_renderer_end(renderer); wlr_output_swap_buffers(output->wlr_output, NULL, NULL); }