commit 765b9bd99fb181078e15c553e0cbd57d2c0908ea
parent 2e46c9d760a6541606eec145a2b9ba9e7af1b351
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 23 Apr 2019 21:26:27 -0400
Receive & render new XDG surfaces
Diffstat:
6 files changed, 114 insertions(+), 1 deletion(-)
diff --git a/include/server.h b/include/server.h
@@ -10,6 +10,7 @@
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_pointer.h>
#include <wlr/types/wlr_xcursor_manager.h>
+#include <wlr/types/wlr_xdg_shell.h>
struct wio_server {
struct wl_display *wl_display;
@@ -20,11 +21,13 @@ struct wio_server {
struct wlr_renderer *renderer;
struct wlr_seat *seat;
struct wlr_xcursor_manager *cursor_mgr;
+ struct wlr_xdg_shell *xdg_shell;
struct wl_list outputs;
struct wl_list inputs;
struct wl_list pointers;
struct wl_list keyboards;
+ struct wl_list views;
struct wl_listener new_output;
struct wl_listener new_input;
@@ -32,6 +35,8 @@ struct wio_server {
struct wl_listener cursor_motion_absolute;
struct wl_listener cursor_button;
struct wl_listener cursor_axis;
+
+ struct wl_listener new_xdg_surface;
};
struct wio_output {
diff --git a/include/view.h b/include/view.h
@@ -0,0 +1,18 @@
+#ifndef _WIO_VIEW_H
+#define _WIO_VIEW_H
+#include <wlr/types/wlr_xdg_shell.h>
+#include <wayland-server.h>
+
+struct wio_server;
+
+struct wio_view {
+ int x, y;
+ struct wlr_xdg_surface *xdg_surface;
+ struct wio_server *server;
+ struct wl_list link;
+ struct wl_listener destroy;
+};
+
+void server_new_xdg_surface(struct wl_listener *listener, void *data);
+
+#endif
diff --git a/main.c b/main.c
@@ -8,8 +8,10 @@
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_xcursor_manager.h>
+#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/log.h>
#include "server.h"
+#include "view.h"
int main(int argc, char **argv) {
struct wio_server server;
@@ -56,6 +58,12 @@ int main(int argc, char **argv) {
wl_list_init(&server.keyboards);
wl_list_init(&server.pointers);
+ wl_list_init(&server.views);
+ server.xdg_shell = wlr_xdg_shell_create(server.wl_display);
+ server.new_xdg_surface.notify = server_new_xdg_surface;
+ wl_signal_add(&server.xdg_shell->events.new_surface,
+ &server.new_xdg_surface);
+
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
@@ -34,6 +34,7 @@ wio_sources = files(
'main.c',
'input.c',
'output.c',
+ 'view.c',
)
executable(
diff --git a/output.c b/output.c
@@ -2,10 +2,47 @@
#include <stdlib.h>
#include <time.h>
#include <wayland-server.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output.h>
#include <wlr/render/wlr_renderer.h>
#include "colors.h"
#include "server.h"
+#include "view.h"
+
+struct render_data {
+ struct wlr_output *output;
+ struct wlr_renderer *renderer;
+ struct wio_view *view;
+ struct timespec *when;
+};
+
+static void render_surface(struct wlr_surface *surface,
+ int sx, int sy, void *data) {
+ struct render_data *rdata = data;
+ struct wio_view *view = rdata->view;
+ struct wlr_output *output = rdata->output;
+ struct wlr_texture *texture = wlr_surface_get_texture(surface);
+ if (texture == NULL) {
+ return;
+ }
+ double ox = 0, oy = 0;
+ wlr_output_layout_output_coords(
+ view->server->output_layout, output, &ox, &oy);
+ ox += view->x + sx, oy += view->y + sy;
+ struct wlr_box box = {
+ .x = ox * output->scale,
+ .y = oy * output->scale,
+ .width = surface->current.width * output->scale,
+ .height = surface->current.height * output->scale,
+ };
+ float matrix[9];
+ enum wl_output_transform transform =
+ wlr_output_transform_invert(surface->current.transform);
+ wlr_matrix_project_box(matrix, &box, transform, 0,
+ output->transform_matrix);
+ wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1);
+ wlr_surface_send_frame_done(surface, rdata->when);
+}
static void output_frame(struct wl_listener *listener, void *data) {
struct wio_output *output = wl_container_of(listener, output, frame);
@@ -23,7 +60,22 @@ static void output_frame(struct wl_listener *listener, void *data) {
wlr_renderer_begin(renderer, width, height);
wlr_renderer_clear(renderer, background);
- // TODO: other stuff
+
+ struct wio_view *view;
+ wl_list_for_each_reverse(view, &output->server->views, link) {
+ if (!view->xdg_surface->mapped) {
+ continue;
+ }
+ struct render_data rdata = {
+ .output = output->wlr_output,
+ .view = view,
+ .renderer = renderer,
+ .when = &now,
+ };
+ wlr_xdg_surface_for_each_surface(view->xdg_surface,
+ render_surface, &rdata);
+ }
+
wlr_renderer_end(renderer);
wlr_output_swap_buffers(output->wlr_output, NULL, NULL);
}
diff --git a/view.c b/view.c
@@ -0,0 +1,29 @@
+#include <stdlib.h>
+#include <wayland-server.h>
+#include <wlr/types/wlr_xdg_shell.h>
+#include "server.h"
+#include "view.h"
+
+static void xdg_surface_destroy(struct wl_listener *listener, void *data) {
+ struct wio_view *view = wl_container_of(listener, view, destroy);
+ wl_list_remove(&view->link);
+ free(view);
+}
+
+void server_new_xdg_surface(struct wl_listener *listener, void *data) {
+ struct wio_server *server = wl_container_of(
+ listener, server, new_xdg_surface);
+ struct wlr_xdg_surface *xdg_surface = data;
+ if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
+ return;
+ }
+
+ struct wio_view *view = calloc(1, sizeof(struct wio_view));
+ view->server = server;
+ view->xdg_surface = xdg_surface;
+
+ view->destroy.notify = xdg_surface_destroy;
+ wl_signal_add(&xdg_surface->events.destroy, &view->destroy);
+
+ wl_list_insert(&server->views, &view->link);
+}