diff --git a/examples/output-layout.c b/examples/output-layout.c index b9228692..d9325838 100644 --- a/examples/output-layout.c +++ b/examples/output-layout.c @@ -105,11 +105,11 @@ static void handle_output_frame(struct output_state *output, animate_cat(sample, output->output); - bool intersects = wlr_output_layout_intersects(sample->layout, - output->output, sample->x_offs, sample->y_offs, - sample->x_offs + 128, sample->y_offs + 128); - - if (intersects) { + struct wlr_box box = { + .x = sample->x_offs, .y = sample->y_offs, + .width = 128, .height = 128, + }; + if (wlr_output_layout_intersects(sample->layout, output->output, &box)) { float matrix[16]; // transform global coordinates to local coordinates @@ -122,7 +122,6 @@ static void handle_output_frame(struct output_state *output, &wlr_output->transform_matrix, local_x, local_y); wlr_render_with_matrix(sample->renderer, sample->cat_texture, &matrix); - } wlr_renderer_end(sample->renderer); diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index a016bb94..8d706b65 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -47,6 +47,7 @@ struct roots_desktop { struct wl_listener output_add; struct wl_listener output_remove; + struct wl_listener layout_change; struct wl_listener xdg_shell_v6_surface; struct wl_listener wl_shell_surface; struct wl_listener decoration_new; diff --git a/include/wlr/types/wlr_box.h b/include/wlr/types/wlr_box.h index 5290ada5..0588201c 100644 --- a/include/wlr/types/wlr_box.h +++ b/include/wlr/types/wlr_box.h @@ -8,18 +8,18 @@ struct wlr_box { int width, height; }; -void wlr_box_closest_point(struct wlr_box *box, double x, double y, - double *dest_x, double *dest_y); +void wlr_box_closest_point(const struct wlr_box *box, double x, double y, + double *dest_x, double *dest_y); -bool wlr_box_intersection(struct wlr_box *box_a, - struct wlr_box *box_b, struct wlr_box **dest); +bool wlr_box_intersection(const struct wlr_box *box_a, + const struct wlr_box *box_b, struct wlr_box *dest); -bool wlr_box_contains_point(struct wlr_box *box, double x, double y); +bool wlr_box_contains_point(const struct wlr_box *box, double x, double y); -bool wlr_box_empty(struct wlr_box *box); +bool wlr_box_empty(const struct wlr_box *box); enum wl_output_transform; -void wlr_box_transform(struct wlr_box *box, enum wl_output_transform transform, - struct wlr_box *dest); +void wlr_box_transform(const struct wlr_box *box, + enum wl_output_transform transform, struct wlr_box *dest); #endif diff --git a/include/wlr/types/wlr_output_layout.h b/include/wlr/types/wlr_output_layout.h index a99debf6..9187b377 100644 --- a/include/wlr/types/wlr_output_layout.h +++ b/include/wlr/types/wlr_output_layout.h @@ -1,6 +1,7 @@ #ifndef WLR_TYPES_WLR_OUTPUT_LAYOUT_H #define WLR_TYPES_WLR_OUTPUT_LAYOUT_H +#include #include #include #include @@ -61,7 +62,7 @@ bool wlr_output_layout_contains_point(struct wlr_output_layout *layout, struct wlr_output *reference, int x, int y); bool wlr_output_layout_intersects(struct wlr_output_layout *layout, - struct wlr_output *reference, int x1, int y1, int x2, int y2); + struct wlr_output *reference, const struct wlr_box *target_box); /** * Get the closest point on this layout from the given point from the reference diff --git a/rootston/desktop.c b/rootston/desktop.c index 69dcf4a9..b74e2cb1 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -38,12 +38,9 @@ static void view_update_output(const struct roots_view *view, view_get_box(view, &box); wl_list_for_each(output, &desktop->outputs, link) { bool intersected = before != NULL && wlr_output_layout_intersects( - desktop->layout, output->wlr_output, - before->x, before->y, before->x + before->width, - before->y + before->height); - bool intersects = wlr_output_layout_intersects( - desktop->layout, output->wlr_output, - view->x, view->y, view->x + box.width, view->y + box.height); + desktop->layout, output->wlr_output, before); + bool intersects = wlr_output_layout_intersects(desktop->layout, + output->wlr_output, &box); if (intersected && !intersects) { wlr_surface_send_leave(view->wlr_surface, output->wlr_output); } @@ -386,6 +383,34 @@ struct roots_view *desktop_view_at(struct roots_desktop *desktop, double lx, return NULL; } +static void handle_layout_change(struct wl_listener *listener, void *data) { + struct roots_desktop *desktop = + wl_container_of(listener, desktop, layout_change); + + struct wlr_output *center_output = + wlr_output_layout_get_center_output(desktop->layout); + if (center_output == NULL) { + return; + } + + struct wlr_box *center_output_box = + wlr_output_layout_get_box(desktop->layout, center_output); + double center_x = center_output_box->x + center_output_box->width/2; + double center_y = center_output_box->y + center_output_box->height/2; + + struct roots_view *view; + wl_list_for_each(view, &desktop->views, link) { + struct wlr_box box; + view_get_box(view, &box); + + if (wlr_output_layout_intersects(desktop->layout, NULL, &box)) { + continue; + } + + view_move(view, center_x - box.width/2, center_y - box.height/2); + } +} + struct roots_desktop *desktop_create(struct roots_server *server, struct roots_config *config) { wlr_log(L_DEBUG, "Initializing roots desktop"); @@ -428,6 +453,9 @@ struct roots_desktop *desktop_create(struct roots_server *server, } desktop->layout = wlr_output_layout_create(); + desktop->layout_change.notify = handle_layout_change; + wl_signal_add(&desktop->layout->events.change, &desktop->layout_change); + desktop->compositor = wlr_compositor_create(server->wl_display, server->renderer); diff --git a/rootston/output.c b/rootston/output.c index e510be71..10450df3 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -34,79 +34,84 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, static void render_surface(struct wlr_surface *surface, struct roots_desktop *desktop, struct wlr_output *wlr_output, struct timespec *when, double lx, double ly, float rotation) { - if (wlr_surface_has_buffer(surface)) { - int width = surface->current->width; - int height = surface->current->height; - int render_width = width * wlr_output->scale; - int render_height = height * wlr_output->scale; - double ox = lx, oy = ly; - wlr_output_layout_output_coords(desktop->layout, wlr_output, &ox, &oy); - ox *= wlr_output->scale; - oy *= wlr_output->scale; - - if (wlr_output_layout_intersects(desktop->layout, wlr_output, - lx, ly, lx + render_width, ly + render_height)) { - float matrix[16]; - - float translate_center[16]; - wlr_matrix_translate(&translate_center, - (int)ox + render_width / 2, (int)oy + render_height / 2, 0); - - float rotate[16]; - wlr_matrix_rotate(&rotate, rotation); - - float translate_origin[16]; - wlr_matrix_translate(&translate_origin, -render_width / 2, - -render_height / 2, 0); - - float scale[16]; - wlr_matrix_scale(&scale, render_width, render_height, 1); - - float transform[16]; - wlr_matrix_mul(&translate_center, &rotate, &transform); - wlr_matrix_mul(&transform, &translate_origin, &transform); - wlr_matrix_mul(&transform, &scale, &transform); - - if (surface->current->transform != WL_OUTPUT_TRANSFORM_NORMAL) { - float surface_translate_center[16]; - wlr_matrix_translate(&surface_translate_center, 0.5, 0.5, 0); - - float surface_transform[16]; - wlr_matrix_transform(surface_transform, - wlr_output_transform_invert(surface->current->transform)); - - float surface_translate_origin[16]; - wlr_matrix_translate(&surface_translate_origin, -0.5, -0.5, 0); - - wlr_matrix_mul(&transform, &surface_translate_center, - &transform); - wlr_matrix_mul(&transform, &surface_transform, &transform); - wlr_matrix_mul(&transform, &surface_translate_origin, - &transform); - } + if (!wlr_surface_has_buffer(surface)) { + return; + } - wlr_matrix_mul(&wlr_output->transform_matrix, &transform, &matrix); + int width = surface->current->width; + int height = surface->current->height; + int render_width = width * wlr_output->scale; + int render_height = height * wlr_output->scale; + double ox = lx, oy = ly; + wlr_output_layout_output_coords(desktop->layout, wlr_output, &ox, &oy); + ox *= wlr_output->scale; + oy *= wlr_output->scale; + + struct wlr_box render_box = { + .x = lx, .y = ly, + .width = render_width, .height = render_height, + }; + if (wlr_output_layout_intersects(desktop->layout, wlr_output, &render_box)) { + float matrix[16]; + + float translate_center[16]; + wlr_matrix_translate(&translate_center, + (int)ox + render_width / 2, (int)oy + render_height / 2, 0); + + float rotate[16]; + wlr_matrix_rotate(&rotate, rotation); + + float translate_origin[16]; + wlr_matrix_translate(&translate_origin, -render_width / 2, + -render_height / 2, 0); + + float scale[16]; + wlr_matrix_scale(&scale, render_width, render_height, 1); + + float transform[16]; + wlr_matrix_mul(&translate_center, &rotate, &transform); + wlr_matrix_mul(&transform, &translate_origin, &transform); + wlr_matrix_mul(&transform, &scale, &transform); + + if (surface->current->transform != WL_OUTPUT_TRANSFORM_NORMAL) { + float surface_translate_center[16]; + wlr_matrix_translate(&surface_translate_center, 0.5, 0.5, 0); + + float surface_transform[16]; + wlr_matrix_transform(surface_transform, + wlr_output_transform_invert(surface->current->transform)); + + float surface_translate_origin[16]; + wlr_matrix_translate(&surface_translate_origin, -0.5, -0.5, 0); + + wlr_matrix_mul(&transform, &surface_translate_center, + &transform); + wlr_matrix_mul(&transform, &surface_transform, &transform); + wlr_matrix_mul(&transform, &surface_translate_origin, + &transform); + } - wlr_render_with_matrix(desktop->server->renderer, surface->texture, - &matrix); + wlr_matrix_mul(&wlr_output->transform_matrix, &transform, &matrix); - wlr_surface_send_frame_done(surface, when); - } + wlr_render_with_matrix(desktop->server->renderer, surface->texture, + &matrix); - struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { - struct wlr_surface_state *state = subsurface->surface->current; - double sx = state->subsurface_position.x; - double sy = state->subsurface_position.y; - double sw = state->buffer_width / state->scale; - double sh = state->buffer_height / state->scale; - rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); - - render_surface(subsurface->surface, desktop, wlr_output, when, - lx + sx, - ly + sy, - rotation); - } + wlr_surface_send_frame_done(surface, when); + } + + struct wlr_subsurface *subsurface; + wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { + struct wlr_surface_state *state = subsurface->surface->current; + double sx = state->subsurface_position.x; + double sy = state->subsurface_position.y; + double sw = state->buffer_width / state->scale; + double sh = state->buffer_height / state->scale; + rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); + + render_surface(subsurface->surface, desktop, wlr_output, when, + lx + sx, + ly + sy, + rotation); } } @@ -356,7 +361,9 @@ void output_add_notify(struct wl_listener *listener, void *data) { void output_remove_notify(struct wl_listener *listener, void *data) { struct wlr_output *wlr_output = data; - struct roots_desktop *desktop = wl_container_of(listener, desktop, output_remove); + struct roots_desktop *desktop = + wl_container_of(listener, desktop, output_remove); + struct roots_output *output = NULL, *_output; wl_list_for_each(_output, &desktop->outputs, link) { if (_output->wlr_output == wlr_output) { @@ -367,10 +374,13 @@ void output_remove_notify(struct wl_listener *listener, void *data) { if (!output) { return; // We are unfamiliar with this output } + wlr_output_layout_remove(desktop->layout, output->wlr_output); + // TODO: cursor //example_config_configure_cursor(sample->config, sample->cursor, // sample->compositor); + wl_list_remove(&output->link); wl_list_remove(&output->frame.link); free(output); diff --git a/types/wlr_box.c b/types/wlr_box.c index 5e910b2e..9afd7ef0 100644 --- a/types/wlr_box.c +++ b/types/wlr_box.c @@ -6,7 +6,7 @@ #include #include -void wlr_box_closest_point(struct wlr_box *box, double x, double y, +void wlr_box_closest_point(const struct wlr_box *box, double x, double y, double *dest_x, double *dest_y) { // find the closest x point if (x < box->x) { @@ -27,13 +27,12 @@ void wlr_box_closest_point(struct wlr_box *box, double x, double y, } } -bool wlr_box_empty(struct wlr_box *box) { +bool wlr_box_empty(const struct wlr_box *box) { return box == NULL || box->width <= 0 || box->height <= 0; } -bool wlr_box_intersection(struct wlr_box *box_a, - struct wlr_box *box_b, struct wlr_box **box_dest) { - struct wlr_box *dest = *box_dest; +bool wlr_box_intersection(const struct wlr_box *box_a, + const struct wlr_box *box_b, struct wlr_box *dest) { bool a_empty = wlr_box_empty(box_a); bool b_empty = wlr_box_empty(box_b); @@ -58,7 +57,7 @@ bool wlr_box_intersection(struct wlr_box *box_a, return !wlr_box_empty(dest); } -bool wlr_box_contains_point(struct wlr_box *box, double x, double y) { +bool wlr_box_contains_point(const struct wlr_box *box, double x, double y) { if (wlr_box_empty(box)) { return false; } else { @@ -67,7 +66,7 @@ bool wlr_box_contains_point(struct wlr_box *box, double x, double y) { } } -void wlr_box_transform(struct wlr_box *box, +void wlr_box_transform(const struct wlr_box *box, enum wl_output_transform transform, struct wlr_box *dest) { if (transform % 2 == 0) { dest->width = box->width; diff --git a/types/wlr_output.c b/types/wlr_output.c index 46db98b3..c76f85f5 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -555,9 +555,8 @@ static void output_cursor_update_visible(struct wlr_output_cursor *cursor) { output_cursor_get_box(cursor, &cursor_box); struct wlr_box intersection; - struct wlr_box *intersection_ptr = &intersection; bool visible = - wlr_box_intersection(&output_box, &cursor_box, &intersection_ptr); + wlr_box_intersection(&output_box, &cursor_box, &intersection); if (cursor->surface != NULL) { if (cursor->visible && !visible) { diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index a6942655..5b2dee8c 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -230,30 +230,38 @@ bool wlr_output_layout_contains_point(struct wlr_output_layout *layout, } bool wlr_output_layout_intersects(struct wlr_output_layout *layout, - struct wlr_output *reference, int x1, int y1, int x2, int y2) { - struct wlr_output_layout_output *layout_output = - wlr_output_layout_get(layout, reference); - if (!layout_output) { - return false; - } + struct wlr_output *reference, const struct wlr_box *target_box) { + struct wlr_box out_box; - struct wlr_box *output_box = wlr_output_layout_output_get_box(layout_output); - struct wlr_box target_box = {x1, y1, x2 - x1, y2 - y1}; + if (reference == NULL) { + struct wlr_output_layout_output *l_output; + wl_list_for_each(l_output, &layout->outputs, link) { + struct wlr_box *output_box = + wlr_output_layout_output_get_box(l_output); + if (wlr_box_intersection(output_box, target_box, &out_box)) { + return true; + } + } + return false; + } else { + struct wlr_output_layout_output *l_output = + wlr_output_layout_get(layout, reference); + if (!l_output) { + return false; + } - struct wlr_box out; - struct wlr_box *out_ptr = &out; - return wlr_box_intersection(output_box, &target_box, &out_ptr); + struct wlr_box *output_box = wlr_output_layout_output_get_box(l_output); + return wlr_box_intersection(output_box, target_box, &out_box); + } } struct wlr_output *wlr_output_layout_output_at(struct wlr_output_layout *layout, double x, double y) { struct wlr_output_layout_output *l_output; wl_list_for_each(l_output, &layout->outputs, link) { - if (l_output->output) { - struct wlr_box *box = wlr_output_layout_output_get_box(l_output); - if (wlr_box_contains_point(box, x, y)) { - return l_output->output; - } + struct wlr_box *box = wlr_output_layout_output_get_box(l_output); + if (wlr_box_contains_point(box, x, y)) { + return l_output->output; } } return NULL;