mirror of
https://cagebreak.project-repo.co/cagebreak.git
synced 2026-08-09 15:19:11 +02:00
Merge branch 'output_config' of https://github.com/project-repo/cagebreak into output_config
This commit is contained in:
commit
27fa2b70b9
8 changed files with 221 additions and 8 deletions
16
cagebreak.c
16
cagebreak.c
|
|
@ -307,6 +307,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);
|
||||
|
||||
|
|
@ -506,6 +508,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);
|
||||
|
||||
|
|
@ -523,6 +532,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
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "../parse.h"
|
||||
#include "../seat.h"
|
||||
#include "../server.h"
|
||||
#include "../output.h"
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -58,6 +59,7 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
|
|||
/* new_xwayland_surface */
|
||||
server.keybindings = keybinding_list_init();
|
||||
server.output_transform = 0;
|
||||
wl_list_init(&server.output_config);
|
||||
|
||||
server.running = true;
|
||||
server.modes = malloc(sizeof(char *));
|
||||
|
|
@ -82,5 +84,13 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||
free(str);
|
||||
keybinding_list_free(server.keybindings);
|
||||
server.keybindings = keybinding_list_init();
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,6 +182,13 @@ by prepending a line with the # symbol.
|
|||
|
||||
> Enter mode "`<mode>`". After a keybinding is processed, return to default mode
|
||||
|
||||
**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).
|
||||
|
||||
**setmode <mode>**
|
||||
|
||||
> Set the default mode to `<mode>`
|
||||
|
|
|
|||
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"
|
||||
|
|
@ -343,6 +344,104 @@ parse_definemode(char ***modes, char **saveptr) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
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_rc_line(struct cg_server *server, char *line) {
|
||||
char *saveptr = NULL; // Used internally by strtok_r
|
||||
|
|
@ -374,6 +473,10 @@ parse_rc_line(struct cg_server *server, char *line) {
|
|||
if(parse_and_run_exec(&saveptr) != 0) {
|
||||
return -1;
|
||||
}
|
||||
} else if(strcmp(command, "output") == 0) {
|
||||
if(parse_output_config(&server->output_config, &saveptr) != 0) {
|
||||
return -1;
|
||||
}
|
||||
} else if(strcmp(command, "workspaces") == 0) {
|
||||
char *nws_str = strtok_r(NULL, " ", &saveptr);
|
||||
if(nws_str == NULL) {
|
||||
|
|
|
|||
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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue