Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#65 add ON_CHANGE_CMD to run a shell command in handle_success #162

Merged
merged 21 commits into from
Apr 20, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
bc91418
add spawn_async function
PaideiaDilemma Mar 29, 2024
7dbb2ed
add ON_CHANGE_CMD config
PaideiaDilemma Mar 29, 2024
f1a2a3d
spawn on_change_cmd in handle_success
PaideiaDilemma Mar 29, 2024
afb57ba
adapt marshalling tests
PaideiaDilemma Mar 29, 2024
cfbe233
isolate the spawed process a bit more
PaideiaDilemma Apr 1, 2024
82191fa
ignore adaptive sync changes
PaideiaDilemma Apr 2, 2024
41cd743
add a test for the change command
PaideiaDilemma Apr 2, 2024
e2f3456
add ON_CHANGE_CMD to cfg.yaml
PaideiaDilemma Apr 2, 2024
e63e344
sanitary fixes
PaideiaDilemma Apr 2, 2024
76169f3
wrap spawn_async and simplify the on_change_cmd test
PaideiaDilemma Apr 7, 2024
6a68451
fix mem leak due to creating the default config twice
PaideiaDilemma Apr 7, 2024
8a85133
rename to CHANGE_SUCCESS_CMD
PaideiaDilemma Apr 9, 2024
2b1e78d
add cli set and delete for CHANGE_SUCCESS_CMD
PaideiaDilemma Apr 9, 2024
1351215
add CHANGE_SUCCESS_CMD to print_cfg and print_cfg_commands
PaideiaDilemma Apr 9, 2024
32fa9a9
add cfg merge tests for change_success_cmd
PaideiaDilemma Apr 9, 2024
3ae2d9c
revision spawn command
PaideiaDilemma Apr 15, 2024
b490c60
add CHANGE_SUCCESS_CMD to cli usage
PaideiaDilemma Apr 15, 2024
a0264d2
add CHANGE_SUCCESS_CMD to man
alex-courtis Apr 16, 2024
afe995e
prepare for next minor release
alex-courtis Apr 16, 2024
637b104
setup signal handlers in the server to avoid zombie processes
PaideiaDilemma Apr 16, 2024
7eefc79
add compound command example, unify man and cfg.yaml
alex-courtis Apr 20, 2024
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
4 changes: 2 additions & 2 deletions doc/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ See all violations:

## Documentation

Please update `README.md` and `doc/configuration.md`.
Please update `README.md`.

Please update the man page:
* update `way-displays.1.pandoc`
Expand All @@ -83,7 +83,7 @@ Please match the style of the surrounding code and obey `.editorconfig`. Default

## Adding Options

Please add the option to `config.yaml` with a descriptive comment.
Please add the option to `cfg.yaml` with a descriptive comment.

Please add a command line option and update the usage message.

6 changes: 6 additions & 0 deletions examples/cfg.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ VRR_OFF:
# - '!.*my monitor.*'


# Sets a command to be executed when display configurations are
# successfully changed.
# NOTE: Depending on your compositor this could get executed multiple times when
# a change happens. Especially likely on a (dis-)connect.
#CHANGE_SUCCESS_CMD: 'notify-send "Monitor changed"'

# Laptop displays usually start with eDP e.g. eDP-1. This may be overridden if
# your laptop is different.
#LAPTOP_DISPLAY_PREFIX: 'eDP'
Expand Down
2 changes: 2 additions & 0 deletions inc/cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ struct Cfg {

bool updated;

char *change_success_cmd;
char *laptop_display_prefix;
struct SList *order_name_desc;
enum Arrange arrange;
Expand Down Expand Up @@ -89,6 +90,7 @@ enum CfgElement {
MODE,
TRANSFORM,
VRR_OFF,
CHANGE_SUCCESS_CMD,
LAPTOP_DISPLAY_PREFIX,
MAX_PREFERRED_REFRESH,
LOG_THRESHOLD,
Expand Down
2 changes: 2 additions & 0 deletions inc/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pid_t pid_active_server(void);

void pid_file_create(void);

void spawn_async(const char * const command);

// exit; caller should return afterwards
void wd_exit(int __status);

Expand Down
28 changes: 28 additions & 0 deletions src/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,11 @@ struct Cfg *clone_cfg(struct Cfg *from) {
slist_append(&to->adaptive_sync_off_name_desc, strdup((char*)i->val));
}

// CHANGE_SUCCESS_CMD
if (from->change_success_cmd) {
to->change_success_cmd = strdup(from->change_success_cmd);
}

// LAPTOP_DISPLAY_PREFIX
if (from->laptop_display_prefix) {
to->laptop_display_prefix = strdup(from->laptop_display_prefix);
Expand Down Expand Up @@ -345,6 +350,13 @@ bool cfg_equal(struct Cfg *a, struct Cfg *b) {
return false;
}

// CHANGE_SUCCESS_CMD
char *ao = a->change_success_cmd;
char *bo = b->change_success_cmd;
if ((ao && !bo) || (!ao && bo) || (ao && bo && strcmp(ao, bo) != 0)) {
return false;
}

// LAPTOP_DISPLAY_PREFIX
char *al = a->laptop_display_prefix;
char *bl = b->laptop_display_prefix;
Expand Down Expand Up @@ -643,6 +655,14 @@ struct Cfg *merge_set(struct Cfg *to, struct Cfg *from) {
}
}

// CHANGE_SUCCESS_CMD
if (from->change_success_cmd) {
if (merged->change_success_cmd) {
free(merged->change_success_cmd);
}
merged->change_success_cmd = strdup(from->change_success_cmd);
}

return merged;
}

Expand Down Expand Up @@ -680,6 +700,12 @@ struct Cfg *merge_del(struct Cfg *to, struct Cfg *from) {
slist_remove_all_free(&merged->disabled_name_desc, slist_predicate_strcmp, i->val, NULL);
}

// CHANGE_SUCCESS_CMD
if (from->change_success_cmd && strlen(from->change_success_cmd) == 0) {
free(merged->change_success_cmd);
merged->change_success_cmd = NULL;
}

return merged;
}

Expand Down Expand Up @@ -845,6 +871,8 @@ void cfg_free(struct Cfg *cfg) {

cfg_free_paths(cfg);

free(cfg->change_success_cmd);

free(cfg->laptop_display_prefix);

slist_free_vals(&cfg->order_name_desc, NULL);
Expand Down
21 changes: 21 additions & 0 deletions src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,19 @@ struct Cfg *parse_element(enum IpcCommand command, enum CfgElement element, int
}
parsed = true;
break;
case CHANGE_SUCCESS_CMD:
switch (command) {
case CFG_SET:
cfg->change_success_cmd = strdup(argv[optind]);
parsed = true;
break;
case CFG_DEL:
cfg->change_success_cmd = strdup("");
parsed = true;
break;
default:
break;
}
default:
break;
}
Expand Down Expand Up @@ -226,6 +239,7 @@ struct IpcRequest *parse_set(int argc, char **argv) {
case AUTO_SCALE:
case DISABLED:
case VRR_OFF:
case CHANGE_SUCCESS_CMD:
if (optind + 1 != argc) {
log_error("%s requires one argument", cfg_element_name(element));
wd_exit(EXIT_FAILURE);
Expand Down Expand Up @@ -266,6 +280,13 @@ struct IpcRequest *parse_del(int argc, char **argv) {
return NULL;
}
break;
case CHANGE_SUCCESS_CMD:
if (optind != argc) {
log_error("%s takes no arguments", cfg_element_name(element));
wd_exit(EXIT_FAILURE);
return NULL;
}
break;
default:
log_error("invalid %s: %s", ipc_command_friendly(CFG_DEL), element ? cfg_element_name(element) : optarg);
wd_exit(EXIT_FAILURE);
Expand Down
1 change: 1 addition & 0 deletions src/convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ static struct NameVal cfg_elements[] = {
{ .val = SCALE, .name = "SCALE", },
{ .val = MODE, .name = "MODE", },
{ .val = VRR_OFF, .name = "VRR_OFF", },
{ .val = CHANGE_SUCCESS_CMD, .name = "CHANGE_SUCCESS_CMD" },
{ .val = LAPTOP_DISPLAY_PREFIX, .name = "LAPTOP_DISPLAY_PREFIX", },
{ .val = MAX_PREFERRED_REFRESH, .name = "MAX_PREFERRED_REFRESH", },
{ .val = TRANSFORM, .name = "TRANSFORM", },
Expand Down
11 changes: 11 additions & 0 deletions src/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ void print_cfg(enum LogThreshold t, struct Cfg *cfg, bool del) {
}
}

if (cfg->change_success_cmd) {
log_(t, " Change success command:");
log_(t, " %s", cfg->change_success_cmd);
}

if (cfg->laptop_display_prefix) {
log_(t, " Laptop display prefix: %s", cfg->laptop_display_prefix);
}
Expand Down Expand Up @@ -293,6 +298,12 @@ void print_cfg_commands(enum LogThreshold t, struct Cfg *cfg) {
print_newline(t, &newline);
log_(t, "way-displays -s VRR_OFF '%s'", (char*)i->val);
}

newline = true;
if (cfg->change_success_cmd) {
print_newline(t, &newline);
log_(t, "way-displays -s CHANGE_SUCCESS_CMD '%s'", cfg->change_success_cmd);
}
}

void print_head_current(enum LogThreshold t, struct Head *head) {
Expand Down
9 changes: 8 additions & 1 deletion src/layout.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ void report_adaptive_sync_fail(struct Head *head) {
void handle_success(void) {
if (head_changing_mode) {

// succesful mode change is not always reported
// successful mode change is not always reported
head_changing_mode->current.mode = head_changing_mode->desired.mode;

head_changing_mode = NULL;
Expand All @@ -351,6 +351,13 @@ void handle_success(void) {
}
}

if (!head_changing_adaptive_sync && cfg->change_success_cmd) {
alex-courtis marked this conversation as resolved.
Show resolved Hide resolved
log_info("\nExecuting CHANGE_SUCCESS_CMD:");
log_info(" %s", cfg->change_success_cmd);

spawn_async(cfg->change_success_cmd);
}

log_info("\nChanges successful");
}

Expand Down
14 changes: 14 additions & 0 deletions src/marshalling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,10 @@ YAML::Emitter& operator << (YAML::Emitter& e, struct Cfg& cfg) {
e << YAML::EndSeq; // MAX_PREFERRED_REFRESH
}

if (cfg.change_success_cmd) {
e << YAML::Key << "CHANGE_SUCCESS_CMD" << YAML::Value << cfg.change_success_cmd;
}

if (cfg.laptop_display_prefix) {
e << YAML::Key << "LAPTOP_DISPLAY_PREFIX" << YAML::Value << cfg.laptop_display_prefix;
}
Expand Down Expand Up @@ -373,6 +377,14 @@ struct CfgValidated*& operator << (struct CfgValidated*& cfg_validated, const YA
}
}

if (node["CHANGE_SUCCESS_CMD"]) {
if (cfg->change_success_cmd) {
free(cfg->change_success_cmd);
}

cfg->change_success_cmd = strdup(node["CHANGE_SUCCESS_CMD"].as<std::string>().c_str());
}

if (node["LAPTOP_DISPLAY_PREFIX"]) {
if (cfg->laptop_display_prefix) {
free(cfg->laptop_display_prefix);
Expand Down Expand Up @@ -709,6 +721,8 @@ struct Cfg*& operator << (struct Cfg*& cfg, const YAML::Node& node) {
}
}

TI(cfg->change_success_cmd = strdup(node["CHANGE_SUCCESS_CMD"].as<std::string>().c_str()));

TI(cfg->laptop_display_prefix = strdup(node["LAPTOP_DISPLAY_PREFIX"].as<std::string>().c_str()));

TI(cfg->log_threshold = log_threshold_val(node["LOG_THRESHOLD"].as<std::string>().c_str()));
Expand Down
37 changes: 37 additions & 0 deletions src/process.c
alex-courtis marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stdlib.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>

#include "process.h"
Expand Down Expand Up @@ -103,6 +104,42 @@ void pid_file_create(void) {
free(path);
}

void spawn_async(const char * const command) {
pid_t pid = fork();
if (pid < 0) {
log_error_errno("\nunable to fork");
return;
}

if (pid == 0) {
// fork again to "disown"
setsid();
sigset_t mask;
sigemptyset(&mask);
sigprocmask(SIG_SETMASK, &mask, NULL);

pid_t pid2 = fork();
if (pid2 < 0) {
log_error_errno("\nunable to fork");
exit(-1);
}

if (pid2 == 0) {
// execute command in the child's child process
execl("/bin/sh", "/bin/sh", "-c", command, (char *)NULL);
log_error_errno("\nfailed to execute /bin/sh");
exit(-1);
}
// primary child exits here
exit(0);
}

// wait for the primary child to exit
if (waitpid(pid, NULL, 0) != pid) {
log_error("\nfailed to wait for child process");
};
}

void wd_exit(int __status) {
exit(__status);
}
Expand Down
2 changes: 1 addition & 1 deletion tst/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ WRAPS_COMMON = -Wl,$\
--wrap=log_set_threshold,$\
--wrap=log_,--wrap=log_error,--wrap=log_warn,--wrap=log_info,--wrap=log_debug,--wrap=log_error_errno,$\
--wrap=print_head,--wrap=print_mode,$\
--wrap=wd_exit,--wrap=wd_exit_message
--wrap=spawn_async,--wrap=wd_exit,--wrap=wd_exit_message

tst-head: WRAPS=,$\
--wrap=mode_dpi,$\
Expand Down
1 change: 1 addition & 0 deletions tst/marshalling/cfg-all.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ TRANSFORM:
VRR_OFF:
- ten
- ELEVEN
CHANGE_SUCCESS_CMD: cmd
LAPTOP_DISPLAY_PREFIX: ldp
LOG_THRESHOLD: ERROR
DISABLED:
Expand Down
1 change: 1 addition & 0 deletions tst/marshalling/ipc-request-cfg-set.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ CFG:
VRR_OFF:
- ten
- ELEVEN
CHANGE_SUCCESS_CMD: cmd
LAPTOP_DISPLAY_PREFIX: ldp
LOG_THRESHOLD: ERROR
DISABLED:
Expand Down
1 change: 1 addition & 0 deletions tst/marshalling/ipc-responses-map.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ CFG:
VRR_OFF:
- ten
- ELEVEN
CHANGE_SUCCESS_CMD: cmd
LAPTOP_DISPLAY_PREFIX: ldp
LOG_THRESHOLD: ERROR
DISABLED:
Expand Down
32 changes: 32 additions & 0 deletions tst/tst-cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,21 @@ void merge_set__disabled(void **state) {
cfg_free(merged);
}

void merge_set__change_success_cmd(void **state) {
struct State *s = *state;

s->to->change_success_cmd = strdup("to");
s->from->change_success_cmd = strdup("from");

s->expected->change_success_cmd = strdup("from");

struct Cfg *merged = merge_set(s->to, s->from);

assert_cfg_equal(merged, s->expected);

cfg_free(merged);
}

void merge_del__scale(void **state) {
struct State *s = *state;

Expand Down Expand Up @@ -311,6 +326,21 @@ void merge_del__disabled(void **state) {
cfg_free(merged);
}

void merge_del__change_success_cmd(void **state) {
struct State *s = *state;

s->to->change_success_cmd = strdup("to");
s->from->change_success_cmd = strdup("");

s->expected->change_success_cmd = NULL;

struct Cfg *merged = merge_del(s->to, s->from);

assert_cfg_equal(merged, s->expected);

cfg_free(merged);
}

void validate_fix__col(void **state) {
struct State *s = *state;

Expand Down Expand Up @@ -436,12 +466,14 @@ int main(void) {
TEST(merge_set__mode),
TEST(merge_set__adaptive_sync_off),
TEST(merge_set__disabled),
TEST(merge_set__change_success_cmd),

TEST(merge_del__scale),
TEST(merge_del__mode),
TEST(merge_del__transform),
TEST(merge_del__adaptive_sync_off),
TEST(merge_del__disabled),
TEST(merge_del__change_success_cmd),

TEST(validate_fix__col),
TEST(validate_fix__row),
Expand Down
Loading
Loading