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
Changes from 11 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
@@ -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`
@@ -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
@@ -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.
#ON_CHANGE_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'
2 changes: 2 additions & 0 deletions inc/cfg.h
Original file line number Diff line number Diff line change
@@ -61,6 +61,7 @@ struct Cfg {

bool updated;

char *on_change_cmd;
char *laptop_display_prefix;
struct SList *order_name_desc;
enum Arrange arrange;
@@ -89,6 +90,7 @@ enum CfgElement {
MODE,
TRANSFORM,
VRR_OFF,
ON_CHANGE_CMD,
LAPTOP_DISPLAY_PREFIX,
MAX_PREFERRED_REFRESH,
LOG_THRESHOLD,
2 changes: 2 additions & 0 deletions inc/process.h
Original file line number Diff line number Diff line change
@@ -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);

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

// ON_CHANGE_CMD
if (from->on_change_cmd) {
to->on_change_cmd = strdup(from->on_change_cmd);
}

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

// ON_CHANGE_CMD
char *ao = a->on_change_cmd;
char *bo = b->on_change_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;
@@ -845,6 +857,8 @@ void cfg_free(struct Cfg *cfg) {

cfg_free_paths(cfg);

free(cfg->on_change_cmd);

free(cfg->laptop_display_prefix);

slist_free_vals(&cfg->order_name_desc, NULL);
1 change: 1 addition & 0 deletions src/convert.c
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@ static struct NameVal cfg_elements[] = {
{ .val = SCALE, .name = "SCALE", },
{ .val = MODE, .name = "MODE", },
{ .val = VRR_OFF, .name = "VRR_OFF", },
{ .val = ON_CHANGE_CMD, .name = "ON_CHANGE_CMD" },
{ .val = LAPTOP_DISPLAY_PREFIX, .name = "LAPTOP_DISPLAY_PREFIX", },
{ .val = MAX_PREFERRED_REFRESH, .name = "MAX_PREFERRED_REFRESH", },
{ .val = TRANSFORM, .name = "TRANSFORM", },
9 changes: 8 additions & 1 deletion src/layout.c
Original file line number Diff line number Diff line change
@@ -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;
@@ -351,6 +351,13 @@ void handle_success(void) {
}
}

if (!head_changing_adaptive_sync && cfg->on_change_cmd) {
log_info("\nExecuting ON_CHANGE_CMD:");
log_info(" %s", cfg->on_change_cmd);

spawn_async(cfg->on_change_cmd);
}

log_info("\nChanges successful");
}

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

if (cfg.on_change_cmd) {
e << YAML::Key << "ON_CHANGE_CMD" << YAML::Value << cfg.on_change_cmd;
}

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

if (node["ON_CHANGE_CMD"]) {
if (cfg->on_change_cmd) {
free(cfg->on_change_cmd);
}
cfg->on_change_cmd = strdup(node["ON_CHANGE_CMD"].as<std::string>().c_str());
}

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

TI(cfg->on_change_cmd = strdup(node["ON_CHANGE_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()));
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
@@ -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"
@@ -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);
}
2 changes: 1 addition & 1 deletion tst/GNUmakefile
Original file line number Diff line number Diff line change
@@ -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,$\
1 change: 1 addition & 0 deletions tst/marshalling/cfg-all.yaml
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ TRANSFORM:
VRR_OFF:
- ten
- ELEVEN
ON_CHANGE_CMD: cmd
LAPTOP_DISPLAY_PREFIX: ldp
LOG_THRESHOLD: ERROR
DISABLED:
1 change: 1 addition & 0 deletions tst/marshalling/ipc-request-cfg-set.yaml
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@ CFG:
VRR_OFF:
- ten
- ELEVEN
ON_CHANGE_CMD: cmd
LAPTOP_DISPLAY_PREFIX: ldp
LOG_THRESHOLD: ERROR
DISABLED:
1 change: 1 addition & 0 deletions tst/marshalling/ipc-responses-map.yaml
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ CFG:
VRR_OFF:
- ten
- ELEVEN
ON_CHANGE_CMD: cmd
LAPTOP_DISPLAY_PREFIX: ldp
LOG_THRESHOLD: ERROR
DISABLED:
17 changes: 16 additions & 1 deletion tst/tst-layout.c
Original file line number Diff line number Diff line change
@@ -5,16 +5,18 @@
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wayland-client-protocol.h>
#include <wayland-util.h>

#include "cfg.h"
#include "global.h"
#include "head.h"
#include "info.h"
#include "slist.h"
#include "log.h"
#include "mode.h"
#include "slist.h"
#include "util.h"
#include "wlr-output-management-unstable-v1.h"

struct SList *order_heads(struct SList *order_name_desc, struct SList *heads);
@@ -640,6 +642,18 @@ void handle_success__head_changing_mode(void **state) {
assert_null(head_changing_mode);
}

void handle_success__on_change_cmd(void **state) {
cfg->on_change_cmd = strdup("echo \"hi from way-displays\"");

expect_value(__wrap_spawn_async, command, cfg->on_change_cmd);

handle_success();

assert_log(INFO, "\nExecuting ON_CHANGE_CMD:\n"
" echo \"hi from way-displays\"\n"
"\nChanges successful\n");
}

void handle_success__ok(void **state) {
handle_success();

@@ -743,6 +757,7 @@ int main(void) {
TEST(handle_success__head_changing_adaptive_sync),
TEST(handle_success__head_changing_adaptive_sync_fail),
TEST(handle_success__head_changing_mode),
TEST(handle_success__on_change_cmd),
TEST(handle_success__ok),

TEST(handle_failure__mode),
1 change: 1 addition & 0 deletions tst/tst-marshalling.c
Original file line number Diff line number Diff line change
@@ -66,6 +66,7 @@ struct Cfg *cfg_all(void) {
cfg->auto_scale_min = 0.5f;
cfg->auto_scale_max = 2.5f;

cfg->on_change_cmd = strdup("cmd");
cfg->laptop_display_prefix = strdup("ldp");

slist_append(&cfg->order_name_desc, strdup("one"));
5 changes: 4 additions & 1 deletion tst/wrap-process.c
Original file line number Diff line number Diff line change
@@ -2,11 +2,14 @@

#include <cmocka.h>

void __wrap_spawn_async(const char * const command) {
check_expected(command);
}

void __wrap_wd_exit(int __status) {
check_expected(__status);
}

void __wrap_wd_exit_message(int __status) {
check_expected(__status);
}