Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

Commit

Permalink
Add relative layouts to rootston
Browse files Browse the repository at this point in the history
In order to properly manage relative layouts in rootston, the
'wlr_output_layout' has been encapsulated in 'roots_layout'. This is
primarily to deal with outputs not being available to reference. This
lives in rootston since compositors might want to deal differently with
missing outputs.

The behavior of rootston in the case of missign outputs, is to mark
rules whose relative output is not available as unconfigured. When an
output is unconfigured it will be placed to the right of any other outputs.
This way, no gaps will occur in the layout, unless the user
specifically configures them with fixed output.

This commit adds the possibility to switch layouts at runtime trough
the commnd 'next_layout'.
  • Loading branch information
VincentVanlaer committed May 28, 2018
1 parent 67a2d6e commit f97aa49
Show file tree
Hide file tree
Showing 14 changed files with 482 additions and 48 deletions.
16 changes: 15 additions & 1 deletion include/rootston/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ struct roots_output_config {
char *name;
bool enable;
enum wl_output_transform transform;
int x, y;
float scale;
struct wl_list link;
struct {
Expand All @@ -19,6 +18,20 @@ struct roots_output_config {
} mode;
};

struct roots_layout_config {
char *name;
struct wl_list link;
struct wl_list rules;
};

struct roots_layout_rule_config {
char *output_name;
struct wl_list link;
enum wlr_output_layout_output_configuration configuration;
char *reference_output;
int x, y;
};

struct roots_device_config {
char *name;
char *seat;
Expand Down Expand Up @@ -67,6 +80,7 @@ struct roots_config {
struct wl_list bindings;
struct wl_list keyboards;
struct wl_list cursors;
struct wl_list layouts;

char *config_path;
char *startup_cmd;
Expand Down
3 changes: 2 additions & 1 deletion include/rootston/desktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "rootston/config.h"
#include "rootston/output.h"
#include "rootston/view.h"
#include "rootston/layout.h"

struct roots_desktop {
struct wl_list views; // roots_view::link
Expand All @@ -34,8 +35,8 @@ struct roots_desktop {

struct roots_server *server;
struct roots_config *config;
struct roots_layout *layout;

struct wlr_output_layout *layout;
struct wlr_xcursor_manager *xcursor_manager;

struct wlr_compositor *compositor;
Expand Down
31 changes: 31 additions & 0 deletions include/rootston/layout.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef ROOTSTON_LAYOUT_H
#define ROOTSTON_LAYOUT_H

#include <wlr/types/wlr_output_layout.h>
#include "rootston/config.h"
#include "rootston/output.h"

struct roots_layout_rule {
struct roots_layout_rule_config *config;
struct roots_output *output;
struct wl_list link;
bool configured;
};

struct roots_layout {
struct wlr_output_layout *wlr_layout;
struct roots_layout_config *current_config;
struct wl_list rules;
};

struct roots_layout* roots_layout_create(struct roots_layout_config *config);
void roots_layout_destroy(struct roots_layout *layout);
void roots_layout_add_output(struct roots_layout *layout,
struct roots_output *output);
void roots_layout_remove_output(struct roots_layout *layout,
struct roots_output *output);
void roots_layout_reflow(struct roots_layout *layout);
void roots_layout_reconfigure(struct roots_layout *layout,
struct roots_layout_config *config);

#endif
100 changes: 96 additions & 4 deletions rootston/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,79 @@ static void config_handle_keyboard(struct roots_config *config,
}
}

static void config_handle_layout(struct roots_config *config,
const char *layout_name, const char *name, const char *value) {
struct roots_layout_config *lc;
bool found = false;
wl_list_for_each(lc, &config->layouts, link) {
if (strcmp(lc->name, layout_name) == 0) {
found = true;
break;
}
}

if (!found) {
lc = calloc(1, sizeof(struct roots_layout_config));
lc->name = strdup(layout_name);
wl_list_insert(&config->layouts, &lc->link);
wl_list_init(&lc->rules);
}

char *mod_value = strdup(value);
char *strstart = mod_value;
char *saveptr;
mod_value = strtok_r(mod_value, " ", &saveptr);

struct roots_layout_rule_config *rule =
calloc(1, sizeof(struct roots_layout_rule_config));
wl_list_insert(&lc->rules, &rule->link);
rule->output_name = strdup(name);

if (strcmp(mod_value, "fixed") == 0) {
mod_value = strtok_r(NULL, " ", &saveptr);
rule->x = strtol(mod_value, NULL, 10);
mod_value = strtok_r(NULL, " ", &saveptr);
rule->y = strtol(mod_value, NULL, 10);
rule->configuration =
WLR_OUTPUT_LAYOUT_OUTPUT_CONFIGURATION_FIXED;
} else if (strcmp(mod_value, "left-of") == 0) {
mod_value = strtok_r(NULL, " ", &saveptr);
rule->reference_output = strdup(mod_value);
rule->configuration =
WLR_OUTPUT_LAYOUT_OUTPUT_CONFIGURATION_RELATIVE_LEFT_OF;
} else if (strcmp(mod_value, "right-of") == 0) {
mod_value = strtok_r(NULL, " ", &saveptr);
rule->reference_output = strdup(mod_value);
rule->configuration =
WLR_OUTPUT_LAYOUT_OUTPUT_CONFIGURATION_RELATIVE_RIGHT_OF;
} else if (strcmp(mod_value, "below") == 0) {
mod_value = strtok_r(NULL, " ", &saveptr);
rule->reference_output = strdup(mod_value);
rule->configuration =
WLR_OUTPUT_LAYOUT_OUTPUT_CONFIGURATION_RELATIVE_BELOW;
} else if (strcmp(mod_value, "above") == 0) {
mod_value = strtok_r(NULL, " ", &saveptr);
rule->reference_output = strdup(mod_value);
rule->configuration =
WLR_OUTPUT_LAYOUT_OUTPUT_CONFIGURATION_RELATIVE_ABOVE;
} else if (strcmp(mod_value, "same-as") == 0) {
mod_value = strtok_r(NULL, " ", &saveptr);
rule->reference_output = strdup(mod_value);
rule->configuration =
WLR_OUTPUT_LAYOUT_OUTPUT_CONFIGURATION_RELATIVE_SAME_AS;
} else {
wlr_log(L_ERROR, "got invalid input for layout %s: %s = %s",
layout_name, name, value);
}

free(strstart);
}

static const char *output_prefix = "output:";
static const char *device_prefix = "device:";
static const char *keyboard_prefix = "keyboard:";
static const char *cursor_prefix = "cursor:";
static const char *layout_prefix = "layout:";

static int config_ini_handler(void *user, const char *section, const char *name,
const char *value) {
Expand Down Expand Up @@ -280,10 +349,6 @@ static int config_ini_handler(void *user, const char *section, const char *name,
} else {
wlr_log(L_ERROR, "got invalid output enable value: %s", value);
}
} else if (strcmp(name, "x") == 0) {
oc->x = strtol(value, NULL, 10);
} else if (strcmp(name, "y") == 0) {
oc->y = strtol(value, NULL, 10);
} else if (strcmp(name, "scale") == 0) {
oc->scale = strtof(value, NULL);
assert(oc->scale > 0);
Expand Down Expand Up @@ -376,6 +441,12 @@ static int config_ini_handler(void *user, const char *section, const char *name,
section, strlen(keyboard_prefix)) == 0) {
const char *device_name = section + strlen(keyboard_prefix);
config_handle_keyboard(config, device_name, name, value);
} else if (strcmp(section, "layout") == 0) {
config_handle_layout(config, "", name, value);
} else if (strncmp(layout_prefix,
section, strlen(layout_prefix)) == 0) {
const char *layout_name = section + strlen(layout_prefix);
config_handle_layout(config, layout_name, name, value);
} else if (strcmp(section, "bindings") == 0) {
add_binding_config(&config->bindings, name, value);
} else {
Expand All @@ -398,6 +469,7 @@ struct roots_config *roots_config_create_from_args(int argc, char *argv[]) {
wl_list_init(&config->keyboards);
wl_list_init(&config->cursors);
wl_list_init(&config->bindings);
wl_list_init(&config->layouts);

int c;
while ((c = getopt(argc, argv, "C:E:hD")) != -1) {
Expand Down Expand Up @@ -453,6 +525,14 @@ struct roots_config *roots_config_create_from_args(int argc, char *argv[]) {
exit(1);
}

if (wl_list_empty(&config->layouts)) {
struct roots_layout_config *layout =
calloc(1, sizeof(struct roots_layout_config));
layout->name = strdup("default");
wl_list_init(&layout->rules);
wl_list_insert(&config->layouts, &layout->link);
}

return config;
}

Expand Down Expand Up @@ -500,6 +580,18 @@ void roots_config_destroy(struct roots_config *config) {
free(bc);
}

struct roots_layout_config *lc, *ltmp = NULL;
struct roots_layout_rule_config *lrc, *lrtmp = NULL;
wl_list_for_each_safe(lc, ltmp, &config->layouts, link) {
wl_list_for_each_safe(lrc, lrtmp, &lc->rules, link) {
free(lrc->output_name);
free(lrc->reference_output);
free(lrc);
}
free(lc->name);
free(kc);
}

free(config->config_path);
free(config);
}
Expand Down
43 changes: 24 additions & 19 deletions rootston/desktop.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ static void view_update_output(const struct roots_view *view,
struct roots_output *output;
wl_list_for_each(output, &desktop->outputs, link) {
bool intersected = before != NULL && wlr_output_layout_intersects(
desktop->layout, output->wlr_output, before);
bool intersects = wlr_output_layout_intersects(desktop->layout,
output->wlr_output, &box);
desktop->layout->wlr_layout, output->wlr_output, before);
bool intersects = wlr_output_layout_intersects(
desktop->layout->wlr_layout, output->wlr_output, &box);
if (intersected && !intersects) {
wlr_surface_send_leave(view->wlr_surface, output->wlr_output);
}
Expand Down Expand Up @@ -184,12 +184,12 @@ static struct wlr_output *view_get_output(struct roots_view *view) {
view_get_box(view, &view_box);

double output_x, output_y;
wlr_output_layout_closest_point(view->desktop->layout, NULL,
wlr_output_layout_closest_point(view->desktop->layout->wlr_layout, NULL,
view->x + (double)view_box.width/2,
view->y + (double)view_box.height/2,
&output_x, &output_y);
return wlr_output_layout_output_at(view->desktop->layout, output_x,
output_y);
return wlr_output_layout_output_at(view->desktop->layout->wlr_layout,
output_x, output_y);
}

void view_arrange_maximized(struct roots_view *view) {
Expand All @@ -199,7 +199,7 @@ void view_arrange_maximized(struct roots_view *view) {
struct wlr_output *output = view_get_output(view);
struct roots_output *roots_output = output->data;
struct wlr_box *output_box =
wlr_output_layout_get_box(view->desktop->layout, output);
wlr_output_layout_get_box(view->desktop->layout->wlr_layout, output);
struct wlr_box usable_area;
memcpy(&usable_area, &roots_output->usable_area,
sizeof(struct wlr_box));
Expand Down Expand Up @@ -274,7 +274,7 @@ void view_set_fullscreen(struct roots_view *view, bool fullscreen,
view->saved.height = view_box.height;

struct wlr_box *output_box =
wlr_output_layout_get_box(view->desktop->layout, output);
wlr_output_layout_get_box(view->desktop->layout->wlr_layout, output);
view_move_resize(view, output_box->x, output_box->y, output_box->width,
output_box->height);
view_rotate(view, 0);
Expand Down Expand Up @@ -332,7 +332,7 @@ bool view_center(struct roots_view *view) {
}

struct wlr_output *output =
wlr_output_layout_output_at(desktop->layout,
wlr_output_layout_output_at(desktop->layout->wlr_layout,
seat->cursor->cursor->x,
seat->cursor->cursor->y);
if (!output) {
Expand All @@ -341,7 +341,7 @@ bool view_center(struct roots_view *view) {
}

const struct wlr_output_layout_output *l_output =
wlr_output_layout_get(desktop->layout, output);
wlr_output_layout_get(desktop->layout->wlr_layout, output);

int width, height;
wlr_output_effective_resolution(output, &width, &height);
Expand Down Expand Up @@ -615,7 +615,7 @@ static struct roots_view *desktop_view_at(struct roots_desktop *desktop,
double lx, double ly, struct wlr_surface **surface,
double *sx, double *sy) {
struct wlr_output *wlr_output =
wlr_output_layout_output_at(desktop->layout, lx, ly);
wlr_output_layout_output_at(desktop->layout->wlr_layout, lx, ly);
if (wlr_output != NULL) {
struct roots_output *output =
desktop_output_from_wlr_output(desktop, wlr_output);
Expand Down Expand Up @@ -660,7 +660,7 @@ struct wlr_surface *desktop_surface_at(struct roots_desktop *desktop,
struct roots_view **view) {
struct wlr_surface *surface = NULL;
struct wlr_output *wlr_output =
wlr_output_layout_output_at(desktop->layout, lx, ly);
wlr_output_layout_output_at(desktop->layout->wlr_layout, lx, ly);
struct roots_output *roots_output = NULL;
double ox = lx, oy = ly;
if (view) {
Expand All @@ -669,7 +669,7 @@ struct wlr_surface *desktop_surface_at(struct roots_desktop *desktop,

if (wlr_output) {
roots_output = wlr_output->data;
wlr_output_layout_output_coords(desktop->layout, wlr_output, &ox, &oy);
wlr_output_layout_output_coords(desktop->layout->wlr_layout, wlr_output, &ox, &oy);

if ((surface = layer_surface_at(roots_output,
&roots_output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
Expand Down Expand Up @@ -711,13 +711,13 @@ static void handle_layout_change(struct wl_listener *listener, void *data) {
wl_container_of(listener, desktop, layout_change);

struct wlr_output *center_output =
wlr_output_layout_get_center_output(desktop->layout);
wlr_output_layout_get_center_output(desktop->layout->wlr_layout);
if (center_output == NULL) {
return;
}

struct wlr_box *center_output_box =
wlr_output_layout_get_box(desktop->layout, center_output);
wlr_output_layout_get_box(desktop->layout->wlr_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;

Expand All @@ -726,7 +726,8 @@ static void handle_layout_change(struct wl_listener *listener, void *data) {
struct wlr_box box;
view_get_box(view, &box);

if (wlr_output_layout_intersects(desktop->layout, NULL, &box)) {
if (wlr_output_layout_intersects(desktop->layout->wlr_layout, NULL,
&box)) {
continue;
}

Expand Down Expand Up @@ -771,10 +772,14 @@ struct roots_desktop *desktop_create(struct roots_server *server,
desktop->server = server;
desktop->config = config;

desktop->layout = wlr_output_layout_create();
wlr_xdg_output_manager_create(server->wl_display, desktop->layout);
struct roots_layout_config *default_layout;

wl_list_for_each(default_layout, &config->layouts, link) { break; }

desktop->layout = roots_layout_create(default_layout);
wlr_xdg_output_manager_create(server->wl_display, desktop->layout->wlr_layout);
desktop->layout_change.notify = handle_layout_change;
wl_signal_add(&desktop->layout->events.change, &desktop->layout_change);
wl_signal_add(&desktop->layout->wlr_layout->events.change, &desktop->layout_change);

desktop->compositor = wlr_compositor_create(server->wl_display,
server->renderer);
Expand Down
17 changes: 17 additions & 0 deletions rootston/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "rootston/input.h"
#include "rootston/keyboard.h"
#include "rootston/seat.h"
#include "rootston/layout.h"

static ssize_t pressed_keysyms_index(xkb_keysym_t *pressed_keysyms,
xkb_keysym_t keysym) {
Expand Down Expand Up @@ -133,6 +134,22 @@ static void keyboard_binding_execute(struct roots_keyboard *keyboard,
wl_list_for_each(output, &keyboard->input->server->desktop->outputs, link) {
wlr_output_enable(output->wlr_output, outputs_enabled);
}
} else if (strcmp(command, "next_layout") == 0) {
struct roots_desktop *desktop = keyboard->input->server->desktop;
struct wl_list *next = desktop->layout->current_config->link.next;

if (next == &desktop->config->layouts) {
next = next->next;
}

struct roots_layout_config *config =
wl_container_of(next, desktop->layout->current_config, link);

wlr_log(L_DEBUG, "Switching to layout %s", config->name);

roots_layout_reconfigure(desktop->layout, config);
roots_layout_reflow(desktop->layout);

} else {
wlr_log(L_ERROR, "unknown binding command: %s", command);
}
Expand Down
Loading

0 comments on commit f97aa49

Please sign in to comment.