aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r--sway/desktop/output.c248
1 files changed, 192 insertions, 56 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 2b428c30..0f00222b 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -1,9 +1,11 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <assert.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <time.h> 4#include <time.h>
4#include <wayland-server.h> 5#include <wayland-server.h>
5#include <wlr/types/wlr_output.h> 6#include <wlr/types/wlr_output.h>
6#include <wlr/types/wlr_surface.h> 7#include <wlr/types/wlr_surface.h>
8#include <wlr/types/wlr_wl_shell.h>
7#include <wlr/render.h> 9#include <wlr/render.h>
8#include <wlr/render/matrix.h> 10#include <wlr/render/matrix.h>
9#include "log.h" 11#include "log.h"
@@ -15,76 +17,198 @@
15#include "sway/input/input-manager.h" 17#include "sway/input/input-manager.h"
16#include "sway/input/seat.h" 18#include "sway/input/seat.h"
17 19
18static void output_frame_view(swayc_t *view, void *data) { 20/**
19 struct sway_output *output = data; 21 * Rotate a child's position relative to a parent. The parent size is (pw, ph),
20 struct wlr_output *wlr_output = output->wlr_output; 22 * the child position is (*sx, *sy) and its size is (sw, sh).
21 struct sway_view *sway_view = view->sway_view; 23 */
22 struct wlr_surface *surface = sway_view->surface; 24static void rotate_child_position(double *sx, double *sy, double sw, double sh,
25 double pw, double ph, float rotation) {
26 if (rotation != 0.0) {
27 // Coordinates relative to the center of the subsurface
28 double ox = *sx - pw/2 + sw/2,
29 oy = *sy - ph/2 + sh/2;
30 // Rotated coordinates
31 double rx = cos(-rotation)*ox - sin(-rotation)*oy,
32 ry = cos(-rotation)*oy + sin(-rotation)*ox;
33 *sx = rx + pw/2 - sw/2;
34 *sy = ry + ph/2 - sh/2;
35 }
36}
37
38static void render_surface(struct wlr_surface *surface,
39 struct wlr_output *wlr_output, struct timespec *when,
40 double lx, double ly, float rotation) {
23 if (!wlr_surface_has_buffer(surface)) { 41 if (!wlr_surface_has_buffer(surface)) {
24 return; 42 return;
25 } 43 }
26 // TODO 44 struct wlr_output_layout *layout = root_container.sway_root->output_layout;
27 // - Deal with wlr_output_layout 45 int width = surface->current->width;
28 int width = sway_view->surface->current->width; 46 int height = surface->current->height;
29 int height = sway_view->surface->current->height;
30 int render_width = width * wlr_output->scale; 47 int render_width = width * wlr_output->scale;
31 int render_height = height * wlr_output->scale; 48 int render_height = height * wlr_output->scale;
32 double ox = view->x, oy = view->y; 49 double ox = lx, oy = ly;
33 // TODO 50 wlr_output_layout_output_coords(layout, wlr_output, &ox, &oy);
34 //wlr_output_layout_output_coords(desktop->layout, wlr_output, &ox, &oy);
35 ox *= wlr_output->scale; 51 ox *= wlr_output->scale;
36 oy *= wlr_output->scale; 52 oy *= wlr_output->scale;
37 // TODO 53
38 //if (wlr_output_layout_intersects(desktop->layout, wlr_output, 54 struct wlr_box render_box = {
39 // lx, ly, lx + render_width, ly + render_height)) { 55 .x = lx, .y = ly,
40 // return; 56 .width = render_width, .height = render_height,
41 //} 57 };
42 58 if (wlr_output_layout_intersects(layout, wlr_output, &render_box)) {
43 // if the shell specifies window geometry, make the top left corner of the 59 float matrix[16];
44 // window in the top left corner of the container to avoid arbitrarily 60
45 // sized gaps based on the attached buffer size 61 float translate_center[16];
46 int window_offset_x = 0; 62 wlr_matrix_translate(&translate_center,
47 int window_offset_y = 0; 63 (int)ox + render_width / 2, (int)oy + render_height / 2, 0);
48 64
49 if (view->sway_view->type == SWAY_XDG_SHELL_V6_VIEW) { 65 float rotate[16];
50 window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry->x; 66 wlr_matrix_rotate(&rotate, rotation);
51 window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry->y; 67
68 float translate_origin[16];
69 wlr_matrix_translate(&translate_origin, -render_width / 2,
70 -render_height / 2, 0);
71
72 float scale[16];
73 wlr_matrix_scale(&scale, render_width, render_height, 1);
74
75 float transform[16];
76 wlr_matrix_mul(&translate_center, &rotate, &transform);
77 wlr_matrix_mul(&transform, &translate_origin, &transform);
78 wlr_matrix_mul(&transform, &scale, &transform);
79
80 if (surface->current->transform != WL_OUTPUT_TRANSFORM_NORMAL) {
81 float surface_translate_center[16];
82 wlr_matrix_translate(&surface_translate_center, 0.5, 0.5, 0);
83
84 float surface_transform[16];
85 wlr_matrix_transform(surface_transform,
86 wlr_output_transform_invert(surface->current->transform));
87
88 float surface_translate_origin[16];
89 wlr_matrix_translate(&surface_translate_origin, -0.5, -0.5, 0);
90
91 wlr_matrix_mul(&transform, &surface_translate_center,
92 &transform);
93 wlr_matrix_mul(&transform, &surface_transform, &transform);
94 wlr_matrix_mul(&transform, &surface_translate_origin,
95 &transform);
96 }
97
98 wlr_matrix_mul(&wlr_output->transform_matrix, &transform, &matrix);
99
100 wlr_render_with_matrix(server.renderer, surface->texture,
101 &matrix);
102
103 wlr_surface_send_frame_done(surface, when);
52 } 104 }
53 105
54 // TODO 106 struct wlr_subsurface *subsurface;
55 double rotation = 0; 107 wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) {
56 float matrix[16]; 108 struct wlr_surface_state *state = subsurface->surface->current;
109 double sx = state->subsurface_position.x;
110 double sy = state->subsurface_position.y;
111 double sw = state->buffer_width / state->scale;
112 double sh = state->buffer_height / state->scale;
113 rotate_child_position(&sx, &sy, sw, sh, width, height, rotation);
57 114
58 float translate_origin[16]; 115 render_surface(subsurface->surface, wlr_output, when,
59 wlr_matrix_translate(&translate_origin, 116 lx + sx,
60 (int)ox + render_width / 2 - window_offset_x, 117 ly + sy,
61 (int)oy + render_height / 2 - window_offset_y, 118 rotation);
62 0); 119 }
120}
63 121
64 float rotate[16]; 122static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface,
65 wlr_matrix_rotate(&rotate, rotation); 123 struct wlr_output *wlr_output, struct timespec *when, double base_x,
124 double base_y, float rotation) {
125 double width = surface->surface->current->width;
126 double height = surface->surface->current->height;
66 127
67 float translate_center[16]; 128 struct wlr_xdg_surface_v6 *popup;
68 wlr_matrix_translate(&translate_center, 129 wl_list_for_each(popup, &surface->popups, popup_link) {
69 -render_width / 2, 130 if (!popup->configured) {
70 -render_height / 2, 0); 131 continue;
132 }
71 133
72 float scale[16]; 134 double popup_width = popup->surface->current->width;
73 wlr_matrix_scale(&scale, render_width, render_height, 1); 135 double popup_height = popup->surface->current->height;
74 136
75 float transform[16]; 137 double popup_sx, popup_sy;
76 wlr_matrix_mul(&translate_origin, &rotate, &transform); 138 wlr_xdg_surface_v6_popup_get_position(popup, &popup_sx, &popup_sy);
77 wlr_matrix_mul(&transform, &translate_center, &transform); 139 rotate_child_position(&popup_sx, &popup_sy, popup_width, popup_height,
78 wlr_matrix_mul(&transform, &scale, &transform); 140 width, height, rotation);
79 wlr_matrix_mul(&wlr_output->transform_matrix, &transform, &matrix);
80 141
81 wlr_render_with_matrix(output->server->renderer, surface->texture, &matrix); 142 render_surface(popup->surface, wlr_output, when,
143 base_x + popup_sx, base_y + popup_sy, rotation);
144 render_xdg_v6_popups(popup, wlr_output, when,
145 base_x + popup_sx, base_y + popup_sy, rotation);
146 }
147}
82 148
83 // TODO: move into wlroots 149static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface,
84 struct timespec now; 150 struct wlr_output *wlr_output, struct timespec *when,
85 clock_gettime(CLOCK_MONOTONIC, &now); 151 double lx, double ly, float rotation,
152 bool is_child) {
153 if (is_child || surface->state != WLR_WL_SHELL_SURFACE_STATE_POPUP) {
154 render_surface(surface->surface, wlr_output, when,
155 lx, ly, rotation);
156
157 double width = surface->surface->current->width;
158 double height = surface->surface->current->height;
159
160 struct wlr_wl_shell_surface *popup;
161 wl_list_for_each(popup, &surface->popups, popup_link) {
162 double popup_width = popup->surface->current->width;
163 double popup_height = popup->surface->current->height;
164
165 double popup_x = popup->transient_state->x;
166 double popup_y = popup->transient_state->y;
167 rotate_child_position(&popup_x, &popup_y, popup_width, popup_height,
168 width, height, rotation);
169
170 render_wl_shell_surface(popup, wlr_output, when,
171 lx + popup_x, ly + popup_y, rotation, true);
172 }
173 }
174}
175
176
177static void output_frame_view(swayc_t *view, void *data) {
178 struct sway_output *output = data;
179 struct wlr_output *wlr_output = output->wlr_output;
180 struct sway_view *sway_view = view->sway_view;
181 struct wlr_surface *surface = sway_view->surface;
182
183 if (!surface) {
184 return;
185 }
86 186
87 wlr_surface_send_frame_done(surface, &now); 187 switch (sway_view->type) {
188 case SWAY_XDG_SHELL_V6_VIEW: {
189 int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry->x;
190 int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry->y;
191 render_surface(surface, wlr_output, &output->last_frame,
192 view->x - window_offset_x,
193 view->y - window_offset_y,
194 0);
195 render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output,
196 &output->last_frame,
197 view->x - window_offset_x, view->y - window_offset_y,
198 0);
199 break;
200 }
201 case SWAY_WL_SHELL_VIEW:
202 render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output,
203 &output->last_frame, view->x, view->y, 0, false);
204 break;
205 case SWAY_XWAYLAND_VIEW:
206 render_surface(surface, wlr_output, &output->last_frame, view->x,
207 view->y, 0);
208 break;
209 default:
210 break;
211 }
88} 212}
89 213
90static void output_frame_notify(struct wl_listener *listener, void *data) { 214static void output_frame_notify(struct wl_listener *listener, void *data) {
@@ -92,18 +216,30 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
92 struct wlr_output *wlr_output = data; 216 struct wlr_output *wlr_output = data;
93 struct sway_server *server = soutput->server; 217 struct sway_server *server = soutput->server;
94 218
95 struct timespec now;
96 clock_gettime(CLOCK_MONOTONIC, &now);
97
98 wlr_output_make_current(wlr_output); 219 wlr_output_make_current(wlr_output);
99 wlr_renderer_begin(server->renderer, wlr_output); 220 wlr_renderer_begin(server->renderer, wlr_output);
100 221
101 swayc_descendants_of_type( 222 swayc_descendants_of_type(
102 &root_container, C_VIEW, output_frame_view, soutput); 223 &root_container, C_VIEW, output_frame_view, soutput);
103 224
225 // render unmanaged views on top
226 struct sway_view *view;
227 wl_list_for_each(view, &root_container.sway_root->unmanaged_views,
228 unmanaged_view_link) {
229 if (view->type == SWAY_XWAYLAND_VIEW) {
230 // the only kind of unamanged view right now is xwayland override redirect
231 int view_x = view->wlr_xwayland_surface->x;
232 int view_y = view->wlr_xwayland_surface->y;
233 render_surface(view->surface, wlr_output, &soutput->last_frame,
234 view_x, view_y, 0);
235 }
236 }
237
104 wlr_renderer_end(server->renderer); 238 wlr_renderer_end(server->renderer);
105 wlr_output_swap_buffers(wlr_output); 239 wlr_output_swap_buffers(wlr_output);
106 240
241 struct timespec now;
242 clock_gettime(CLOCK_MONOTONIC, &now);
107 soutput->last_frame = now; 243 soutput->last_frame = now;
108} 244}
109 245