Skip to content

Commit

Permalink
WIP: Atomic layout updates ground work
Browse files Browse the repository at this point in the history
  • Loading branch information
RyanDwyer committed Jun 3, 2018
1 parent fb932cf commit 50f2180
Show file tree
Hide file tree
Showing 16 changed files with 690 additions and 266 deletions.
56 changes: 56 additions & 0 deletions include/sway/desktop/transaction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#ifndef _SWAY_TRANSACTION_H
#define _SWAY_TRANSACTION_H
#include "sway/tree/container.h"

/**
* Transactions enable us to perform atomic layout updates.
*
* When we want to make adjustments to the layout, we create a transaction.
* A transaction contains a list of affected containers and their new state.
* A state might contain a new size, or new border settings, or new parent/child
* relationships.
*
* Calling transaction_commit() makes sway notify of all the affected clients
* with their new sizes. We then wait for all the views to respond with their
* new surface sizes. When all are ready, or when a timeout has passed, we apply
* the updates all at the same time.
*/

struct sway_transaction {
struct wl_event_source *timer;
list_t *instructions; // struct sway_transaction_instruction *
list_t *damage; // struct wlr_box *
size_t num_waiting;
};

/**
* Create a new transaction.
*/
struct sway_transaction *transaction_create(void);

/**
* Add a container's pending state to the transaction.
*/
void transaction_add_container(struct sway_transaction *transaction,
struct sway_container *container);

/**
* Add a box to be damaged when the transaction is applied.
* The box should be in layout coordinates.
*/
void transaction_add_damage(struct sway_transaction *transaction,
struct wlr_box *box);

/**
* Submit a transaction to the client views for configuration.
*/
void transaction_commit(struct sway_transaction *transaction);

/**
* Notify the transaction system that a view is ready for the new layout.
*
* When all views in the transaction are ready, the layout will be applied.
*/
void transaction_notify_view_ready(struct sway_view *view, uint32_t serial);

#endif
2 changes: 2 additions & 0 deletions include/sway/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ void output_damage_surface(struct sway_output *output, double ox, double oy,
void output_damage_from_view(struct sway_output *output,
struct sway_view *view);

void output_damage_box(struct sway_output *output, struct wlr_box *box);

void output_damage_whole_container(struct sway_output *output,
struct sway_container *con);

Expand Down
33 changes: 24 additions & 9 deletions include/sway/tree/arrange.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
#ifndef _SWAY_ARRANGE_H
#define _SWAY_ARRANGE_H
#include "sway/desktop/transaction.h"

struct sway_container;

// Determine the root container's geometry, then iterate to everything below
void arrange_root(void);

// Determine the output's geometry, then iterate to everything below
void arrange_output(struct sway_container *output);
/**
* Arrange layout for all the children of the given container, and add them to
* the given transaction.
*
* Use this function if you need to arrange multiple sections of the tree in one
* transaction.
*/
void arrange_windows(struct sway_container *container,
struct sway_transaction *transaction);

// Determine the workspace's geometry, then iterate to everything below
void arrange_workspace(struct sway_container *workspace);
/**
* Arrange layout for the given container and commit the transaction.
*
* This function is a wrapper around arrange_windows, and handles creating and
* committing the transaction for you. Use this function if you're only doing
* one arrange operation.
*/
void arrange_and_commit(struct sway_container *container);

// Arrange layout for all the children of the given workspace/container
void arrange_children_of(struct sway_container *parent);
// These functions are temporary and are only here to make everything compile.
// They are wrappers around arrange_and_commit.
void arrange_root(void);
void arrange_output(struct sway_container *container);
void arrange_workspace(struct sway_container *container);
void arrange_children_of(struct sway_container *container);

#endif
29 changes: 29 additions & 0 deletions include/sway/tree/container.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,28 @@ struct sway_output;
struct sway_workspace;
struct sway_view;

struct sway_container_state {
// Container/swayc properties
enum sway_container_layout layout;
double swayc_x, swayc_y;
double swayc_width, swayc_height;

//struct sway_container *parent;
//list_t *children;

// View properties
double view_x, view_y;
double view_width, view_height;
bool is_fullscreen;

enum sway_container_border border;
int border_thickness;
bool border_top;
bool border_bottom;
bool border_left;
bool border_right;
};

struct sway_container {
union {
// TODO: Encapsulate state for other node types as well like C_CONTAINER
Expand All @@ -69,6 +91,8 @@ struct sway_container {
*/
size_t id;

struct sway_container_state pending;

char *name; // The view's title (unformatted)
char *formatted_title; // The title displayed in the title bar

Expand Down Expand Up @@ -246,4 +270,9 @@ void container_set_geometry_from_floating_view(struct sway_container *con);
*/
bool container_is_floating(struct sway_container *container);

/**
* Get a container's box in layout coordinates.
*/
struct wlr_box *container_get_box(struct sway_container *container);

#endif
19 changes: 9 additions & 10 deletions include/sway/tree/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ struct sway_view_impl {
const char *(*get_string_prop)(struct sway_view *view,
enum sway_view_prop prop);
uint32_t (*get_int_prop)(struct sway_view *view, enum sway_view_prop prop);
void (*configure)(struct sway_view *view, double lx, double ly, int width,
int height);
uint32_t (*configure)(struct sway_view *view, double lx, double ly,
int width, int height);
void (*set_activated)(struct sway_view *view, bool activated);
void (*set_fullscreen)(struct sway_view *view, bool fullscreen);
bool (*wants_floating)(struct sway_view *view);
Expand Down Expand Up @@ -70,6 +70,12 @@ struct sway_view {

list_t *executed_criteria; // struct criteria *
list_t *marks; // char *
list_t *instructions; // struct sway_transaction_instruction *

// If saved_texture is set, the main surface of the view will render this
// texture instead of its own. This is used while waiting for transactions
// to complete.
struct wlr_texture *saved_texture;

struct wlr_texture *marks_focused;
struct wlr_texture *marks_focused_inactive;
Expand Down Expand Up @@ -103,8 +109,6 @@ struct sway_xdg_shell_v6_view {
struct wl_listener map;
struct wl_listener unmap;
struct wl_listener destroy;

int pending_width, pending_height;
};

struct sway_xdg_shell_view {
Expand All @@ -119,8 +123,6 @@ struct sway_xdg_shell_view {
struct wl_listener map;
struct wl_listener unmap;
struct wl_listener destroy;

int pending_width, pending_height;
};

struct sway_xwayland_view {
Expand All @@ -138,9 +140,6 @@ struct sway_xwayland_view {
struct wl_listener map;
struct wl_listener unmap;
struct wl_listener destroy;

int pending_lx, pending_ly;
int pending_width, pending_height;
};

struct sway_xwayland_unmanaged {
Expand Down Expand Up @@ -212,7 +211,7 @@ uint32_t view_get_window_type(struct sway_view *view);

const char *view_get_shell(struct sway_view *view);

void view_configure(struct sway_view *view, double ox, double oy, int width,
uint32_t view_configure(struct sway_view *view, double lx, double ly, int width,
int height);

/**
Expand Down
70 changes: 63 additions & 7 deletions sway/desktop/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ struct render_data {
struct root_geometry root_geo;
struct sway_output *output;
pixman_region32_t *damage;
struct sway_view *view;
float alpha;
};

Expand Down Expand Up @@ -108,6 +109,38 @@ static bool get_surface_box(struct root_geometry *geo,
return wlr_box_intersection(&output_box, &rotated_box, &intersection);
}

static bool get_view_box(struct root_geometry *geo,
struct sway_output *output, struct sway_view *view, int sx, int sy,
struct wlr_box *surface_box) {
int sw = view->width;
int sh = view->height;

double _sx = sx, _sy = sy;
rotate_child_position(&_sx, &_sy, sw, sh, geo->width, geo->height,
geo->rotation);

struct wlr_box box = {
.x = geo->x + _sx,
.y = geo->y + _sy,
.width = sw,
.height = sh,
};
if (surface_box != NULL) {
memcpy(surface_box, &box, sizeof(struct wlr_box));
}

struct wlr_box rotated_box;
wlr_box_rotated_bounds(&box, geo->rotation, &rotated_box);

struct wlr_box output_box = {
.width = output->swayc->width,
.height = output->swayc->height,
};

struct wlr_box intersection;
return wlr_box_intersection(&output_box, &rotated_box, &intersection);
}

static void surface_for_each_surface(struct wlr_surface *surface,
double ox, double oy, struct root_geometry *geo,
wlr_surface_iterator_func_t iterator, void *user_data) {
Expand Down Expand Up @@ -225,13 +258,26 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy,
pixman_region32_t *output_damage = data->damage;
float alpha = data->alpha;

if (!wlr_surface_has_buffer(surface)) {
return;
struct wlr_texture *texture = NULL;
struct wlr_box box;
bool intersects;

// If this is the main surface of a view, render the saved_texture instead
// if it exists. It exists when we are mid-transaction.
if (data->view && data->view->saved_texture &&
data->view->surface == surface) {
texture = data->view->saved_texture;
intersects = get_view_box(&data->root_geo, data->output, data->view,
sx, sy, &box);
} else {
if (!wlr_surface_has_buffer(surface)) {
return;
}
texture = surface->texture;
intersects = get_surface_box(&data->root_geo, data->output, surface,
sx, sy, &box);
}

struct wlr_box box;
bool intersects = get_surface_box(&data->root_geo, data->output, surface,
sx, sy, &box);
if (!intersects) {
return;
}
Expand All @@ -244,8 +290,7 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy,
wlr_matrix_project_box(matrix, &box, transform, rotation,
wlr_output->transform_matrix);

render_texture(wlr_output, output_damage, surface->texture, &box, matrix,
alpha);
render_texture(wlr_output, output_damage, texture, &box, matrix, alpha);
}

static void render_layer(struct sway_output *output,
Expand Down Expand Up @@ -315,6 +360,7 @@ static void render_view_surfaces(struct sway_view *view,
struct render_data data = {
.output = output,
.damage = damage,
.view = view,
.alpha = alpha,
};
output_view_for_each_surface(
Expand Down Expand Up @@ -1105,6 +1151,16 @@ void output_damage_from_view(struct sway_output *output,
output_damage_view(output, view, false);
}

// Expecting an unscaled box in layout coordinates
void output_damage_box(struct sway_output *output, struct wlr_box *_box) {
struct wlr_box box;
memcpy(&box, _box, sizeof(struct wlr_box));
box.x -= output->swayc->x;
box.y -= output->swayc->y;
scale_box(&box, output->wlr_output->scale);
wlr_output_damage_add_box(output->damage, &box);
}

static void output_damage_whole_container_iterator(struct sway_container *con,
void *data) {
struct sway_output *output = data;
Expand Down
Loading

0 comments on commit 50f2180

Please sign in to comment.