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(&params);
+               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(&params);
+       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, &registry_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>

Reply via email to