kanshi: Do not allow substring matching of output names, only exact matching v1 NEEDS REVISION

Ivan Oleynikov: 1
 Do not allow substring matching of output names, only exact matching

 1 files changed, 19 insertions(+), 2 deletions(-)
#658738 .build.yml success
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~emersion/public-inbox/patches/27745/mbox | git am -3
Learn more about email & git

[PATCH kanshi] Do not allow substring matching of output names, only exact matching Export this patch

Previously, the matching algorithm was looking for user-configured
output name as a substring in "$output_description ($output_name)". This
lead to unexpected behaviour when you have two outputs where the one's
description is a substring of the other's.

For example, say, you have monitors "hello (DP-1)" and "hello world
(DP-2)" and you're trying to match them in your Kanshi config using

profile {
  output "hello" …
  output "hello world" …

Substring matching allows "hello" to be matched with either of the
outputs, and the profile may end up being applied or rejected depending
on the order in which the outputs are discovered: if "hello world
(DP-2)" is discovered first, it gets matched with "hello", while "hello
world" fails to match with "hello (DP-1)".

This patch trims the " ($output_name)" part from the stored output
description (which was redundant anyway, we already store it in another
field) and expects the user-configured string to fully match the

This patch fixes my issue that I reported in
<https://todo.sr.ht/~emersion/kanshi/54> (I don't know if it fixes the
issues of others reported there).
 main.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/main.c b/main.c
index db34789..98349c9 100644
--- a/main.c
+++ b/main.c
@@ -25,8 +25,7 @@ static bool match_profile_output(struct kanshi_profile_output *output,
	// TODO: improve vendor/model/serial matching
	return strcmp(output->name, "*") == 0 ||
		strcmp(output->name, head->name) == 0 ||
		(strchr(output->name, ' ') != NULL &&
		strstr(head->description, output->name) != NULL);
		strcmp(output->name, head->description) == 0;

static bool match_profile(struct kanshi_state *state,
@@ -318,6 +317,24 @@ static void head_handle_description(void *data,
		struct zwlr_output_head_v1 *wlr_head, const char *description) {
	struct kanshi_head *head = data;
	head->description = strdup(description);
	// The following code trims the output name from the description. The name
	// contained here is a duplicate of the one received by head_handle_name so we
	// don't need to store it in the description.
	// We expect the description we receive to have the format
	// "$useful_part ($name)" and the following loop trims the " ($name)" storing
	// only the "$useful_part". The implementation is simplistic, it assumes $name
	// doesn't contain brackets.
	int len = strlen(head->description);
	if (head->description[len - 1] == ')') {
		for (int i = len - 2; i >= 0; --i) {
			if (head->description[i] == '(') {
				if (i > 0 && head->description[i-1] == ' ')
  				head->description[i - 1] = '\0';

static void head_handle_physical_size(void *data,
kanshi/patches/.build.yml: SUCCESS in 33s

[Do not allow substring matching of output names, only exact matching][0] from [Ivan Oleynikov][1]

[0]: https://lists.sr.ht/~emersion/public-inbox/patches/27745
[1]: mailto:ivan.oleynikov95@gmail.com

✓ #658738 SUCCESS kanshi/patches/.build.yml https://builds.sr.ht/~emersion/job/658738