Release 1.2.1

- Fix Issue 5 in Bugs.md
- Fix Issue 6 in Bugs.md
- Apply clang-format
- Introduce -fanalyzer analysis for gcc compilation
This commit is contained in:
Cagebreak Signing Key 1 2020-05-24 18:48:52 +02:00
commit e35da69b87
21 changed files with 310 additions and 60 deletions

22
Bugs.md
View file

@ -58,8 +58,8 @@ Steps to reproduce:
### Issue 4
github issue number: #1
Fixed: 1.1.0
* github issue number: #1
* Fixed: 1.1.0
This issue is code duplication in `parse.c`.
@ -79,3 +79,21 @@ PS: As a side effect, this would allow quirky statements such as
`bind dbind r hsplit` which would bind the d key to binding the r key to
split the output...
```
### Issue 5
* github issue number : N/A
* Fixed: 1.2.1
Cagebreak up to and including release 1.2.0 does not warn of irreproducibility
if a different compiler or compiler version is used. This makes cagebreak
difficult to reproduce.
### Issue 6
* github issue number : N/A
* Fixed: 1.2.1
Our fuzzing framework up to and including release 1.2.0 does not the limit line
lengths. This can crash the fuzzing framework with a segfault due to running
out of memory.

View file

@ -61,6 +61,33 @@ Nonetheless, don't be intimidated by the (slightly lengthy) release checklist or
part of this file. Do what you can, open an issue and we will collaborate
toward a solution.
### GCC and -fanalyzer
Cagebreak should compile with any reasonably new gcc or clang. Consider
a gcc version of at least [10.1](https://gcc.gnu.org/gcc-10/changes.html) if
you want to get the benefit of the brand-new
[-fanalyzer](https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html)
flag. However, this new flag sometimes produces false-postives and we
selectively disable warnings for affected code segments as described below.
Meson is configured to set `CG_HAS_FANALYZE` if `-fanalyzer` is available.
Therefore, to maintain portability, false-positive fanalyzer warnings are to be
disabled using the following syntax:
```
#if CG_HAS_FANALYZE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "WARNING OPTION"
#endif
```
and after
```
#if CG_HAS_FANALYZE
#pragma GCC diagnostic pop
#endif
```
### Branching strategy
All features are to be developed on feature branches, named after the feature.
@ -83,7 +110,8 @@ git tag -v version
git push --tags origin master
```
and a log message roughly describing the features added in the commit.
and a log message roughly describing the features added in the commit is
included.
In the past, our git history did not always reflect this scheme.
@ -93,6 +121,7 @@ Release checklist
* [ ] Cursory testing
* [ ] libfuzzer testing
* [ ] ninja -C build clang-format
* [ ] Version Number
* [ ] meson.build
* [ ] git tag
@ -135,6 +164,9 @@ decided on this compromise to allow flexibility and security. In general we will
adapt the versions to the packages available under arch linux at the time of
release.
There are reproducibility issues up to and including release `1.2.0`. See
`Issue 5` in [Bugs.md](Bugs.md).
#### Reproducible Build Instructions
All hashes and signatures are provided for the following build instructions.
@ -148,6 +180,11 @@ ninja -C build
For every release after 1.0.5, hashes will be provided.
1.2.1
* sha 256: 803f7667dc4997062f9ec95afcdca0cac68c82a7cf057cef83fe1ccfee33b8bc
* sha 512: 4d6b7efea10d190a153f893123b1715f290f4b131b490f3d23f489e2dd8edbb886001282849aad9575ad2f40375bbbded59c1cb6157115fcc14dd6a2a061b103
1.2.0
* sha 256: b3c6135833001a0ef600ea9628cca11f4130a524ebe748929d8f7bad034f2bf0

View file

@ -198,10 +198,12 @@ set_configuration(struct cg_server *server,
if(parse_rc_line(server, line) != 0) {
wlr_log(WLR_ERROR, "Error in config file \"%s\", line %d\n",
config_file_path, line_num);
fclose(config_file);
return -1;
}
}
}
fclose(config_file);
return 0;
}
@ -218,6 +220,10 @@ get_config_file() {
}
char *config_path = malloc(
(strlen(config_home_path) + strlen(addition) + 1) * sizeof(char));
if(!config_path) {
wlr_log(WLR_ERROR, "Failed to allocate space for configuration path");
return NULL;
}
sprintf(config_path, "%s%s", config_home_path, addition);
return config_path;
}
@ -256,6 +262,12 @@ main(int argc, char *argv[]) {
wlr_log_init(WLR_ERROR, NULL);
#endif
server.modes = malloc(4 * sizeof(char *));
if(!server.modes) {
wlr_log(WLR_ERROR, "Error allocating mode array");
return -1;
}
/* Wayland requires XDG_RUNTIME_DIR to be set. */
if(!getenv("XDG_RUNTIME_DIR")) {
wlr_log(WLR_ERROR, "XDG_RUNTIME_DIR is not set in the environment");
@ -270,11 +282,15 @@ main(int argc, char *argv[]) {
server.running = true;
server.modes = malloc(4 * sizeof(char *));
server.modes[0] = strdup("top");
server.modes[1] = strdup("root");
server.modes[2] = strdup("resize");
server.modes[3] = NULL;
if(server.modes[0] == NULL || server.modes[1] == NULL ||
server.modes[2] == NULL) {
wlr_log(WLR_ERROR, "Error allocating default modes");
goto end;
}
server.nws = 1;
server.message_timeout = 2;
@ -530,13 +546,18 @@ main(int argc, char *argv[]) {
wl_display_destroy_clients(server.wl_display);
end:
#if CG_HAS_FANALYZE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-double-free"
#endif
for(unsigned int i = 0; server.modes[i] != NULL; ++i) {
free(server.modes[i]);
}
free(server.modes);
struct cg_output_config *output_config, *output_config_tmp;
wl_list_for_each_safe(output_config, output_config_tmp, &server.output_config, link) {
wl_list_for_each_safe(output_config, output_config_tmp,
&server.output_config, link) {
wl_list_remove(&output_config->link);
free(output_config->output_name);
free(output_config);
@ -559,3 +580,6 @@ end:
return ret;
}
#if CG_HAS_FANALYZE
#pragma GCC diagnostic pop
#endif

View file

@ -2,6 +2,7 @@
#define CG_CONFIG_H
#mesondefine CG_HAS_XWAYLAND
#mesondefine CG_HAS_FANALYZE
#mesondefine CG_VERSION

View file

@ -8,12 +8,11 @@
#define _POSIX_C_SOURCE 200812L
#include "../keybinding.h"
#include "../output.h"
#include "../parse.h"
#include "../seat.h"
#include "../server.h"
#include "../output.h"
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
@ -417,9 +416,13 @@ set_configuration(struct cg_server *server, char *content) {
int
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
char *str = malloc(size * sizeof(char) + 1);
strncpy(str, (char *)data, size);
str[size] = 0;
if(size == 0) {
return 0;
}
int max_line_size = 256 > size ? size : 256;
char *str = malloc(sizeof(char) * max_line_size);
strncpy(str, (char *)data, max_line_size);
str[max_line_size - 1] = 0;
set_configuration(&server, str);
free(str);
keybinding_list_free(server.keybindings);
@ -450,7 +453,8 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
server.modes = realloc(server.modes, 4 * sizeof(char *));
struct cg_output_config *output_config, *output_config_tmp;
wl_list_for_each_safe(output_config, output_config_tmp, &server.output_config, link) {
wl_list_for_each_safe(output_config, output_config_tmp,
&server.output_config, link) {
wl_list_remove(&output_config->link);
free(output_config->output_name);
free(output_config);

View file

@ -22,6 +22,10 @@ struct cg_idle_inhibitor_v1 {
struct wl_listener destroy;
};
#if CG_HAS_FANALYZE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
#endif
static void
idle_inhibit_v1_check_active(struct cg_server *server) {
/* As of right now, this does not check whether the inhibitor
@ -29,6 +33,9 @@ idle_inhibit_v1_check_active(struct cg_server *server) {
bool inhibited = !wl_list_empty(&server->inhibitors);
wlr_idle_set_enabled(server->idle, NULL, !inhibited);
}
#if CG_HAS_FANALYZE
#pragma GCC diagnostic pop
#endif
static void
handle_destroy(struct wl_listener *listener, void *data) {

View file

@ -453,8 +453,12 @@ keybinding_workspace_fullscreen(struct cg_server *server) {
}
workspace_free_tiles(output->workspaces[output->curr_workspace]);
full_screen_workspace_tiles(output,
output->workspaces[output->curr_workspace]);
if(full_screen_workspace_tiles(
server->output_layout, output->wlr_output,
output->workspaces[output->curr_workspace]) != 0) {
wlr_log(WLR_ERROR, "Failed to allocate space for fullscreen workspace");
return;
}
seat_set_focus(server->seat, current_view);
}
@ -517,6 +521,10 @@ keybinding_split_output(struct cg_output *output, bool vertical) {
}
struct cg_tile *new_tile = calloc(1, sizeof(struct cg_tile));
if(!new_tile) {
wlr_log(WLR_ERROR, "Failed to allocate new tile for splitting");
return;
}
new_tile->tile.x = new_x;
new_tile->tile.y = new_y;
new_tile->tile.width = x + width - new_x;
@ -741,6 +749,11 @@ keybinding_set_nws(struct cg_server *server, int nws) {
output->workspaces = new_workspaces;
for(int i = server->nws; i < nws; ++i) {
output->workspaces[i] = full_screen_workspace(output);
if(!output->workspaces[i]) {
wlr_log(WLR_ERROR, "Failed to allocate additional workspaces");
return;
}
wl_list_init(&output->workspaces[i]->views);
wl_list_init(&output->workspaces[i]->unmanaged_views);
}

View file

@ -1,4 +1,4 @@
% CAGEBREAK-CONFIG(1) Version 1.2 | Cagebreak Manual
% CAGEBREAK-CONFIG(1) Version 1.2.1 | Cagebreak Manual
# NAME

View file

@ -1,4 +1,4 @@
% CAGEBREAK(1) Version 1.2 | Cagebreak Manual
% CAGEBREAK(1) Version 1.2.1 | Cagebreak Manual
# NAME

View file

@ -1,5 +1,5 @@
project('cagebreak', 'c',
version: '1.2.0',
version: '1.2.1',
license: 'MIT',
default_options: [
'c_std=c11',
@ -100,6 +100,14 @@ else
have_xwayland = false
endif
fanalyzer_compile_flag=[]
if cc.has_argument('-fanalyzer')
have_fanalyze=true
fanalyzer_compile_flag=[ '-fanalyzer' ]
else
have_fanalyze=false
endif
if get_option('version_override') != ''
version = '@0@'.format(get_option('version_override'))
else
@ -108,6 +116,7 @@ endif
conf_data = configuration_data()
conf_data.set10('CG_HAS_XWAYLAND', have_xwayland)
conf_data.set10('CG_HAS_FANALYZE', have_fanalyze)
conf_data.set_quoted('CG_VERSION', version)
@ -208,12 +217,23 @@ foreach name, dep : cagebreak_dependencies_dict
endif
endforeach
reproducible_build_compiler = 'gcc'
reproducible_build_compiler_version = '10.1.0'
if cc.get_id() != reproducible_build_compiler
warning('The compiler "' + cc.get_id() + '" differs from the one used to generate to binary specified in the README section "Reproducible Builds" (' + reproducible_build_compiler + ').')
endif
if cc.version() != reproducible_build_compiler_version
warning('The version of ' + cc.get_id() + ' (' + cc.version() + ') differs from the one used to generate the binary specified in the README section "Reproducible Builds" ' + reproducible_build_compiler_version + '.')
endif
executable(
meson.project_name(),
cagebreak_main_file + cagebreak_sources + cagebreak_headers,
dependencies: cagebreak_dependencies,
install: true,
link_args: fuzz_link_args,
link_args: fuzz_link_args+fanalyzer_compile_flag,
c_args: fuzz_compile_args,
)

View file

@ -7,6 +7,7 @@
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_output_damage.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/util/log.h>
#include "cairo.h"
#include "message.h"
@ -94,10 +95,19 @@ create_message_texture(const char *string, const struct cg_output *output) {
return texture;
}
#if CG_HAS_FANALYZE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
#endif
void
message_set_output(struct cg_output *output, const char *string,
struct wlr_box *box, enum cg_message_align align) {
struct cg_message *message = malloc(sizeof(struct cg_message));
if(!message) {
wlr_log(WLR_ERROR, "Error allocating message structure");
free(box);
return;
}
message->message = create_message_texture(string, output);
message->position = box;
wl_list_insert(&output->messages, &message->link);
@ -136,6 +146,10 @@ void
message_printf(struct cg_output *output, const char *fmt, ...) {
uint16_t buf_len = 256;
char *buffer = (char *)malloc(buf_len * sizeof(char));
if(buffer == NULL) {
wlr_log(WLR_ERROR, "Failed to allocate buffer in message_printf");
return;
}
va_list ap;
va_start(ap, fmt);
@ -143,6 +157,11 @@ message_printf(struct cg_output *output, const char *fmt, ...) {
va_end(ap);
struct wlr_box *box = malloc(sizeof(struct wlr_box));
if(box == NULL) {
wlr_log(WLR_ERROR, "Failed to allocate box in message_printf");
free(buffer);
return;
}
struct wlr_box *output_box = wlr_output_layout_get_box(
output->server->output_layout, output->wlr_output);
@ -155,6 +174,9 @@ message_printf(struct cg_output *output, const char *fmt, ...) {
free(buffer);
alarm(output->server->message_timeout);
}
#if CG_HAS_FANALYZE
#pragma GCC diagnostic pop
#endif
void
message_printf_pos(struct cg_output *output, struct wlr_box *position,

View file

@ -480,8 +480,8 @@ handle_output_destroy(struct wl_listener *listener, void *data) {
output_destroy(output);
}
struct cg_output_config*
output_find_config(struct cg_server* server, struct wlr_output* output) {
struct cg_output_config *
output_find_config(struct cg_server *server, struct wlr_output *output) {
struct cg_output_config *config;
wl_list_for_each(config, &server->output_config, link) {
if(strcmp(config->output_name, output->name) == 0) {
@ -491,31 +491,33 @@ output_find_config(struct cg_server* server, struct wlr_output* output) {
return NULL;
}
static void output_set_mode(struct wlr_output *output, int width, int height,
float refresh_rate) {
static void
output_set_mode(struct wlr_output *output, int width, int height,
float refresh_rate) {
int mhz = (int)(refresh_rate * 1000);
if (wl_list_empty(&output->modes)) {
if(wl_list_empty(&output->modes)) {
wlr_log(WLR_DEBUG, "Assigning custom mode to %s", output->name);
wlr_output_set_custom_mode(output, width, height,
refresh_rate > 0 ? mhz : 0);
refresh_rate > 0 ? mhz : 0);
return;
}
struct wlr_output_mode *mode, *best = NULL;
wl_list_for_each(mode, &output->modes, link) {
if (mode->width == width && mode->height == height) {
if (mode->refresh == mhz) {
if(mode->width == width && mode->height == height) {
if(mode->refresh == mhz) {
best = mode;
break;
}
if (best == NULL || mode->refresh > best->refresh) {
if(best == NULL || mode->refresh > best->refresh) {
best = mode;
}
}
}
if (!best) {
wlr_log(WLR_ERROR, "Configured mode for %s not available", output->name);
if(!best) {
wlr_log(WLR_ERROR, "Configured mode for %s not available",
output->name);
wlr_log(WLR_INFO, "Picking preferred mode instead");
best = wlr_output_preferred_mode(output);
} else {
@ -525,7 +527,7 @@ static void output_set_mode(struct wlr_output *output, int width, int height,
}
void
output_configure(struct cg_server* server, struct cg_output *output) {
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);
if(output->wlr_output->enabled) {
@ -541,11 +543,17 @@ output_configure(struct cg_server* server, struct cg_output *output) {
wlr_output_set_mode(wlr_output, preferred_mode);
}
} else {
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);
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);
}
}
#if CG_HAS_FANALYZE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
#endif
void
handle_new_output(struct wl_listener *listener, void *data) {
struct cg_server *server = wl_container_of(listener, server, new_output);
@ -580,6 +588,10 @@ handle_new_output(struct wl_listener *listener, void *data) {
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);
}
@ -603,6 +615,10 @@ handle_new_output(struct wl_listener *listener, void *data) {
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");
return;
}
wl_list_init(&output->workspaces[i]->views);
wl_list_init(&output->workspaces[i]->unmanaged_views);
}
@ -615,6 +631,9 @@ handle_new_output(struct wl_listener *listener, void *data) {
DEFAULT_XCURSOR, server->seat->cursor);
wlr_cursor_warp(server->seat->cursor, NULL, 0, 0);
}
#if CG_HAS_FANALYZE
#pragma GCC diagnostic pop
#endif
void
output_set_window_title(struct cg_output *output, const char *title) {

View file

@ -29,9 +29,9 @@ struct cg_output {
struct cg_output_config {
struct wlr_box pos;
char* output_name;
char *output_name;
float refresh_rate;
struct wl_list link;// cg_server::output_config
struct wl_list link; // cg_server::output_config
};
typedef void (*cg_surface_iterator_func_t)(struct cg_output *output,
@ -42,7 +42,7 @@ typedef void (*cg_surface_iterator_func_t)(struct cg_output *output,
void
handle_new_output(struct wl_listener *listener, void *data);
void
output_configure(struct cg_server* server, struct cg_output* output);
output_configure(struct cg_server *server, struct cg_output *output);
void
output_surface_for_each_surface(struct cg_output *output,
struct wlr_surface *surface, double ox,

85
parse.c
View file

@ -1,9 +1,9 @@
#define _POSIX_C_SOURCE 200812L
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <wlr/util/log.h>
#include <limits.h>
#include "keybinding.h"
#include "output.h"
@ -67,6 +67,11 @@ parse_command(struct cg_server *server, struct keybinding *keybinding,
struct keybinding *
parse_keybinding(struct cg_server *server, char **saveptr) {
struct keybinding *keybinding = malloc(sizeof(struct keybinding));
if(keybinding == NULL) {
wlr_log(WLR_ERROR,
"Failed to allocate memory for keybinding in parse_keybinding");
return NULL;
}
char *key = strtok_r(NULL, " ", saveptr);
if(parse_key(keybinding, key) != 0) {
wlr_log(WLR_ERROR, "Could not parse key definition \"%s\"", key);
@ -153,6 +158,11 @@ parse_background(struct cg_server *server, float *color, char **saveptr) {
struct keybinding *
parse_escape(char **saveptr) {
struct keybinding *keybinding = malloc(sizeof(struct keybinding));
if(keybinding == NULL) {
wlr_log(WLR_ERROR,
"Failed to allocate memory for keybinding in parse_escape");
return NULL;
}
char *key = strtok_r(NULL, " ", saveptr);
if(parse_key(keybinding, key) != 0) {
wlr_log(WLR_ERROR,
@ -194,7 +204,7 @@ parse_workspaces(char **saveptr) {
}
int
parse_uint(char **saveptr, const char* delim) {
parse_uint(char **saveptr, const char *delim) {
char *uint_str = strtok_r(NULL, delim, saveptr);
if(uint_str == NULL) {
wlr_log(WLR_ERROR, "Expected a non-negative integer, got nothing");
@ -204,13 +214,16 @@ parse_uint(char **saveptr, const char* delim) {
if(uint >= 0 && uint <= INT_MAX) {
return uint;
} else {
wlr_log(WLR_ERROR, "Error parsing non-negative integer. Must be a number larger or equal to 0 and less or equal to %d",INT_MAX);
wlr_log(WLR_ERROR,
"Error parsing non-negative integer. Must be a number larger "
"or equal to 0 and less or equal to %d",
INT_MAX);
return -1;
}
}
float
parse_float(char **saveptr, const char* delim) {
parse_float(char **saveptr, const char *delim) {
char *uint_str = strtok_r(NULL, delim, saveptr);
if(uint_str == NULL) {
wlr_log(WLR_ERROR, "Expected a non-negative float, got nothing");
@ -220,74 +233,114 @@ parse_float(char **saveptr, const char* delim) {
if(ufloat >= 0) {
return ufloat;
} else {
wlr_log(WLR_ERROR, "Error parsing non-negative float. Must be a number larger or equal to 0");
wlr_log(WLR_ERROR, "Error parsing non-negative float. Must be a number "
"larger or equal to 0");
return -1;
}
}
int
parse_output_config(struct wl_list *config_list, char **saveptr) {
struct cg_output_config* cfg = malloc(sizeof(struct cg_output_config));
struct cg_output_config *cfg = malloc(sizeof(struct cg_output_config));
if(cfg == NULL) {
wlr_log(WLR_ERROR,
"Failed to allocate memory for output configuration");
goto error;
}
char *name = strtok_r(NULL, " ", saveptr);
if(name == NULL) {
wlr_log(WLR_ERROR, "Expected name of output to be configured, got none");
wlr_log(WLR_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) {
wlr_log(WLR_ERROR, "Expected keyword \"pos\" in output configuration for output %s", name);
wlr_log(
WLR_ERROR,
"Expected keyword \"pos\" in output configuration for output %s",
name);
goto error;
}
cfg->pos.x = parse_uint(saveptr, " ");
if(cfg->pos.x < 0) {
wlr_log(WLR_ERROR, "Error parsing x coordinate of output configuration for output %s", name);
wlr_log(
WLR_ERROR,
"Error parsing x coordinate of output configuration for output %s",
name);
goto error;
}
cfg->pos.y = parse_uint(saveptr, " ");
if(cfg->pos.y < 0) {
wlr_log(WLR_ERROR, "Error parsing y coordinate of output configuration for output %s", name);
wlr_log(
WLR_ERROR,
"Error parsing y coordinate of output configuration for output %s",
name);
goto error;
}
char *res_str = strtok_r(NULL, " ", saveptr);
if(res_str == NULL || strcmp(res_str, "res") != 0) {
wlr_log(WLR_ERROR, "Expected keyword \"res\" in output configuration for output %s", name);
wlr_log(
WLR_ERROR,
"Expected keyword \"res\" in output configuration for output %s",
name);
goto error;
}
cfg->pos.width = parse_uint(saveptr, "x");
if(cfg->pos.width <= 0) {
wlr_log(WLR_ERROR, "Error parsing width of output configuration for output %s (hint: width must be larger than 0)", name);
wlr_log(WLR_ERROR,
"Error parsing width of output configuration for output %s "
"(hint: width must be larger than 0)",
name);
goto error;
}
cfg->pos.height = parse_uint(saveptr, " ");
if(cfg->pos.height <= 0) {
wlr_log(WLR_ERROR, "Error parsing height of output configuration for output %s (hint: height must e larger than 0)", name);
wlr_log(WLR_ERROR,
"Error parsing height of output configuration for output %s "
"(hint: height must e larger than 0)",
name);
goto error;
}
char *rate_str = strtok_r(NULL, " ", saveptr);
if(rate_str == NULL || strcmp(rate_str, "rate") != 0) {
wlr_log(WLR_ERROR, "Expected keyword \"rate\" in output configuration for output %s", name);
wlr_log(
WLR_ERROR,
"Expected keyword \"rate\" in output configuration for output %s",
name);
goto error;
}
cfg->refresh_rate = parse_float(saveptr, " ");
if(cfg->refresh_rate <= 0.0) {
wlr_log(WLR_ERROR, "Error parsing refresh rate of output configuration for output %s", name);
wlr_log(
WLR_ERROR,
"Error parsing refresh rate of output configuration for output %s",
name);
goto error;
}
#if CG_HAS_FANALYZE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
#endif
cfg->output_name = strdup(name);
wl_list_insert(config_list, &cfg->link);
return 0;
#if CG_HAS_FANALYZE
#pragma GCC diagnostic pop
#endif
error:
free(cfg);
wlr_log(WLR_ERROR, "Output configuration must be of the form \"output <name> pos <x> <y> res <width>x<height> rate <refresh_rate>");
wlr_log(WLR_ERROR,
"Output configuration must be of the form \"output <name> pos <x> "
"<y> res <width>x<height> rate <refresh_rate>");
return -1;
}

1
seat.c
View file

@ -794,6 +794,7 @@ handle_destroy(struct wl_listener *listener, void *_data) {
struct cg_keyboard_group *group, *group_tmp;
wl_list_for_each_safe(group, group_tmp, &seat->keyboard_groups, link) {
wl_list_remove(&group->link);
wlr_keyboard_group_destroy(group->wlr_group);
wl_event_source_remove(group->key_repeat_timer);
free(group);

BIN
signatures/1.2.0.sig Normal file

Binary file not shown.

Binary file not shown.

4
view.c
View file

@ -229,9 +229,9 @@ view_unmap(struct cg_view *view) {
if((view->type != CG_XWAYLAND_VIEW || xwayland_view_should_manage(view)))
#endif
{
if(view_is_visible(view)) {
struct cg_tile *view_tile = view_get_tile(view);
if(view_tile != NULL) {
struct cg_view *prev = view_get_prev_view(view);
struct cg_tile *view_tile = view_get_tile(view);
wlr_output_damage_add_box(view_tile->workspace->output->damage,
&view_tile->tile);
if((view->workspace->server->seat->seat->keyboard_state

View file

@ -12,6 +12,7 @@
#include <stdlib.h>
#include <wayland-server-core.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/util/log.h>
#include "message.h"
#include "output.h"
@ -19,27 +20,45 @@
#include "view.h"
#include "workspace.h"
void
full_screen_workspace_tiles(const struct cg_output *output,
#if CG_HAS_FANALYZE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
#endif
int
full_screen_workspace_tiles(struct wlr_output_layout *layout,
struct wlr_output *output,
struct cg_workspace *workspace) {
workspace->server = output->server;
workspace->focused_tile = calloc(1, sizeof(struct cg_tile));
if(!workspace->focused_tile) {
return -1;
}
workspace->focused_tile->workspace = workspace;
workspace->focused_tile->next = workspace->focused_tile;
workspace->focused_tile->prev = workspace->focused_tile;
workspace->focused_tile->tile.x = 0;
workspace->focused_tile->tile.y = 0;
struct wlr_box *output_box = wlr_output_layout_get_box(
output->server->output_layout, output->wlr_output);
struct wlr_box *output_box = wlr_output_layout_get_box(layout, output);
workspace->focused_tile->tile.width = output_box->width;
workspace->focused_tile->tile.height = output_box->height;
workspace->focused_tile->view = NULL;
return 0;
}
#if CG_HAS_FANALYZE
#pragma GCC diagnostic pop
#endif
struct cg_workspace *
full_screen_workspace(struct cg_output *output) {
struct cg_workspace *workspace = calloc(1, sizeof(struct cg_workspace));
full_screen_workspace_tiles(output, workspace);
if(!workspace) {
return NULL;
}
workspace->server = output->server;
if(full_screen_workspace_tiles(output->server->output_layout,
output->wlr_output, workspace) != 0) {
free(workspace);
return NULL;
}
workspace->output = output;
return workspace;
}
@ -48,6 +67,10 @@ void
workspace_focus_tile(struct cg_workspace *ws, struct cg_tile *tile) {
ws->focused_tile = tile;
struct wlr_box *box = malloc(sizeof(struct wlr_box));
if(!box) {
wlr_log(WLR_ERROR, "Failed to allocate box required to focus tile");
return;
}
box->x = tile->tile.x + tile->tile.width / 2;
box->y = tile->tile.y + tile->tile.height / 2;
message_printf_pos(ws->output, box, CG_MESSAGE_CENTER, "Current frame");

View file

@ -25,8 +25,9 @@ struct cg_workspace {
struct cg_workspace *
full_screen_workspace(struct cg_output *output);
void
full_screen_workspace_tiles(const struct cg_output *output,
int
full_screen_workspace_tiles(struct wlr_output_layout *layout,
struct wlr_output *output,
struct cg_workspace *workspace);
void
workspace_free_tiles(struct cg_workspace *workspace);

View file

@ -32,6 +32,10 @@ xdg_decoration_handle_destroy(struct wl_listener *listener, void *_data) {
free(xdg_decoration);
}
#if CG_HAS_FANALYZE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
#endif
static void
xdg_decoration_handle_request_mode(struct wl_listener *listener, void *_data) {
struct cg_xdg_decoration *xdg_decoration =
@ -42,6 +46,9 @@ xdg_decoration_handle_request_mode(struct wl_listener *listener, void *_data) {
wlr_xdg_toplevel_decoration_v1_set_mode(xdg_decoration->wlr_decoration,
mode);
}
#if CG_HAS_FANALYZE
#pragma GCC diagnostic pop
#endif
static void
xdg_popup_destroy(struct cg_view_child *child) {