mirror of
https://cagebreak.project-repo.co/cagebreak.git
synced 2026-08-09 07:09:11 +02:00
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:
parent
fa8d3ba144
commit
e35da69b87
21 changed files with 310 additions and 60 deletions
22
Bugs.md
22
Bugs.md
|
|
@ -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.
|
||||
|
|
|
|||
39
README.md
39
README.md
|
|
@ -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
|
||||
|
|
|
|||
28
cagebreak.c
28
cagebreak.c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define CG_CONFIG_H
|
||||
|
||||
#mesondefine CG_HAS_XWAYLAND
|
||||
#mesondefine CG_HAS_FANALYZE
|
||||
|
||||
#mesondefine CG_VERSION
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
17
keybinding.c
17
keybinding.c
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
% CAGEBREAK-CONFIG(1) Version 1.2 | Cagebreak Manual
|
||||
% CAGEBREAK-CONFIG(1) Version 1.2.1 | Cagebreak Manual
|
||||
|
||||
# NAME
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
% CAGEBREAK(1) Version 1.2 | Cagebreak Manual
|
||||
% CAGEBREAK(1) Version 1.2.1 | Cagebreak Manual
|
||||
|
||||
# NAME
|
||||
|
||||
|
|
|
|||
24
meson.build
24
meson.build
|
|
@ -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,
|
||||
)
|
||||
|
||||
|
|
|
|||
22
message.c
22
message.c
|
|
@ -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,
|
||||
|
|
|
|||
47
output.c
47
output.c
|
|
@ -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) {
|
||||
|
|
|
|||
6
output.h
6
output.h
|
|
@ -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
85
parse.c
|
|
@ -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
1
seat.c
|
|
@ -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
BIN
signatures/1.2.0.sig
Normal file
Binary file not shown.
Binary file not shown.
4
view.c
4
view.c
|
|
@ -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
|
||||
|
|
|
|||
35
workspace.c
35
workspace.c
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue