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:
M | include/server.h | | | 6 | ++++++ |
M | main.c | | | 53 | +++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | meson.build | | | 2 | ++ |
M | output.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);
}