diff --git a/cagebreak.c b/cagebreak.c index 4d1bd3b..0e3b9bb 100644 --- a/cagebreak.c +++ b/cagebreak.c @@ -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); } } diff --git a/keybinding.c b/keybinding.c index a061bc2..5c1ee9f 100644 --- a/keybinding.c +++ b/keybinding.c @@ -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" */ diff --git a/output.c b/output.c index a38d65f..38b79a1 100644 --- a/output.c +++ b/output.c @@ -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"); diff --git a/output.h b/output.h index b114176..83a79b9 100644 --- a/output.h +++ b/output.h @@ -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; diff --git a/parse.c b/parse.c index 043625b..895ed71 100644 --- a/parse.c +++ b/parse.c @@ -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) { diff --git a/seat.c b/seat.c index 7095907..5c6e379 100644 --- a/seat.c +++ b/seat.c @@ -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; diff --git a/server.h b/server.h index 24c2fb1..4e594b9 100644 --- a/server.h +++ b/server.h @@ -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;