Add support for disabling outputs

This commit is contained in:
project-repo 2021-01-09 09:17:59 +01:00
commit b2193f4c1d
7 changed files with 103 additions and 37 deletions

View file

@ -335,6 +335,7 @@ main(int argc, char *argv[]) {
server.bg_color = (float[4]){0, 0, 0, 1};
wl_list_init(&server.outputs);
wl_list_init(&server.disabled_outputs);
server.output_layout = wlr_output_layout_create();
if(!server.output_layout) {
@ -544,8 +545,9 @@ main(int argc, char *argv[]) {
}
{
struct cg_output *output;
wl_list_for_each(output, &server.outputs, link) {
struct cg_output *output, *output_tmp;
wl_list_for_each_safe(output, output_tmp, &server.outputs, link) {
output_configure(&server, output);
}
}

View file

@ -838,6 +838,20 @@ keybinding_configure_output(struct cg_server *server,
}
}
wl_list_insert(&server->output_config, &cfg->link);
struct cg_output *output, *tmp_output;
wl_list_for_each_safe(output, tmp_output, &server->outputs, link) {
if(strcmp(cfg->output_name, output->wlr_output->name) == 0) {
output_configure(server, output);
return;
}
}
wl_list_for_each_safe(output, tmp_output, &server->disabled_outputs, link) {
if(strcmp(cfg->output_name, output->wlr_output->name) == 0) {
output_configure(server, output);
return;
}
}
}
/* Hint: see keybinding.h for details on "data" */

View file

@ -364,7 +364,7 @@ static void
handle_output_transform(struct wl_listener *listener, void *data) {
struct cg_output *output = wl_container_of(listener, output, transform);
if(!output->wlr_output->enabled) {
if(!output->wlr_output->enabled || output->workspaces==NULL) {
return;
}
@ -379,7 +379,7 @@ static void
handle_output_mode(struct wl_listener *listener, void *data) {
struct cg_output *output = wl_container_of(listener, output, mode);
if(!output->wlr_output->enabled) {
if(!output->wlr_output->enabled || output->workspaces==NULL) {
return;
}
@ -390,22 +390,15 @@ handle_output_mode(struct wl_listener *listener, void *data) {
}
}
static void
output_destroy(struct cg_output *output) {
struct cg_server *server = output->server;
wl_list_remove(&output->destroy.link);
wl_list_remove(&output->mode.link);
wl_list_remove(&output->transform.link);
wl_list_remove(&output->damage_frame.link);
wl_list_remove(&output->damage_destroy.link);
void output_clear(struct cg_output* output) {
struct cg_server *server=output->server;
wlr_output_layout_remove(server->output_layout, output->wlr_output);
if(server->running && server->curr_output == output &&
wl_list_length(&server->outputs) > 1) {
keybinding_cycle_outputs(server, false);
}
wl_list_remove(&output->link);
message_clear(output);
@ -413,6 +406,13 @@ output_destroy(struct cg_output *output) {
struct cg_view *view, *view_tmp;
if(server->running) {
for(unsigned int i = 0; i < server->nws; ++i) {
bool first = true;
for(struct cg_tile *tile = output->workspaces[i]->focused_tile;
first || output->workspaces[i]->focused_tile != tile; tile = tile->next) {
first = false;
tile->view=NULL;
}
wl_list_for_each_safe(view, view_tmp, &output->workspaces[i]->views,
link) {
wl_list_remove(&view->link);
@ -451,6 +451,20 @@ output_destroy(struct cg_output *output) {
}
}
}
static void
output_destroy(struct cg_output *output) {
struct cg_server *server = output->server;
wl_list_remove(&output->destroy.link);
wl_list_remove(&output->mode.link);
wl_list_remove(&output->transform.link);
wl_list_remove(&output->damage_frame.link);
wl_list_remove(&output->damage_destroy.link);
output_clear(output);
/*Important: due to unfortunate events, "workspace" and "output->workspace"
* have nothing in common. The former is the workspace of a single output,
* whereas the latter is the workspace of the outputs.*/
@ -530,11 +544,15 @@ void
output_configure(struct cg_server *server, struct cg_output *output) {
struct wlr_output *wlr_output = output->wlr_output;
struct cg_output_config *config = output_find_config(server, wlr_output);
/* Refuse to disable the only output */
if(config!=NULL&&config->status == OUTPUT_DISABLE && wl_list_length(&server->outputs)==1) {
return;
}
if(output->wlr_output->enabled) {
wlr_output_layout_remove(server->output_layout, wlr_output);
}
if(config == NULL) {
if(config == NULL || config->status == OUTPUT_ENABLE) {
wlr_output_layout_add_auto(server->output_layout, wlr_output);
struct wlr_output_mode *preferred_mode =
@ -542,11 +560,24 @@ output_configure(struct cg_server *server, struct cg_output *output) {
if(preferred_mode) {
wlr_output_set_mode(wlr_output, preferred_mode);
}
wl_list_remove(&output->link);
wl_list_insert(&server->outputs,&output->link);
wlr_output_enable(wlr_output, true);
wlr_output_commit(wlr_output);
} else if(config->status == OUTPUT_DISABLE) {
output_clear(output);
wl_list_insert(&server->disabled_outputs,&output->link);
wlr_output_enable(wlr_output, false);
wlr_output_commit(wlr_output);
} else {
wl_list_remove(&output->link);
wl_list_insert(&server->outputs,&output->link);
output_set_mode(wlr_output, config->pos.width, config->pos.height,
config->refresh_rate);
wlr_output_layout_add(server->output_layout, wlr_output, config->pos.x,
config->pos.y);
wlr_output_enable(wlr_output, true);
wlr_output_commit(wlr_output);
}
}
@ -569,7 +600,6 @@ handle_new_output(struct wl_listener *listener, void *data) {
output->server = server;
output->damage = wlr_output_damage_create(wlr_output);
output->last_scanned_out_view = NULL;
wl_list_insert(&server->outputs, &output->link);
output->mode.notify = handle_output_mode;
wl_signal_add(&wlr_output->events.mode, &output->mode);
@ -583,19 +613,7 @@ handle_new_output(struct wl_listener *listener, void *data) {
wl_signal_add(&output->damage->events.destroy, &output->damage_destroy);
wlr_output_set_transform(wlr_output, server->output_transform);
output_configure(server, output);
output->workspaces = malloc(server->nws * sizeof(struct cg_workspace *));
for(unsigned int i = 0; i < server->nws; ++i) {
output->workspaces[i] = full_screen_workspace(output);
if(!output->workspaces[i]) {
wlr_log(WLR_ERROR, "Failed to allocate workspaces for output");
return;
}
wl_list_init(&output->workspaces[i]->views);
wl_list_init(&output->workspaces[i]->unmanaged_views);
}
output->workspaces=NULL;
output->curr_workspace = 0;
wl_list_init(&output->messages);
@ -607,14 +625,12 @@ handle_new_output(struct wl_listener *listener, void *data) {
wlr_output->name, wlr_output->scale);
}
wl_list_insert(&server->outputs, &output->link);
output_configure(server, output);
wlr_output_damage_add_whole(output->damage);
wlr_output_enable(wlr_output, true);
wlr_output_commit(wlr_output);
/* TODO:If you see a way to circumvent having to loop twice, please do so */
output->workspaces = malloc(server->nws * sizeof(struct cg_workspace *));
for(unsigned int i = 0; i < server->nws; ++i) {
workspace_free(output->workspaces[i]);
output->workspaces[i] = full_screen_workspace(output);
if(!output->workspaces[i]) {
wlr_log(WLR_ERROR, "Failed to allocate workspaces for output");

View file

@ -28,7 +28,14 @@ struct cg_output {
struct wl_list link; // cg_server::outputs
};
enum output_status {
OUTPUT_ENABLE,
OUTPUT_DISABLE,
OUTPUT_DEFAULT
};
struct cg_output_config {
enum output_status status;
struct wlr_box pos;
char *output_name;
float refresh_rate;

27
parse.c
View file

@ -259,6 +259,23 @@ parse_float(char **saveptr, const char *delim) {
}
}
int
parse_output_config_keyword(char *key_str,enum output_status *status) {
if(key_str == NULL) {
return -1;
}
if(strcmp(key_str,"pos") == 0) {
*status=OUTPUT_DEFAULT;
} else if(strcmp(key_str, "enable") == 0) {
*status=OUTPUT_ENABLE;
} else if(strcmp(key_str, "disable") == 0) {
*status=OUTPUT_DISABLE;
} else {
return -1;
}
return 0;
}
struct cg_output_config *
parse_output_config(char **saveptr, char **errstr) {
struct cg_output_config *cfg = malloc(sizeof(struct cg_output_config));
@ -273,13 +290,17 @@ parse_output_config(char **saveptr, char **errstr) {
log_error("Expected name of output to be configured, got none");
goto error;
}
char *pos_str = strtok_r(NULL, " ", saveptr);
if(pos_str == NULL || strcmp(pos_str, "pos") != 0) {
char *key_str = strtok_r(NULL, " ", saveptr);
if(parse_output_config_keyword(key_str,&(cfg->status))!=0) {
*errstr = log_error(
"Expected keyword \"pos\" in output configuration for output %s",
"Expected keyword \"pos\", \"enable\" or \"disable\" in output configuration for output %s",
name);
goto error;
}
if(cfg->status == OUTPUT_ENABLE || cfg->status == OUTPUT_DISABLE) {
cfg->output_name = strdup(name);
return cfg;
}
cfg->pos.x = parse_uint(saveptr, " ");
if(cfg->pos.x < 0) {

5
seat.c
View file

@ -54,6 +54,11 @@ view_at(const struct cg_view *view, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
struct wlr_box *output_layout_box = wlr_output_layout_get_box(
view->server->output_layout, view->workspace->output->wlr_output);
if(output_layout_box == NULL) {
fprintf(stderr, "OUTPUT:%d\n",view->workspace->output->wlr_output->enabled);
return output_layout_box->x;
return false;
}
double view_sx = lx - view->ox - output_layout_box->x;
double view_sy = ly - view->oy - output_layout_box->y;

View file

@ -26,6 +26,7 @@ struct cg_server {
struct wl_list inhibitors;
struct wlr_output_layout *output_layout;
struct wl_list disabled_outputs;
struct wl_list outputs;
struct cg_output *curr_output;
struct wl_listener new_output;