Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions doc/way-displays.1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.\" Automatically generated by Pandoc 3.2
.\" Automatically generated by Pandoc 3.1.12.1
.\"
.TH "WAY\-DISPLAYS" "1" "2025/02/24" "way\-displays" "User Manuals"
.TH "WAY\-DISPLAYS" "1" "2025/03/28" "way\-displays" "User Manuals"
.SH NAME
way\-displays \- Auto Manage Your Wayland Displays
.SH SYNOPSIS
Expand Down Expand Up @@ -186,6 +186,23 @@ Enable a display.
Remove command on display configuration success.
.RE
.TP
\f[CR]\-t\f[R], \f[CR]\-\-t[oggle]\f[R]
Toggle a setting.
.RS
.TP
\f[CR]SCALING\f[R]
Toggle scaling.
.TP
\f[CR]AUTO_SCALE\f[R]
Toggle auto scaling.
.TP
\f[CR]VRR_OFF\f[R] <\f[I]name\f[R]>
Toggle VRR for a display.
.TP
\f[CR]DISABLED\f[R] <\f[I]name\f[R]>
Toggle a display.
.RE
.TP
\f[CR]\-w\f[R] | \f[CR]\-\-w[rite]\f[R]
Write active configuration to cfg.yaml; removes any whitespace or comments.
.SH NAMING
Expand Down
17 changes: 16 additions & 1 deletion doc/way-displays.1.pandoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
% WAY-DISPLAYS(1) way-displays | User Manuals
% Alexander Courtis
% 2025/02/24
% 2025/03/28

# NAME

Expand Down Expand Up @@ -150,6 +150,21 @@ User should be a member of the `input` group for querying laptop lid state.
`CALLBACK_CMD` <*shell command*>
: Remove command on display configuration success.

`-t`, `--t[oggle]`
: Toggle a setting.

`SCALING`
: Toggle scaling.

`AUTO_SCALE`
: Toggle auto scaling.

`VRR_OFF` <*name*>
: Toggle VRR for a display.

`DISABLED` <*name*>
: Toggle a display.

`-w` | `--w[rite]`
: Write active configuration to cfg.yaml; removes any whitespace or comments.

Expand Down
4 changes: 3 additions & 1 deletion inc/cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stdbool.h>
#include <stdint.h>
#include "log.h"
#include "ipc.h"

#define AUTO_SCALE_MIN_DEFAULT 1.0f
#define AUTO_SCALE_MAX_DEFAULT -1.0f
Expand Down Expand Up @@ -108,7 +109,7 @@ void cfg_init_path(const char *cfg_path);

bool cfg_equal(struct Cfg *a, struct Cfg *b);

struct Cfg *cfg_merge(struct Cfg *to, struct Cfg *from, bool del);
struct Cfg *cfg_merge(struct Cfg *to, struct Cfg *from, enum IpcCommand command);

void cfg_file_reload(void);

Expand Down Expand Up @@ -148,6 +149,7 @@ void cfg_file_paths_destroy(void);
// visible for testing
//
struct Cfg *merge_set(struct Cfg *to, struct Cfg *from);
struct Cfg *merge_toggle(struct Cfg *to, struct Cfg *from);
struct Cfg *merge_del(struct Cfg *to, struct Cfg *from);
void validate_warn(struct Cfg *cfg);
void validate_fix(struct Cfg *cfg);
Expand Down
1 change: 1 addition & 0 deletions inc/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ struct Cfg *parse_element(enum IpcCommand command, enum CfgElement element, int
struct IpcRequest *parse_write(int argc, char **argv);
struct IpcRequest *parse_set(int argc, char **argv);
struct IpcRequest *parse_del(int argc, char **argv);
struct IpcRequest *parse_toggle(int argc, char **argv);
enum LogThreshold parse_log_threshold(char *optarg);

#endif // CLI_H
3 changes: 2 additions & 1 deletion inc/ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ enum IpcCommand {
CFG_SET,
CFG_DEL,
CFG_WRITE,
CFG_TOGGLE,
};

struct IpcOperation {
Expand All @@ -31,7 +32,7 @@ struct IpcOperation {
struct IpcRequest {
enum IpcCommand command;
enum LogThreshold log_threshold; // server marshals >=
struct Cfg *cfg; // for CFG_SET, CFG_DEL
struct Cfg *cfg; // for CFG_SET, CFG_DEL, CFG_TOGGLE
bool yaml; // client print yaml only bar errors
int socket_client; // client and server, set to -1 on failure
bool bad; // used by server on receipt of bad message
Expand Down
8 changes: 8 additions & 0 deletions lib/col/inc/fn.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ bool fn_comp_equals_strcmp(const void* const a, const void* const b);
// true if both NULL or strstr(a, b)
bool fn_comp_equals_strstr(const void* const a, const void* const b);

// copies a string using strdup, if val is NULL, returns NULL
void *fn_copy_strdup(const void* const val);

//
// a < b
//
Expand All @@ -29,5 +32,10 @@ typedef bool (*fn_test)(const void* const val);
//
typedef void (*fn_free_val)(const void* const val);

//
// copy
//
typedef void* (*fn_copy_val)(const void* const val);

#endif // FN_H

3 changes: 3 additions & 0 deletions lib/col/inc/slist.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ size_t slist_remove_all(struct SList **head, fn_equals, const void *b);
// remove items and free vals, NULL equals is val pointer comparison, NULL fn_free_val calls free()
size_t slist_remove_all_free(struct SList **head, fn_equals, const void *b, fn_free_val);

// merges list2 into list1, such that the resulting list contains only elements that appeared exclusively in list1 or list2.
size_t slist_xor_free(struct SList **head1, struct SList *head2, fn_equals, fn_free_val, fn_copy_val);

/*
* Access
*/
Expand Down
7 changes: 7 additions & 0 deletions lib/col/src/fn.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,10 @@ bool fn_comp_equals_strstr(const void* const a, const void* const b) {

return strstr(a, b);
}

void *fn_copy_strdup(const void* const val) {
if (val == NULL)
return NULL;

return strdup(val);
}
21 changes: 21 additions & 0 deletions lib/col/src/slist.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,27 @@ size_t slist_remove_all_free(struct SList **head, fn_equals equals, const void *
return removed;
}

size_t slist_xor_free(struct SList **head1, struct SList *head2, fn_equals equals, fn_free_val free_val, fn_copy_val copy_val) {
struct SList *i = head2;
size_t removed = 0;

while (i) {
size_t removed = slist_remove_all_free(head1, equals, i->val, free_val);

if (!removed) {
if (copy_val) {
slist_append(head1, copy_val(i->val));
} else {
slist_append(head1, i->val);
}
}

i = i->nex;
}

return removed;
}

void *slist_at(struct SList *head, size_t index) {
size_t c = 0;
for (struct SList *i = head; i; i = i->nex, c++) {
Expand Down
45 changes: 38 additions & 7 deletions src/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@
#include "convert.h"
#include "global.h"
#include "info.h"
#include "ipc.h"
#include "mode.h"
#include "slist.h"
#include "log.h"
#include "marshalling.h"

static enum OnOff on_off_invert(enum OnOff val) {
return (val == ON) ? OFF : ON;
}

static void cfg_free_paths(struct Cfg *cfg) {
if (!cfg)
return;
Expand Down Expand Up @@ -241,11 +246,9 @@ static struct Cfg *clone_cfg(struct Cfg *from) {
}

// AUTO_SCALE
if (from->auto_scale) {
to->auto_scale = from->auto_scale;
to->auto_scale_min = from->auto_scale_min;
to->auto_scale_max = from->auto_scale_max;
}
to->auto_scale = from->auto_scale;
to->auto_scale_min = from->auto_scale_min;
to->auto_scale_max = from->auto_scale_max;

// SCALE
for (i = from->user_scales; i; i = i->nex) {
Expand Down Expand Up @@ -727,15 +730,43 @@ struct Cfg *merge_del(struct Cfg *to, struct Cfg *from) {
return merged;
}

struct Cfg *cfg_merge(struct Cfg *to, struct Cfg *from, bool del) {
struct Cfg *merge_toggle(struct Cfg *to, struct Cfg *from) {
if (!to || !from) {
return NULL;
}

struct Cfg *merged = clone_cfg(to);

// SCALE
if (from->scaling == ON) {
merged->scaling = on_off_invert(merged->scaling);
}

// AUTO_SCALE
if (from->auto_scale == ON) {
merged->auto_scale = on_off_invert(merged->auto_scale);
}

// DISABLED
slist_xor_free(&merged->disabled_name_desc, from->disabled_name_desc, fn_comp_equals_strcmp, NULL, fn_copy_strdup);

// VRR_OFF
slist_xor_free(&merged->adaptive_sync_off_name_desc, from->adaptive_sync_off_name_desc, fn_comp_equals_strcmp, NULL, fn_copy_strdup);

return merged;
}

struct Cfg *cfg_merge(struct Cfg *to, struct Cfg *from, enum IpcCommand command) {
if (!to || !from) {
return NULL;
}

struct Cfg *merged = NULL;

if (del) {
if (command == CFG_DEL) {
merged = merge_del(to, from);
} else if (command == CFG_TOGGLE) {
merged = merge_toggle(to, from);
} else {
merged = merge_set(to, from);
}
Expand Down
53 changes: 52 additions & 1 deletion src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ static void usage(FILE *stream) {
" DISABLED <name>\n"
" VRR_OFF <name>\n"
" CALLBACK_CMD <shell command>\n"
" -t, --t[toggle] toggle parameter\n"
" SCALING\n"
" AUTO_SCALE\n"
" DISABLED <name>\n"
" VRR_OFF <name>\n"
" -d, --d[elete] remove\n"
" SCALE <name>\n"
" MODE <name>\n"
Expand All @@ -67,9 +72,19 @@ struct Cfg *parse_element(enum IpcCommand command, enum CfgElement element, int
parsed = parsed && (cfg->align = align_val_start(argv[optind + 1]));
break;
case SCALING:
if (command == CFG_TOGGLE) {
cfg->scaling = ON;
parsed = true;
break;
}
parsed = (cfg->scaling = on_off_val(argv[optind]));
break;
case AUTO_SCALE:
if (command == CFG_TOGGLE) {
cfg->auto_scale = ON;
parsed = true;
break;
}
parsed = (cfg->auto_scale = on_off_val(argv[optind]));
break;
case SCALE:
Expand Down Expand Up @@ -303,6 +318,38 @@ struct IpcRequest *parse_del(int argc, char **argv) {
return request;
}

struct IpcRequest *parse_toggle(int argc, char **argv) {
enum CfgElement element = cfg_element_val(optarg);
switch (element) {
case SCALING:
case AUTO_SCALE:
if (optind != argc) {
log_fatal("%s takes no arguments", cfg_element_name(element));
wd_exit(EXIT_FAILURE);
return NULL;
}
break;
case VRR_OFF:
case DISABLED:
if (optind + 1 != argc) {
log_fatal("%s requires one argument", cfg_element_name(element));
wd_exit(EXIT_FAILURE);
return NULL;
}
break;
default:
log_fatal("invalid %s: %s", ipc_command_friendly(CFG_TOGGLE), element ? cfg_element_name(element) : optarg);
wd_exit(EXIT_FAILURE);
return NULL;
}

struct IpcRequest *request = calloc(1, sizeof(struct IpcRequest));
request->command = CFG_TOGGLE;
request->cfg = parse_element(CFG_TOGGLE, element, argc, argv);

return request;
}

enum LogThreshold parse_log_threshold(char *optarg) {
enum LogThreshold threshold = log_threshold_val(optarg);

Expand All @@ -322,12 +369,13 @@ void parse_args(int argc, char **argv, struct IpcRequest **ipc_request, char **c
{ "help", no_argument, 0, 'h' },
{ "log-threshold", required_argument, 0, 'L' },
{ "set", required_argument, 0, 's' },
{ "toggle", required_argument, 0, 't' },
{ "version", no_argument, 0, 'v' },
{ "write", no_argument, 0, 'w' },
{ "yaml", no_argument, 0, 'y' },
{ 0, 0, 0, 0 }
};
static char *short_options = "c:d:ghL:s:vwy";
static char *short_options = "c:d:ghL:s:t:vwy";

bool yaml = false;
enum LogThreshold threshold = 0;
Expand Down Expand Up @@ -369,6 +417,9 @@ void parse_args(int argc, char **argv, struct IpcRequest **ipc_request, char **c
case 'd':
*ipc_request = parse_del(argc, argv);
break;
case 't':
*ipc_request = parse_toggle(argc, argv);
break;
case 'w':
*ipc_request = parse_write(argc, argv);
break;
Expand Down
11 changes: 6 additions & 5 deletions src/convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,12 @@ static struct NameVal on_offs[] = {
};

static struct NameVal ipc_commands[] = {
{ .val = GET, .name = "GET", .friendly = "get", },
{ .val = CFG_SET, .name = "CFG_SET", .friendly = "set", },
{ .val = CFG_DEL, .name = "CFG_DEL", .friendly = "delete", },
{ .val = CFG_WRITE, .name = "CFG_WRITE", .friendly = "write", },
{ .val = 0, .name = NULL, .friendly = NULL, },
{ .val = GET, .name = "GET", .friendly = "get", },
{ .val = CFG_SET, .name = "CFG_SET", .friendly = "set", },
{ .val = CFG_DEL, .name = "CFG_DEL", .friendly = "delete", },
{ .val = CFG_WRITE, .name = "CFG_WRITE", .friendly = "write", },
{ .val = CFG_TOGGLE, .name = "CFG_TOGGLE", .friendly = "toggle", },
{ .val = 0, .name = NULL, .friendly = NULL, },
};

static struct NameVal transforms[] = {
Expand Down
3 changes: 2 additions & 1 deletion src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ static void receive_ipc_request(int server_socket) {
switch (ipc_request->command) {
case CFG_DEL:
case CFG_SET:
case CFG_TOGGLE:
{
struct Cfg *cfg_merged = cfg_merge(cfg, ipc_request->cfg, ipc_request->command == CFG_DEL);
struct Cfg *cfg_merged = cfg_merge(cfg, ipc_request->cfg, ipc_request->command);
if (cfg_merged) {
// ongoing
ipc_operation->done = false;
Expand Down
Loading