Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package kanshi for openSUSE:Factory checked in at 2023-07-03 17:42:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kanshi (Old) and /work/SRC/openSUSE:Factory/.kanshi.new.13546 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kanshi" Mon Jul 3 17:42:00 2023 rev:2 rq:1096218 version:1.4.0 Changes: -------- --- /work/SRC/openSUSE:Factory/kanshi/kanshi.changes 2023-03-16 22:59:56.323928192 +0100 +++ /work/SRC/openSUSE:Factory/.kanshi.new.13546/kanshi.changes 2023-07-03 17:42:01.224448343 +0200 @@ -1,0 +2,10 @@ +Fri Jun 30 22:53:04 UTC 2023 - llyyr <llyyr.pub...@gmail.com> + +- Update to v.1.4.0: + * Add support for adaptive sync + * Add kanshictl switch + * Keep current profile if it still matches + * Add --listen-fd + * manpage improvements + +------------------------------------------------------------------- Old: ---- kanshi-1.3.1.tar.gz New: ---- kanshi-1.4.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kanshi.spec ++++++ --- /var/tmp/diff_new_pack.YTXioH/_old 2023-07-03 17:42:01.848452017 +0200 +++ /var/tmp/diff_new_pack.YTXioH/_new 2023-07-03 17:42:01.852452040 +0200 @@ -1,7 +1,7 @@ # # spec file for package kanshi # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: kanshi -Version: 1.3.1 +Version: 1.4.0 Release: 0 Summary: Dynamic display configuration License: MIT ++++++ kanshi-1.3.1.tar.gz -> kanshi-1.4.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/.gitignore new/kanshi-v1.4.0/.gitignore --- old/kanshi-v1.3.1/.gitignore 2022-12-14 14:49:54.000000000 +0100 +++ new/kanshi-v1.4.0/.gitignore 2023-06-30 10:08:18.000000000 +0200 @@ -1,2 +1 @@ -/build -/build-* +/subprojects diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/ctl.c new/kanshi-v1.4.0/ctl.c --- old/kanshi-v1.3.1/ctl.c 2022-12-14 14:49:54.000000000 +0100 +++ new/kanshi-v1.4.0/ctl.c 2023-06-30 10:08:18.000000000 +0200 @@ -10,15 +10,26 @@ #include "ipc.h" -static void usage(const char *progname) { - fprintf(stderr, "Usage: %s [command]\n" - "Accepted commands:\n" - " reload - reload the config file\n", - progname); +static void usage(void) { + fprintf(stderr, "Usage: kanshictl [command]\n" + "\n" + "Commands:\n" + " reload Reload the configuration file\n" + " switch <profile> Switch to another profile"); } -static long reload_callback(VarlinkConnection *connection, const char *error, +static long handle_call_done(VarlinkConnection *connection, const char *error, VarlinkObject *parameters, uint64_t flags, void *userdata) { + if (error != NULL) { + if (strcmp(error, "fr.emersion.kanshi.ProfileNotFound") == 0) { + fprintf(stderr, "Profile not found\n"); + } else if (strcmp(error, "fr.emersion.kanshi.ProfileNotMatched") == 0) { + fprintf(stderr, "Profile does not match the current output configuration\n"); + } else { + fprintf(stderr, "Error: %s\n", error); + } + exit(EXIT_FAILURE); + } return varlink_connection_close(connection); } @@ -56,11 +67,11 @@ int main(int argc, char *argv[]) { if (argc < 2) { - usage(argv[0]); + usage(); return EXIT_FAILURE; } if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) { - usage(argv[0]); + usage(); return EXIT_SUCCESS; } @@ -74,17 +85,35 @@ "Is the kanshi daemon running?\n", address); return EXIT_FAILURE; } - if (strcmp(argv[1], "reload") == 0) { - long result = varlink_connection_call(connection, - "fr.emersion.kanshi.Reload", NULL, 0, reload_callback, NULL); - if (result != 0) { - fprintf(stderr, "varlink_connection_call failed: %s\n", - varlink_error_string(-result)); + + const char *command = argv[1]; + long ret; + if (strcmp(command, "reload") == 0) { + ret = varlink_connection_call(connection, + "fr.emersion.kanshi.Reload", NULL, 0, handle_call_done, NULL); + } else if (strcmp(command, "switch") == 0) { + if (argc < 3) { + usage(); return EXIT_FAILURE; } - return wait_for_event(connection); + const char *profile = argv[2]; + + VarlinkObject *params = NULL; + varlink_object_new(¶ms); + varlink_object_set_string(params, "profile", profile); + ret = varlink_connection_call(connection, + "fr.emersion.kanshi.Switch", params, 0, handle_call_done, NULL); + varlink_object_unref(params); + } else { + fprintf(stderr, "invalid command: %s\n", argv[1]); + usage(); + return EXIT_FAILURE; } - fprintf(stderr, "invalid command: %s\n", argv[1]); - usage(argv[0]); - return EXIT_FAILURE; + if (ret != 0) { + fprintf(stderr, "varlink_connection_call failed: %s\n", + varlink_error_string(-ret)); + return EXIT_FAILURE; + } + + return wait_for_event(connection); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/doc/kanshi.1.scd new/kanshi-v1.4.0/doc/kanshi.1.scd --- old/kanshi-v1.3.1/doc/kanshi.1.scd 1970-01-01 01:00:00.000000000 +0100 +++ new/kanshi-v1.4.0/doc/kanshi.1.scd 2023-06-30 10:08:18.000000000 +0200 @@ -0,0 +1,49 @@ +kanshi(1) + +# NAME + +kanshi - dynamic output configuration + +# SYNOPSIS + +*kanshi* [options...] + +# OPTIONS + +*-h, --help* + Show help message and quit. + +*-c, --config* <config> + Specifies a config file. + +*-l, --listen-fd* <fd> + Listen on the specified file descriptor for IPC. + +# DESCRIPTION + +kanshi is a Wayland daemon that automatically configures outputs. + +kanshi is configured with a list of output profiles. Each profile contains a set +of outputs. A profile will be automatically activated if all specified outputs +are currently connected. A profile contains configuration for each output. + +If kanshi receives a SIGHUP signal, it will reread its config file. + +# CONFIGURATION + +kanshi reads its configuration from *$XDG_CONFIG_HOME/kanshi/config*. If unset, +*$XDG_CONFIG_HOME* defaults to *~/.config*. + +An error is raised if no configuration file is found. + +For information on the configuration file format, see *kanshi*(5). + +# AUTHORS + +Maintained by Simon Ser <cont...@emersion.fr>, who is assisted by other +open-source contributors. For more information about kanshi development, see +<https://git.sr.ht/~emersion/kanshi>. + +# SEE ALSO + +*kanshi*(5) *kanshictl*(1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/doc/kanshi.5.scd new/kanshi-v1.4.0/doc/kanshi.5.scd --- old/kanshi-v1.3.1/doc/kanshi.5.scd 1970-01-01 01:00:00.000000000 +0100 +++ new/kanshi-v1.4.0/doc/kanshi.5.scd 2023-06-30 10:08:18.000000000 +0200 @@ -0,0 +1,125 @@ +kanshi(5) + +# NAME + +kanshi - configuration file + +# DESCRIPTION + +A kanshi configuration file is a list of profiles. Each profile has an optional +name and contains profile directives delimited by brackets (*{* and *}*). + +Example: + +``` +include /etc/kanshi/config.d/* + +profile { + output LVDS-1 disable + output "Some Company ASDF 4242" mode 1600x900 position 0,0 +} + +profile nomad { + output LVDS-1 enable scale 2 +} +``` + +# DIRECTIVES + +*profile* [<name>] { <profile directives...> } + Defines a new profile using the specified bracket-delimited profile + directives. A name can be specified but is optional. + +*include* <path> + Include as another file from _path_. Expands shell syntax (see *wordexp*(3) + for details). + +# PROFILE DIRECTIVES + +Profile directives are followed by space-separated arguments. Arguments can be +quoted (with *"*) if they contain spaces. + +*output* <criteria> <output-command...> + An output directive adds an output to the profile. The criteria can either + be an output name, an output description or "\*". The latter can be used to + match any output. + + On *sway*(1), output names and descriptions can be obtained via + *swaymsg -t get_outputs*. + +*exec* <command> + An exec directive executes a command when the profile was successfully + applied. This can be used to update the compositor state to the profile + when not done automatically. + + Commands are executed asynchronously and their order may not be preserved. + If you need to execute sequential commands, you should collect in one exec + statement or in a separate script. + + On *sway*(1) for example, *exec* can be used to move workspaces to the + right output: + + ``` + profile multihead { + output eDP-1 enable + output DP-1 enable transform 270 + exec swaymsg workspace 1, move workspace to eDP-1 + } + ``` + + Note that some extra care must be taken with outputs identified by an + output description as the real name may change: + + ``` + profile complex { + output "Some Other Company GTBZ 2525" mode 1920x1200 + exec swaymsg workspace 1, move workspace to output '"Some Other Company GTBZ 2525"' + } + ``` + +# OUTPUT DIRECTIVES + +*enable*|*disable* + Enables or disables the specified output. + +*mode* <width>x<height>[@<rate>[Hz]] + Configures the specified output to use the specified mode. Modes are a + combination of width and height (in pixels) and a refresh rate (in Hz) that + your display can be configured to use. + + Examples: + + ``` + output HDMI-A-1 mode 1920x1080 + output HDMI-A-1 mode 1920x1080@60Hz + ``` + +*position* <x>,<y> + Places the output at the specified position in the global coordinates space. + + Example: + + ``` + output HDMI-A-1 position 1600,0 + ``` + +*scale* <factor> + Scales the output by the specified scale factor. + +*transform* <transform> + Sets the output transform. Can be one of "90", "180", "270" for a rotation; + or "flipped", "flipped-90", "flipped-180", "flipped-270" for a rotation and + a flip; or "normal" for no transform. + +*adaptive_sync* on|off + Enables or disables adaptive synchronization (aka. Variable Refresh Rate). + +# AUTHORS + +Maintained by Simon Ser <cont...@emersion.fr>, who is assisted by other +open-source contributors. For more information about kanshi development, see +<https://git.sr.ht/~emersion/kanshi>. + +# SEE ALSO + +*kanshi*(1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/doc/kanshictl.1.scd new/kanshi-v1.4.0/doc/kanshictl.1.scd --- old/kanshi-v1.3.1/doc/kanshictl.1.scd 1970-01-01 01:00:00.000000000 +0100 +++ new/kanshi-v1.4.0/doc/kanshictl.1.scd 2023-06-30 10:08:18.000000000 +0200 @@ -0,0 +1,32 @@ +kanshictl(1) + +# NAME + +kanshictl - control the kanshi daemon remotely + +# SYNOPSIS + +*kanshictl* [options...] [command] + +# OPTIONS + +*-h, --help* + Show help message and quit. + +# COMMANDS + +*reload* + Reload the config file. + +*switch* <profile> + Switch to a different profile. + +# AUTHORS + +Maintained by Simon Ser <cont...@emersion.fr>, who is assisted by other +open-source contributors. For more information about kanshi development, see +https://git.sr.ht/~emersion/kanshi. + +# SEE ALSO + +*kanshi*(1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/doc/meson.build new/kanshi-v1.4.0/doc/meson.build --- old/kanshi-v1.3.1/doc/meson.build 1970-01-01 01:00:00.000000000 +0100 +++ new/kanshi-v1.4.0/doc/meson.build 2023-06-30 10:08:18.000000000 +0200 @@ -0,0 +1,35 @@ +scdoc = dependency( + 'scdoc', + version: '>=1.9.2', + native: true, + required: get_option('man-pages'), +) +if not scdoc.found() + subdir_done() +endif + +scdoc_path = scdoc.get_variable('scdoc') +mandir = get_option('mandir') +man_files = [ + 'kanshi.1.scd', + 'kanshi.5.scd', +] +if varlink.found() + man_files += 'kanshictl.1.scd' +endif +foreach filename : man_files + topic = filename.split('.')[-3].split('/')[-1] + section = filename.split('.')[-2] + output = '@0@.@1@'.format(topic, section) + + custom_target( + output, + input: filename, + output: output, + command: scdoc_path, + capture: true, + feed: true, + install: true, + install_dir: '@0@/man@1@'.format(mandir, section) + ) +endforeach diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/include/config.h new/kanshi-v1.4.0/include/config.h --- old/kanshi-v1.3.1/include/config.h 2022-12-14 14:49:54.000000000 +0100 +++ new/kanshi-v1.4.0/include/config.h 2023-06-30 10:08:18.000000000 +0200 @@ -10,6 +10,7 @@ KANSHI_OUTPUT_POSITION = 1 << 2, KANSHI_OUTPUT_SCALE = 1 << 3, KANSHI_OUTPUT_TRANSFORM = 1 << 4, + KANSHI_OUTPUT_ADAPTIVE_SYNC = 1 << 5, }; struct kanshi_profile_output { @@ -27,6 +28,7 @@ } position; float scale; enum wl_output_transform transform; + bool adaptive_sync; }; struct kanshi_profile_command { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/include/ipc.h new/kanshi-v1.4.0/include/ipc.h --- old/kanshi-v1.3.1/include/ipc.h 2022-12-14 14:49:54.000000000 +0100 +++ new/kanshi-v1.4.0/include/ipc.h 2023-06-30 10:08:18.000000000 +0200 @@ -5,7 +5,7 @@ #include "kanshi.h" -int kanshi_init_ipc(struct kanshi_state *state); +int kanshi_init_ipc(struct kanshi_state *state, int listen_fd); void kanshi_free_ipc(struct kanshi_state *state); int get_ipc_address(char *address, size_t size); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/include/kanshi.h new/kanshi-v1.4.0/include/kanshi.h --- old/kanshi-v1.3.1/include/kanshi.h 2022-12-14 14:49:54.000000000 +0100 +++ new/kanshi-v1.4.0/include/kanshi.h 2023-06-30 10:08:18.000000000 +0200 @@ -38,6 +38,7 @@ int32_t x, y; enum wl_output_transform transform; double scale; + bool adaptive_sync; }; struct kanshi_state { @@ -64,6 +65,7 @@ }; bool kanshi_reload_config(struct kanshi_state *state); +bool kanshi_switch(struct kanshi_state *state, struct kanshi_profile *profile); int kanshi_main_loop(struct kanshi_state *state); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/ipc.c new/kanshi-v1.4.0/ipc.c --- old/kanshi-v1.3.1/ipc.c 2022-12-14 14:49:54.000000000 +0100 +++ new/kanshi-v1.4.0/ipc.c 2023-06-30 10:08:18.000000000 +0200 @@ -1,11 +1,25 @@ #define _POSIX_C_SOURCE 200809L +#include <fcntl.h> #include <limits.h> #include <stdio.h> +#include <string.h> #include <varlink.h> +#include "config.h" #include "kanshi.h" #include "ipc.h" +static long reply_error(VarlinkCall *call, const char *name) { + VarlinkObject *params = NULL; + long ret = varlink_object_new(¶ms); + if (ret < 0) { + return ret; + } + ret = varlink_call_reply_error(call, name, params); + varlink_object_unref(params); + return ret; +} + static void reload_config_done(void *data, struct wl_callback *callback, uint32_t serial) { VarlinkCall *call = data; @@ -29,7 +43,55 @@ return 0; } -int kanshi_init_ipc(struct kanshi_state *state) { +static long handle_switch(VarlinkService *service, VarlinkCall *call, + VarlinkObject *parameters, uint64_t flags, void *userdata) { + struct kanshi_state *state = userdata; + + const char *profile_name; + if (varlink_object_get_string(parameters, "profile", &profile_name) < 0) { + return varlink_call_reply_invalid_parameter(call, "profile"); + } + + struct kanshi_profile *profile; + bool found = false; + wl_list_for_each(profile, &state->config->profiles, link) { + if (strcmp(profile->name, profile_name) == 0) { + found = true; + break; + } + } + if (!found) { + return reply_error(call, "fr.emersion.kanshi.ProfileNotFound"); + } + + if (!kanshi_switch(state, profile)) { + return reply_error(call, "fr.emersion.kanshi.ProfileNotMatched"); + } + + // TODO: use the wlr-output-management event instead + struct wl_callback *callback = wl_display_sync(state->display); + wl_callback_add_listener(callback, &reload_config_listener, call); + return 0; +} + +static int set_cloexec(int fd) { + int flags = fcntl(fd, F_GETFD); + if (flags < 0) { + perror("fnctl(F_GETFD) failed"); + return -1; + } + if (fcntl(fd, F_SETFD, flags | O_CLOEXEC) < 0) { + perror("fnctl(F_SETFD) failed"); + return -1; + } + return 0; +} + +int kanshi_init_ipc(struct kanshi_state *state, int listen_fd) { + if (listen_fd >= 0 && set_cloexec(listen_fd) < 0) { + return -1; + } + VarlinkService *service; char address[PATH_MAX]; if (get_ipc_address(address, sizeof(address)) < 0) { @@ -37,17 +99,21 @@ } if (varlink_service_new(&service, "emersion", "kanshi", KANSHI_VERSION, "https://wayland.emersion.fr/kanshi/", - address, -1) < 0) { + address, listen_fd) < 0) { fprintf(stderr, "Couldn't start kanshi varlink service at %s.\n" "Is the kanshi daemon already running?\n", address); return -1; } const char *interface = "interface fr.emersion.kanshi\n" - "method Reload() -> ()"; + "method Reload() -> ()\n" + "method Switch(profile: string) -> ()\n" + "error ProfileNotFound()\n" + "error ProfileNotMatched()\n"; long result = varlink_service_add_interface(service, interface, "Reload", handle_reload, state, + "Switch", handle_switch, state, NULL); if (result != 0) { fprintf(stderr, "varlink_service_add_interface failed: %s\n", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/kanshi.1.scd new/kanshi-v1.4.0/kanshi.1.scd --- old/kanshi-v1.3.1/kanshi.1.scd 2022-12-14 14:49:54.000000000 +0100 +++ new/kanshi-v1.4.0/kanshi.1.scd 1970-01-01 01:00:00.000000000 +0100 @@ -1,46 +0,0 @@ -kanshi(1) - -# NAME - -kanshi - dynamic output configuration - -# SYNOPSIS - -*kanshi* [options...] - -# OPTIONS - -*-h, --help* - Show help message and quit. - -*-c, --config* <config> - Specifies a config file. - -# DESCRIPTION - -kanshi is a Wayland daemon that automatically configures outputs. - -kanshi is configured with a list of output profiles. Each profile contains a set -of outputs. A profile will be automatically activated if all specified outputs -are currently connected. A profile contains configuration for each output. - -If kanshi receives a SIGHUP signal, it will reread its config file. - -# CONFIGURATION - -kanshi reads its configuration from *$XDG_CONFIG_HOME/kanshi/config*. If unset, -*$XDG_CONFIG_HOME* defaults to *~/.config*. - -An error is raised if no configuration file is found. - -For information on the configuration file format, see *kanshi*(5). - -# AUTHORS - -Maintained by Simon Ser <cont...@emersion.fr>, who is assisted by other -open-source contributors. For more information about kanshi development, see -https://git.sr.ht/~emersion/kanshi. - -# SEE ALSO - -*kanshi*(5) *kanshictl*(1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/kanshi.5.scd new/kanshi-v1.4.0/kanshi.5.scd --- old/kanshi-v1.3.1/kanshi.5.scd 2022-12-14 14:49:54.000000000 +0100 +++ new/kanshi-v1.4.0/kanshi.5.scd 1970-01-01 01:00:00.000000000 +0100 @@ -1,122 +0,0 @@ -kanshi(5) - -# NAME - -kanshi - configuration file - -# DESCRIPTION - -A kanshi configuration file is a list of profiles. Each profile has an optional -name and contains profile directives delimited by brackets (*{* and *}*). - -Example: - -``` -include /etc/kanshi/config.d/* - -profile { - output LVDS-1 disable - output "Some Company ASDF 4242" mode 1600x900 position 0,0 -} - -profile nomad { - output LVDS-1 enable scale 2 -} -``` - -# DIRECTIVES - -*profile* [<name>] { <profile directives...> } - Defines a new profile using the specified bracket-delimited profile - directives. A name can be specified but is optional. - -*include* <path> - Include as another file from _path_. Expands shell syntax (see *wordexp*(3) - for details). - -# PROFILE DIRECTIVES - -Profile directives are followed by space-separated arguments. Arguments can be -quoted (with *"*) if they contain spaces. - -*output* <criteria> <output-command...> - An output directive adds an output to the profile. The criteria can either - be an output name, an output description or "\*". The latter can be used to - match any output. - - On *sway*(1), output names and descriptions can be obtained via - *swaymsg -t get_outputs*. - -*exec* <command> - An exec directive executes a command when the profile was successfully - applied. This can be used to update the compositor state to the profile - when not done automatically. - - Commands are executed asynchronously and their order may not be preserved. - If you need to execute sequential commands, you should collect in one exec - statement or in a separate script. - - On *sway*(1) for example, *exec* can be used to move workspaces to the - right output: - -``` - profile multihead { - output eDP-1 enable - output DP-1 enable transform 270 - exec swaymsg workspace 1, move workspace to eDP-1 - } -``` - - Note that some extra care must be taken with outputs identified by an - output description as the real name may change: - -``` - profile complex { - output "Some Other Company GTBZ 2525" mode 1920x1200 - exec swaymsg workspace 1, move workspace to output '"Some Other Company GTBZ 2525"' - } -``` - -# OUTPUT DIRECTIVES - -*enable*|*disable* - Enables or disables the specified output. - -*mode* <width>x<height>[@<rate>[Hz]] - Configures the specified output to use the specified mode. Modes are a - combination of width and height (in pixels) and a refresh rate (in Hz) that - your display can be configured to use. - - Examples: - -``` - output HDMI-A-1 mode 1920x1080 - output HDMI-A-1 mode 1920x1080@60Hz -``` - -*position* <x>,<y> - Places the output at the specified position in the global coordinates space. - - Example: - -``` - output HDMI-A-1 position 1600,0 -``` - -*scale* <factor> - Scales the output by the specified scale factor. - -*transform* <transform> - Sets the output transform. Can be one of "90", "180", "270" for a rotation; - or "flipped", "flipped-90", "flipped-180", "flipped-270" for a rotation and - a flip; or "normal" for no transform. - -# AUTHORS - -Maintained by Simon Ser <cont...@emersion.fr>, who is assisted by other -open-source contributors. For more information about kanshi development, see -https://git.sr.ht/~emersion/kanshi. - -# SEE ALSO - -*kanshi*(1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/kanshictl.1.scd new/kanshi-v1.4.0/kanshictl.1.scd --- old/kanshi-v1.3.1/kanshictl.1.scd 2022-12-14 14:49:54.000000000 +0100 +++ new/kanshi-v1.4.0/kanshictl.1.scd 1970-01-01 01:00:00.000000000 +0100 @@ -1,28 +0,0 @@ -kanshictl(1) - -# NAME - -kanshictl - control the kanshi daemon remotely - -# SYNOPSIS - -*kanshictl* [options...] [command] - -# OPTIONS - -*-h, --help* - Show help message and quit. - -# COMMANDS - -reload - reload the config file - -# AUTHORS - -Maintained by Simon Ser <cont...@emersion.fr>, who is assisted by other -open-source contributors. For more information about kanshi development, see -https://git.sr.ht/~emersion/kanshi. - -# SEE ALSO - -*kanshi*(1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/main.c new/kanshi-v1.4.0/main.c --- old/kanshi-v1.3.1/main.c 2022-12-14 14:49:54.000000000 +0100 +++ new/kanshi-v1.4.0/main.c 2023-06-30 10:08:18.000000000 +0200 @@ -20,7 +20,7 @@ #define HEADS_MAX 64 -static bool try_apply_profiles(struct kanshi_state *state); +static bool match_and_apply(struct kanshi_state *state); static bool match_profile_output(struct kanshi_profile_output *output, struct kanshi_head *head) { @@ -131,25 +131,24 @@ } } -static void execute_profile_commands(struct kanshi_profile *profile) { +static void config_handle_succeeded(void *data, + struct zwlr_output_configuration_v1 *config) { + struct kanshi_pending_profile *pending = data; + zwlr_output_configuration_v1_destroy(config); + + struct kanshi_state *state = pending->state; + struct kanshi_profile *profile = pending->profile; + struct kanshi_profile_command *command; wl_list_for_each(command, &profile->commands, link) { - fprintf(stderr, "Running command '%s'\n", command->command); + fprintf(stderr, "running command '%s'\n", command->command); exec_command(command->command); } -} -static void config_handle_succeeded(void *data, - struct zwlr_output_configuration_v1 *config) { - struct kanshi_pending_profile *pending = data; - zwlr_output_configuration_v1_destroy(config); - fprintf(stderr, "running commands for configuration '%s'\n", pending->profile->name); - execute_profile_commands(pending->profile); - fprintf(stderr, "configuration for profile '%s' applied\n", - pending->profile->name); - pending->state->current_profile = pending->profile; - if (pending->profile == pending->state->pending_profile) { - pending->state->pending_profile = NULL; + fprintf(stderr, "configuration for profile '%s' applied\n", profile->name); + state->current_profile = profile; + if (profile == state->pending_profile) { + state->pending_profile = NULL; } free(pending); } @@ -179,7 +178,7 @@ if (pending->serial != pending->state->serial) { // We've already received a new serial, try re-applying the profile // immediately - try_apply_profiles(pending->state); + match_and_apply(pending->state); } free(pending); } @@ -300,6 +299,10 @@ zwlr_output_configuration_head_v1_set_transform(config_head, profile_output->transform); } + if (profile_output->fields & KANSHI_OUTPUT_ADAPTIVE_SYNC) { + zwlr_output_configuration_head_v1_set_adaptive_sync(config_head, + profile_output->adaptive_sync); + } } zwlr_output_configuration_v1_apply(config); @@ -461,6 +464,12 @@ head->serial_number = strdup(serial_number); } +static void head_handle_adaptive_sync(void *data, + struct zwlr_output_head_v1 *zwlr_output_head_v1, uint32_t state) { + struct kanshi_head *head = data; + head->adaptive_sync = state; +} + static const struct zwlr_output_head_v1_listener head_listener = { .name = head_handle_name, .description = head_handle_description, @@ -475,6 +484,7 @@ .make = head_handle_make, .model = head_handle_model, .serial_number = head_handle_serial_number, + .adaptive_sync = head_handle_adaptive_sync, }; static void output_manager_handle_head(void *data, @@ -492,10 +502,14 @@ zwlr_output_head_v1_add_listener(wlr_head, &head_listener, head); } -static bool try_apply_profiles(struct kanshi_state *state) { +static bool match_and_apply(struct kanshi_state *state) { assert(wl_list_length(&state->heads) <= HEADS_MAX); // matches[i] gives the kanshi_profile_output for the i-th head struct kanshi_profile_output *matches[HEADS_MAX]; + if (state->current_profile != NULL && + match_profile(state, state->current_profile, matches)) { + return true; // keep the current profile if it still matches + } struct kanshi_profile *profile = match(state, matches); if (profile != NULL) { apply_profile(state, profile, matches); @@ -505,12 +519,21 @@ return false; } +bool kanshi_switch(struct kanshi_state *state, struct kanshi_profile *profile) { + struct kanshi_profile_output *matches[HEADS_MAX]; + if (!match_profile(state, profile, matches)) { + return false; + } + + apply_profile(state, profile, matches); + return true; +} + static void output_manager_handle_done(void *data, struct zwlr_output_manager_v1 *manager, uint32_t serial) { struct kanshi_state *state = data; state->serial = serial; - - try_apply_profiles(state); + match_and_apply(state); } static void output_manager_handle_finished(void *data, @@ -530,8 +553,8 @@ if (strcmp(interface, zwlr_output_manager_v1_interface.name) == 0) { uint32_t bind_version = 2; - if (version >= 3) { - bind_version = 3; + if (version >= 4) { + bind_version = 4; } state->output_manager = wl_registry_bind(registry, name, &zwlr_output_manager_v1_interface, bind_version); @@ -602,7 +625,7 @@ state->config = config; state->pending_profile = NULL; state->current_profile = NULL; - return try_apply_profiles(state); + return match_and_apply(state); } return false; } @@ -614,18 +637,31 @@ static const struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"config", required_argument, 0, 'c'}, + {"listen-fd", required_argument, 0, 'l'}, {0}, }; int main(int argc, char *argv[]) { const char *config_arg = NULL; +#if KANSHI_HAS_VARLINK + int listen_fd = -1; +#endif int opt; - while ((opt = getopt_long(argc, argv, "hc:", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "hc:l:", long_options, NULL)) != -1) { switch (opt) { case 'c': config_arg = optarg; break; + case 'l': +#if KANSHI_HAS_VARLINK + listen_fd = strtol(optarg, NULL, 10); +#else + fprintf(stderr, "IPC support is disabled, " + "-l/--listen-fd is not supported\n"); + return EXIT_FAILURE; +#endif + break; case 'h': fprintf(stderr, usage, argv[0]); return EXIT_SUCCESS; @@ -654,7 +690,7 @@ }; int ret = EXIT_SUCCESS; #if KANSHI_HAS_VARLINK - if (kanshi_init_ipc(&state) != 0) { + if (kanshi_init_ipc(&state, listen_fd) != 0) { ret = EXIT_FAILURE; goto done; } @@ -663,7 +699,6 @@ struct wl_registry *registry = wl_display_get_registry(display); wl_registry_add_listener(registry, ®istry_listener, &state); - wl_display_dispatch(display); wl_display_roundtrip(display); if (state.output_manager == NULL) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/meson.build new/kanshi-v1.4.0/meson.build --- old/kanshi-v1.3.1/meson.build 2022-12-14 14:49:54.000000000 +0100 +++ new/kanshi-v1.4.0/meson.build 2023-06-30 10:08:18.000000000 +0200 @@ -1,7 +1,7 @@ project( 'kanshi', 'c', - version: '1.3.1', + version: '1.4.0', license: 'MIT', meson_version: '>=0.59.0', default_options: [ @@ -64,7 +64,7 @@ executable( meson.project_name(), kanshi_srcs, - include_directories: include_directories('include'), + include_directories: 'include', dependencies: kanshi_deps, install: true, ) @@ -76,42 +76,15 @@ 'ctl.c', 'ipc-addr.c', ), - include_directories: include_directories('include'), + include_directories: 'include', dependencies: [varlink], install: true, ) endif -scdoc = dependency( - 'scdoc', - version: '>=1.9.2', - native: true, - required: get_option('man-pages'), -) -if scdoc.found() - scdoc_path = scdoc.get_variable('scdoc') - mandir = get_option('mandir') - man_files = [ - 'kanshi.1.scd', - 'kanshi.5.scd', - ] - if varlink.found() - man_files += 'kanshictl.1.scd' - endif - foreach filename : man_files - topic = filename.split('.')[-3].split('/')[-1] - section = filename.split('.')[-2] - output = '@0@.@1@'.format(topic, section) - - custom_target( - output, - input: filename, - output: output, - command: scdoc_path, - capture: true, - feed: true, - install: true, - install_dir: '@0@/man@1@'.format(mandir, section) - ) - endforeach -endif +subdir('doc') + +summary({ + 'Man pages': scdoc.found(), + 'IPC': varlink.found(), +}, bool_yn: true) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/parser.c new/kanshi-v1.4.0/parser.c --- old/kanshi-v1.3.1/parser.c 2022-12-14 14:49:54.000000000 +0100 +++ new/kanshi-v1.4.0/parser.c 2023-06-30 10:08:18.000000000 +0200 @@ -33,6 +33,7 @@ return ch; } + errno = 0; int ch = fgetc(parser->f); if (ch == EOF) { if (errno != 0) { @@ -288,6 +289,17 @@ return true; } +static bool parse_bool(bool *dst, const char *str) { + if (strcmp(str, "on") == 0) { + *dst = true; + } else if (strcmp(str, "off") == 0) { + *dst = false; + } else { + return false; + } + return true; +} + static struct kanshi_profile_output *parse_profile_output( struct kanshi_parser *parser) { struct kanshi_profile_output *output = calloc(1, sizeof(*output)); @@ -331,6 +343,12 @@ return NULL; } break; + case KANSHI_OUTPUT_ADAPTIVE_SYNC: + if (!parse_bool(&output->adaptive_sync, value)) { + fprintf(stderr, "invalid output adaptive_sync\n"); + return NULL; + } + break; default: abort(); } @@ -355,6 +373,8 @@ key = KANSHI_OUTPUT_SCALE; } else if (strcmp(key_str, "transform") == 0) { key = KANSHI_OUTPUT_TRANSFORM; + } else if (strcmp(key_str, "adaptive_sync") == 0) { + key = KANSHI_OUTPUT_ADAPTIVE_SYNC; } else { fprintf(stderr, "unknown directive '%s' in profile output '%s'\n", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kanshi-v1.3.1/protocol/wlr-output-management-unstable-v1.xml new/kanshi-v1.4.0/protocol/wlr-output-management-unstable-v1.xml --- old/kanshi-v1.3.1/protocol/wlr-output-management-unstable-v1.xml 2022-12-14 14:49:54.000000000 +0100 +++ new/kanshi-v1.4.0/protocol/wlr-output-management-unstable-v1.xml 2023-06-30 10:08:18.000000000 +0200 @@ -39,7 +39,7 @@ interface version number is reset. </description> - <interface name="zwlr_output_manager_v1" version="3"> + <interface name="zwlr_output_manager_v1" version="4"> <description summary="output device configuration manager"> This interface is a manager that allows reading and writing the current output device configuration. @@ -125,7 +125,7 @@ </event> </interface> - <interface name="zwlr_output_head_v1" version="3"> + <interface name="zwlr_output_head_v1" version="4"> <description summary="output device"> A head is an output device. The difference between a wl_output object and a head is that heads are advertised even if they are turned off. A head @@ -338,6 +338,22 @@ object. </description> </request> + + <!-- Version 4 additions --> + + <enum name="adaptive_sync_state" since="4"> + <entry name="disabled" value="0" summary="adaptive sync is disabled"/> + <entry name="enabled" value="1" summary="adaptive sync is enabled"/> + </enum> + + <event name="adaptive_sync" since="4"> + <description summary="current adaptive sync state"> + This event describes whether adaptive sync is currently enabled for + the head or not. Adaptive sync is also known as Variable Refresh + Rate or VRR. + </description> + <arg name="state" type="uint" enum="adaptive_sync_state"/> + </event> </interface> <interface name="zwlr_output_mode_v1" version="3"> @@ -395,7 +411,7 @@ </request> </interface> - <interface name="zwlr_output_configuration_v1" version="3"> + <interface name="zwlr_output_configuration_v1" version="4"> <description summary="output configuration"> This object is used by the client to describe a full output configuration. @@ -513,7 +529,7 @@ </request> </interface> - <interface name="zwlr_output_configuration_head_v1" version="3"> + <interface name="zwlr_output_configuration_head_v1" version="4"> <description summary="head configuration"> This object is used by the client to update a single head's configuration. @@ -526,6 +542,8 @@ <entry name="invalid_custom_mode" value="3" summary="mode is invalid"/> <entry name="invalid_transform" value="4" summary="transform value outside enum"/> <entry name="invalid_scale" value="5" summary="scale negative or zero"/> + <entry name="invalid_adaptive_sync_state" value="6" since="4" + summary="invalid enum value used in the set_adaptive_sync request"/> </enum> <request name="set_mode"> @@ -569,5 +587,15 @@ </description> <arg name="scale" type="fixed"/> </request> + + <!-- Version 4 additions --> + + <request name="set_adaptive_sync" since="4"> + <description summary="enable/disable adaptive sync"> + This request enables/disables adaptive sync. Adaptive sync is also + known as Variable Refresh Rate or VRR. + </description> + <arg name="state" type="uint" enum="zwlr_output_head_v1.adaptive_sync_state"/> + </request> </interface> </protocol>