mirror of
https://cagebreak.project-repo.co/cagebreak.git
synced 2026-08-21 21:14:18 +02:00
Release 1.2.0
- Add output configuration. See README.md and man pages
This commit is contained in:
parent
40e1313a12
commit
fa8d3ba144
13 changed files with 251 additions and 27 deletions
|
|
@ -148,6 +148,11 @@ ninja -C build
|
|||
|
||||
For every release after 1.0.5, hashes will be provided.
|
||||
|
||||
1.2.0
|
||||
|
||||
* sha 256: b3c6135833001a0ef600ea9628cca11f4130a524ebe748929d8f7bad034f2bf0
|
||||
* sha 512: c044a086a9f65b0d27d05e2f12a20fe5d77386fc5682991c13a1894a84804bcd337c9167235869661d6e6581133521bd710ef2330066a5d2e2703d1630042f3f
|
||||
|
||||
1.1.0
|
||||
|
||||
* sha 256: fc393e225c549f893b9e21e8b904e546d5857bac1d905b3d26334c8f8a1cda11
|
||||
|
|
@ -210,6 +215,10 @@ Adds basic tiling window manager functionality to cage.
|
|||
|
||||
Unifies commands and actions. See Issue 4 in Bugs.md.
|
||||
|
||||
### Release 1.2.0
|
||||
|
||||
Adds output configuration as described in the man pages.
|
||||
|
||||
## License
|
||||
|
||||
Please see [LICENSE](https://github.com/project-repo/cagebreak/blob/master/LICENSE)
|
||||
|
|
|
|||
16
cagebreak.c
16
cagebreak.c
|
|
@ -310,6 +310,8 @@ main(int argc, char *argv[]) {
|
|||
goto end;
|
||||
}
|
||||
|
||||
wl_list_init(&server.output_config);
|
||||
|
||||
renderer = wlr_backend_get_renderer(backend);
|
||||
wlr_renderer_init_wl_display(renderer, server.wl_display);
|
||||
|
||||
|
|
@ -509,6 +511,13 @@ main(int argc, char *argv[]) {
|
|||
free(config_file);
|
||||
}
|
||||
|
||||
{
|
||||
struct cg_output *output;
|
||||
wl_list_for_each(output, &server.outputs, link) {
|
||||
output_configure(&server, output);
|
||||
}
|
||||
}
|
||||
|
||||
/* Place the cursor to the topl left of the output layout. */
|
||||
wlr_cursor_warp(server.seat->cursor, NULL, 0, 0);
|
||||
|
||||
|
|
@ -526,6 +535,13 @@ end:
|
|||
}
|
||||
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_remove(&output_config->link);
|
||||
free(output_config->output_name);
|
||||
free(output_config);
|
||||
}
|
||||
|
||||
keybinding_list_free(server.keybindings);
|
||||
wl_event_source_remove(sigint_source);
|
||||
wl_event_source_remove(sigterm_source);
|
||||
|
|
|
|||
|
|
@ -70,3 +70,8 @@ definekey top XF86AudioLowerVolume exec pactl set-sink-mute 0 off&&amixer set Ma
|
|||
definekey top XF86AudioRaiseVolume exec pactl set-sink-mute 0 off&&amixer set Master 1%+
|
||||
definekey top XF86MonBrightnessDown exec xbacklight -dec 1
|
||||
definekey top XF86MonBrightnessUp exec xbacklight -inc 1
|
||||
|
||||
######################
|
||||
#Output configuration
|
||||
######################
|
||||
#output eDP-1 pos 0 0 res 1366x768 rate 60
|
||||
|
|
|
|||
|
|
@ -8,10 +8,13 @@
|
|||
|
||||
#define _POSIX_C_SOURCE 200812L
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include "../keybinding.h"
|
||||
#include "../parse.h"
|
||||
#include "../seat.h"
|
||||
#include "../server.h"
|
||||
#include "../output.h"
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -47,18 +50,18 @@
|
|||
#include <wlr/xwayland.h>
|
||||
#endif
|
||||
|
||||
#include "idle_inhibit_v1.h"
|
||||
#include "keybinding.h"
|
||||
#include "message.h"
|
||||
#include "output.h"
|
||||
#include "parse.h"
|
||||
#include "seat.h"
|
||||
#include "server.h"
|
||||
#include "view.h"
|
||||
#include "workspace.h"
|
||||
#include "xdg_shell.h"
|
||||
#include "../idle_inhibit_v1.h"
|
||||
#include "../keybinding.h"
|
||||
#include "../message.h"
|
||||
#include "../output.h"
|
||||
#include "../parse.h"
|
||||
#include "../seat.h"
|
||||
#include "../server.h"
|
||||
#include "../view.h"
|
||||
#include "../workspace.h"
|
||||
#include "../xdg_shell.h"
|
||||
#if CG_HAS_XWAYLAND
|
||||
#include "xwayland.h"
|
||||
#include "../xwayland.h"
|
||||
#endif
|
||||
|
||||
#ifndef WAIT_ANY
|
||||
|
|
@ -197,6 +200,8 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
|
|||
goto end;
|
||||
}
|
||||
|
||||
wl_list_init(&server.output_config);
|
||||
|
||||
renderer = wlr_backend_get_renderer(backend);
|
||||
wlr_renderer_init_wl_display(renderer, server.wl_display);
|
||||
|
||||
|
|
@ -443,5 +448,13 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||
}
|
||||
server.modes[3] = NULL;
|
||||
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_remove(&output_config->link);
|
||||
free(output_config->output_name);
|
||||
free(output_config);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
% CAGEBREAK-CONFIG(1) Version 1.1 | Cagebreak Manual
|
||||
% CAGEBREAK-CONFIG(1) Version 1.2 | Cagebreak Manual
|
||||
|
||||
# NAME
|
||||
|
||||
|
|
@ -131,6 +131,13 @@ by prepending a line with the # symbol.
|
|||
|
||||
> Remove all splits and make the current window fill the entire screen
|
||||
|
||||
**output <name> pos <xpos> <ypos> res <width>x<height> rate <rate>**
|
||||
|
||||
> Configure the output "<name>". <xpos> and <ypos> are the position of the monitor
|
||||
> in pixels. The top-left monitor should have the coordinates 0 0. <width> and
|
||||
> <height> specify the resolution in pixels and <rate> sets the refresh rate of
|
||||
> the monitor (often this is 50 or 60).
|
||||
|
||||
**prev**
|
||||
|
||||
> Focus previous window in current tile
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
% CAGEBREAK(1) Version 1.1 | Cagebreak Manual
|
||||
% CAGEBREAK(1) Version 1.2 | Cagebreak Manual
|
||||
|
||||
# NAME
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
project('cagebreak', 'c',
|
||||
version: '1.1.0',
|
||||
version: '1.2.0',
|
||||
license: 'MIT',
|
||||
default_options: [
|
||||
'c_std=c11',
|
||||
|
|
@ -10,7 +10,6 @@ project('cagebreak', 'c',
|
|||
add_project_arguments(
|
||||
[
|
||||
'-DWLR_USE_UNSTABLE',
|
||||
'-Wall',
|
||||
'-Wundef',
|
||||
'-Wno-unused-parameter',
|
||||
],
|
||||
|
|
@ -188,7 +187,7 @@ reproducible_build_versions = {
|
|||
'wlroots': '0.10.1',
|
||||
'xkbcommon': '0.10.0',
|
||||
'fontconfig': '2.13.91',
|
||||
'pixman': '0.38.4',
|
||||
'pixman': '0.40.0',
|
||||
'pango': '1.44.7',
|
||||
'cairo': '1.17.3',
|
||||
'pangocairo': '1.44.7',
|
||||
|
|
|
|||
75
output.c
75
output.c
|
|
@ -480,6 +480,72 @@ 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 *config;
|
||||
wl_list_for_each(config, &server->output_config, link) {
|
||||
if(strcmp(config->output_name, output->name) == 0) {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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)) {
|
||||
wlr_log(WLR_DEBUG, "Assigning custom mode to %s", output->name);
|
||||
wlr_output_set_custom_mode(output, width, height,
|
||||
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) {
|
||||
best = mode;
|
||||
break;
|
||||
}
|
||||
if (best == NULL || mode->refresh > best->refresh) {
|
||||
best = mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 {
|
||||
wlr_log(WLR_DEBUG, "Assigning configured mode to %s", output->name);
|
||||
}
|
||||
wlr_output_set_mode(output, best);
|
||||
}
|
||||
|
||||
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);
|
||||
if(output->wlr_output->enabled) {
|
||||
wlr_output_layout_remove(server->output_layout, wlr_output);
|
||||
}
|
||||
|
||||
if(config == NULL) {
|
||||
wlr_output_layout_add_auto(server->output_layout, wlr_output);
|
||||
|
||||
struct wlr_output_mode *preferred_mode =
|
||||
wlr_output_preferred_mode(wlr_output);
|
||||
if(preferred_mode) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_new_output(struct wl_listener *listener, void *data) {
|
||||
struct cg_server *server = wl_container_of(listener, server, new_output);
|
||||
|
|
@ -508,7 +574,8 @@ 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);
|
||||
wlr_output_layout_add_auto(server->output_layout, wlr_output);
|
||||
|
||||
output_configure(server, output);
|
||||
|
||||
output->workspaces = malloc(server->nws * sizeof(struct cg_workspace *));
|
||||
for(unsigned int i = 0; i < server->nws; ++i) {
|
||||
|
|
@ -520,12 +587,6 @@ handle_new_output(struct wl_listener *listener, void *data) {
|
|||
output->curr_workspace = 0;
|
||||
wl_list_init(&output->messages);
|
||||
|
||||
struct wlr_output_mode *preferred_mode =
|
||||
wlr_output_preferred_mode(wlr_output);
|
||||
if(preferred_mode) {
|
||||
wlr_output_set_mode(wlr_output, preferred_mode);
|
||||
}
|
||||
|
||||
if(wlr_xcursor_manager_load(server->seat->xcursor_manager,
|
||||
wlr_output->scale)) {
|
||||
wlr_log(WLR_ERROR,
|
||||
|
|
|
|||
11
output.h
11
output.h
|
|
@ -2,13 +2,13 @@
|
|||
#define CG_OUTPUT_H
|
||||
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_box.h>
|
||||
|
||||
struct cg_server;
|
||||
struct cg_view;
|
||||
struct wlr_output;
|
||||
struct wlr_output_damage;
|
||||
struct wlr_surface;
|
||||
struct wlr_box;
|
||||
|
||||
struct cg_output {
|
||||
struct cg_server *server;
|
||||
|
|
@ -27,6 +27,13 @@ struct cg_output {
|
|||
struct wl_list link; // cg_server::outputs
|
||||
};
|
||||
|
||||
struct cg_output_config {
|
||||
struct wlr_box pos;
|
||||
char* output_name;
|
||||
float refresh_rate;
|
||||
struct wl_list link;// cg_server::output_config
|
||||
};
|
||||
|
||||
typedef void (*cg_surface_iterator_func_t)(struct cg_output *output,
|
||||
struct wlr_surface *surface,
|
||||
struct wlr_box *box,
|
||||
|
|
@ -35,6 +42,8 @@ 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);
|
||||
void
|
||||
output_surface_for_each_surface(struct cg_output *output,
|
||||
struct wlr_surface *surface, double ox,
|
||||
double oy, cg_surface_iterator_func_t iterator,
|
||||
|
|
|
|||
103
parse.c
103
parse.c
|
|
@ -3,6 +3,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "keybinding.h"
|
||||
#include "output.h"
|
||||
|
|
@ -192,6 +193,104 @@ parse_workspaces(char **saveptr) {
|
|||
return nws;
|
||||
}
|
||||
|
||||
int
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
long uint = strtol(uint_str, NULL, 10);
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
float ufloat = strtof(uint_str, NULL);
|
||||
if(ufloat >= 0) {
|
||||
return ufloat;
|
||||
} else {
|
||||
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));
|
||||
char *name = strtok_r(NULL, " ", saveptr);
|
||||
if(name == NULL) {
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
goto error;
|
||||
}
|
||||
|
||||
cfg->output_name = strdup(name);
|
||||
wl_list_insert(config_list, &cfg->link);
|
||||
return 0;
|
||||
|
||||
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>");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
parse_command(struct cg_server *server, struct keybinding *keybinding,
|
||||
char *saveptr) {
|
||||
|
|
@ -380,6 +479,10 @@ parse_command(struct cg_server *server, struct keybinding *keybinding,
|
|||
if(keybinding->data.i < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else if(strcmp(action, "output") == 0) {
|
||||
if(parse_output_config(&server->output_config, &saveptr) != 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Error, unsupported action \"%s\".", action);
|
||||
return -1;
|
||||
|
|
|
|||
2
server.h
2
server.h
|
|
@ -11,6 +11,7 @@ struct cg_output;
|
|||
struct keybinding_list;
|
||||
struct wlr_output_layout;
|
||||
struct wlr_idle_inhibit_manager_v1;
|
||||
struct cg_output_config;
|
||||
|
||||
struct cg_server {
|
||||
struct wl_display *wl_display;
|
||||
|
|
@ -35,6 +36,7 @@ struct cg_server {
|
|||
#endif
|
||||
|
||||
struct keybinding_list *keybindings;
|
||||
struct wl_list output_config;
|
||||
|
||||
enum wl_output_transform output_transform;
|
||||
|
||||
|
|
|
|||
BIN
signatures/1.1.0.sig
Normal file
BIN
signatures/1.1.0.sig
Normal file
Binary file not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue