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

For local services use "localhost" in device URI of temporary queue #353

Merged
merged 3 commits into from
Jun 20, 2022

Conversation

tillkamppeter
Copy link
Member

To print to a temporary CUPS queue for a discovered IPP printer the client has to send an IPP_OP_CUPS_CREATE_LOCAL_PRINTER IPP request to the CUPS daemon with the details for creating the temporary queue. CUPS then calls its create_local_printer() function to actually create the queue. This is already automatically and correctly done if the client uses the convenience API of libcups.

The GTK print dialog does not use the convenience API though. It displays all IPP printers for which CUPS can create temporary queues correctly, but it fails on services which are only available on the local machine and not on the network (loopback interface, "localhost") whereas printing via temporary queue on network/remote services works perfectly.

The problem is that Avahi advertises the local services not with the "localhost" host name but with the network host name of the local machine. The libcups convenience API functions can cope with this and send correct device URIs with the "localhost" host name to CUPS and so the temporary queue gets created correctly.

The GTK dialog wants fully asynchronous CUPS operation and throws the libcups API completely overboard doing all by itself, and sending incorrect device URIs with the network hostname for the local services. CUPS creates the temporary queue with this URI then and fails to do the get-printer-attributes request on the printer to generate the PPD file, leaving the temporary queue in a non-functional state.

This commit correct/works around this by checking whether the device URI's host name is the same as the DNS-SD host name of the local machine and if so, replaces the device URI's host name by "localhost".

Now one can select local services like IPP-over-USB printers or Printer Applications in the GTK print dialog and printing on them through an auto-generated temporary CUPS queue works.

I decided to fix/work around this problem in CUPS as we see that no every print client developer uses the libcups convenience API.

In addition, in the create_local_printer() we check the device_uri IPP attribute also whether it is not empty and fail if it is empty.

@michaelrsweet michaelrsweet self-requested a review March 14, 2022 01:18
@michaelrsweet michaelrsweet self-assigned this Mar 14, 2022
@michaelrsweet michaelrsweet added enhancement New feature or request priority-medium platform issue Issue is specific to an OS or desktop labels Mar 14, 2022
@michaelrsweet michaelrsweet added this to the v2.4.x milestone Mar 14, 2022
@michaelrsweet
Copy link
Member

I would like to do some regression testing before we merge this…

@tillkamppeter
Copy link
Member Author

To get more testing feedback I have applied this patch to Ubuntu's CUPS package (version 2.4.1op1-1ubuntu2) now. So should it cause regressions, I should get bug reports on Ubuntu (Jammy Jellyfish, 22.04).

@tillkamppeter
Copy link
Member Author

tillkamppeter commented Mar 16, 2022

Updated the PR as CUPS crashed with it when not sharing printers (Browsing No in cupsd.conf, see Ubuntu bug #1965112). The second commit fixes this.

@tillkamppeter
Copy link
Member Author

This is now in Ubuntu 22.04 LTS (Jammy Jellyfish) for 2 months without any further complaints. What about merging it?

@zdohnal
Copy link
Member

zdohnal commented Jun 7, 2022

Hi @tillkamppeter ,

if I understand the issue correctly, you cannot print via GTK dialog to IPP services which are advertised on localhost (such as IPP services generated by ipp-usb for IPP-over-USB supported USB printers), correct?

If it is the case, then it looks like an OS issue - because I can print to such queues via GTK on Fedora (at least on 36, because my laptop at the office has Fedora 36, but it is the first release I've tried our Canon printer, which can do IPP-over-USB, with, so maybe earlier Fedoras/GTK can do that as well). I've tried printing via temp queue based on device from snapped ps-printer-app, and printing worked as well.

No cups-browsed was needed.

I have the following versions of GTK, nss-mdns and Avahi:

gtk3 and nss-mdns are vanillas from upstream, but avahi has several downstream patches because of upstream unresponsiveness, so maybe some of them can make it working for Debian/Ubuntu.

I would wait with merging until an investigation regarding mDNS resolving happens in Debian/Ubuntu, because IMHO changing the current behavior which works for some distributions can create other regressions...

@tillkamppeter
Copy link
Member Author

@zdohnal could you run the following commands and post the output here:

avahi-browse -t -r _ipps._tcp
avahi-browse -t -r _ipp._tcp
host YOUR_MACHINES_HOSTNAME
ippfind
driverless
driverless --std-ipp-uris

@zdohnal
Copy link
Member

zdohnal commented Jun 7, 2022

Here are my findings
mdns.txt

I see that my .local hostname for my machine has 3 addresses when I'm connected - ipv4, ipv6 and localhost (127.0.0.1). If I'm disconnected, the .local hostname is resolved only as localhost and thus advertised only such as.

@tillkamppeter
Copy link
Member Author

I have looked into your file. Things look like as they would come out also on my system.
Especially you get

$ host fedora.local
fedora.local has address <my-ipv4-address>
fedora.local has address <my-ipv4-address-for-virtual-bridge>
fedora.local has IPv6 address <my-ipv6-address>

I do not see the localhost (127.0.0.1) as you say. How did you find that for your .local host name?

@tillkamppeter
Copy link
Member Author

Is CUPS working for you as expected (print with GTK dialog to temporary CUPS queue for local-only service) both when connected and when not connected?

@tillkamppeter
Copy link
Member Author

If you use the name "fedora.local" on your machine, is it resolving to 127.0.0.1 or to your machine's network IP address?

@zdohnal
Copy link
Member

zdohnal commented Jun 8, 2022

I do not see the localhost (127.0.0.1) as you say. How did you find that for your .local host name?

Aha, I was so focused on services being showed on localhost, so I have missed localhost address is missing from the host output - since avahi-browse shows 3 different addresses for the same .local hostname.

Is CUPS working for you as expected (print with GTK dialog to temporary CUPS queue for local-only service) both when connected and when not connected?

Yes - for both sources I've tried - ipp-usb and ps-printer-app. Resolving switched correctly to 127.0.0.1 if I'm disconnected.

If you use the name "fedora.local" on your machine, is it resolving to 127.0.0.1 or to your machine's network IP address?

Looks like it depends whether I'm connected or not - if I have network IP address, then it is used in ping:

$ ping fedora.local
PING fedora.local (<my IP>) 56(84) bytes of data.

when I'm disconnected however (i.e. I don't have network IP, only localhost IP):

$ ping fedora.local
PING fedora.local (127.0.0.1) 56(84) bytes of data.

I guess it happens because we have in /etc/nsswitch.conf:

hosts:      files myhostname mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns

IIUC myhostname takes care of my .local hostname and that is controlled by systemd-resolved. Then any .local hostnames from the network itself (any network printers in the local network) are resolved by nss-mdns+Avahi.

host probably does not count localhost address in - ?probably because some discrepancies between resolved and bind API? - @pemensik , our Fedora/RHEL bind maintainer - could know more details.

However from Fedora printing stack view it works correctly, at least on Fedora.

@tillkamppeter
Copy link
Member Author

At Ubuntu we have only

files mdns4_minimal [NOTFOUND=return] dns

in /etc/nsswitch.conf.

So I will try CUPS without this patch but first adding myhostname to /etc/nsswitch.conf and if this does not solve the problem also resolve [!UNAVAIL=return]. WDYT?

I will also discuss my result with the network experts at Canonical then.

@tillkamppeter
Copy link
Member Author

@zdohnal thank you very much for this hint.

@tillkamppeter
Copy link
Member Author

First I removed the patch from CUPS. With patch I can print to temporary queues for localhost-provided IPP services from the GTK print dialog, without I cannot.

@zdohnal @pemensik I have tried. For that I had to install the Ubuntu/Debian packages libnss-myhostname and libnss-resolve which also added the appropriate entries in /etc/nsswitch.conf. I have restarted cupsd after that and also gedit. I restarted these also after each edit on /etc/nsswitch.conf.

Unfortunately the problem did not go away, I still cannot print to temporary queues for localhost-provided IPP services from the GTK print dialog.

I have also modified the automatically created line in /etc/nsswitch.conf from

hosts:          files mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns myhostname

to

hosts:          files myhostname mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns

Also does not help.

@pemensik
Copy link

pemensik commented Jun 8, 2022

Why should local services on localhost require any kind of discovery other than registration to avahi or CUPS? If services running on the same host need multicast resolution or special plugins, there is probably wrong design somewhere. There should be a simple registration method for local services. Be it DBus or just unix socket. But services running locally should not require sending multicast queries to network.

@pemensik
Copy link

pemensik commented Jun 8, 2022

It is possible to test also each plugin separately, if you are in doubt. Try ahosts database, it provides all records, both IPv4 and IPv6 if found.

getent -s myhostname ahosts fedora

I think when something should resolve to 127.0.0.1 address, its name should be always localhost or localhost.localdomain. <hostname>.local should never resolve to 127.0.0.1. If it does, a bug should be filled on that provider.

@zdohnal
Copy link
Member

zdohnal commented Jun 8, 2022

Why should local services on localhost require any kind of discovery other than registration to avahi or CUPS? If services running on the same host need multicast resolution or special plugins, there is probably wrong design somewhere. There should be a simple registration method for local services. Be it DBus or just unix socket. But services running locally should not require sending multicast queries to network.

Althought off-topic, but to clear this - AFAIK we use the mDNS for local services to unify the processing path for as many devices as possible. So instead of having different processing paths for different networks, local networks and localhost services, we use the same processing for devices at local networks and at localhost (devices from different networks will have a different process - similar as it has now, but internals will be different).

But this is really off-topic to this - in case you want to discuss printing stack architecture, feel free to write to printing-architecture@lists.linux-foundation.org.

@pemensik
Copy link

pemensik commented Jun 8, 2022

Is loopback interface used to send mdns queries as well then?

@zdohnal
Copy link
Member

zdohnal commented Jun 8, 2022

@pemensik hmm, I thought <my_hostname>.local hostname could be resolved to 127.0.0.1 since it is a hostname for your local machine, but if I apply logic from classic DNS, every hostname has a specific IP address which is not localhost... so probably resolved (@pemensik please correct me who does 'myhostname' in Fedora - my guess is resolved) takes the first available address for the hostname and uses it.

I can see from logs that if I'm connected the hostname is resolved to my local address:

Jun 08 12:57:00 fedora cupsd[236782]: [Job 19] Set job-printer-state-message to "Connected to printer.", current level=INFO
Jun 08 12:57:00 fedora cupsd[236782]: [Job 19] Connected to <my_real_ip>:8000...

So though it works, we should really use only localhost for local IPP services.

@tillkamppeter I'll do some regression testing in Fedora with the patch and I'll let you know.

@pemensik
Copy link

pemensik commented Jun 8, 2022

@zdohnal getent ahosts <myhostname> is resolved on Fedora by resolve, myhostname and dns (via systemd-resolved) and they resolve to 127.0.0.2 address for some weird reason. It is not well documented systemd extension. It would not work if specific systemd plugins or services are not used, which is more common on Ubuntu. On more traditional distributions it relied on lines in /etc/hosts, which were created during installation.

@michaelrsweet
Copy link
Member

@pemensik

Is loopback interface used to send mdns queries as well then?

No, but Avahi keeps track of services that are registered for the loopback interface and will return them in a query, and all of those queries happen via Avahi's D-Bus interface...

@pemensik
Copy link

pemensik commented Jun 8, 2022

@pemensik hmm, I thought <my_hostname>.local hostname could be resolved to 127.0.0.1 since it is a hostname for your local machine, but if I apply logic from classic DNS, every hostname has a specific IP address which is not localhost... so probably resolved (@pemensik please correct me who does 'myhostname' in Fedora - my guess is resolved) takes the first available address for the hostname and uses it.

No, I think it tries to export ALL addresses detected on the system, not only small subset. I think getent -s myhostname ahosts $HOSTNAME should report all addresses reported also by ip a.

I can see from logs that if I'm connected the hostname is resolved to my local address:

Jun 08 12:57:00 fedora cupsd[236782]: [Job 19] Set job-printer-state-message to "Connected to printer.", current level=INFO
Jun 08 12:57:00 fedora cupsd[236782]: [Job 19] Connected to <my_real_ip>:8000...

So though it works, we should really use only localhost for local IPP services.

Agreed.

No, but Avahi keeps track of services that are registered for the loopback interface and will return them in a query, and all of those queries happen via Avahi's D-Bus interface...

Great, so Avahi just maintains the list for localhost the same way it does for the network. Hides implementation difference. Just note that collision resolution on mdns can modify local hostname exported to avahi. It should not take just hostname from the system, but hostname used by Avahi.

scheduler/ipp.c Outdated
if (strcmp(nameptr + server_name_len - 7, ".local.") == 0)
server_name_len -= 7;

if (host_len == server_name_len && strncmp(host, nameptr, host_len) == 0)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If length is already known, use memcmp(host, nameptr, host_len) == 0. It should be faster

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should actually be comparing with strncasecmp...

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct. domain names are case insensitive.

scheduler/ipp.c Outdated
sizeof(host), &port, resource, sizeof(resource));

host_len = strlen(host);
if (strcmp(host + host_len - 6, ".local") == 0)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we hardcode local. domain? Perhaps domain should be fetched somehow from Avahi

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are comparing to Avahi's DNS-SD hostname, so we only care about .local.

Copy link

@pemensik pemensik Jun 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt it is common, but mdns nss plugin can configure also different domains than .local. Also, can there be a difference between name ending with dot and without it? In DNS, trailing dot means that name does not get applied search domains from /etc/resolv.conf. Can something like that happen in Avahi? I think trailing dot could be squashed by:

if (host_len>1 && host[host_len-1] == '.')
    host[--host_len] = '\0';

Then it would need just single comparison for local instead of two.

Copy link
Member

@michaelrsweet michaelrsweet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments. But I am still not happy with this...

scheduler/ipp.c Outdated
sizeof(host), &port, resource, sizeof(resource));

host_len = strlen(host);
if (strcmp(host + host_len - 6, ".local") == 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are comparing to Avahi's DNS-SD hostname, so we only care about .local.

@tillkamppeter
Copy link
Member Author

@michaelrsweet before changing/optimizing anything of the code, I want to compare the host name in the requested device URI for the local print queue creation by the create_local_printer() function with the host name the scheduler knows it is running on (DNSSDHostName if available, ServerName otherwise). I am cutting off .local or .local. suffixes from both host names if they are there, before comparing them. So myhost and myhost.local. for example are considered equal. In addition coparison is still case-sensitive and you tell me it shopuld be case-insensitive.

How do I have to compare actually? When can I consider the host name cupsd is running under and the host name in the requested device URI as equal?

Or is it all OK if I simply switch to case-insensitive comparing, as you suggest in your first comment?

@michaelrsweet
Copy link
Member

@pemensik We do try to remove the trailing dot when resolving an mDNS service, but the code here should also check for ".local." on the end.

@tillkamppeter
Copy link
Member Author

@michaelrsweet So how has the comparison yo look like? I Know now that it has to be case-insensitive and with and without dot at the end can be treated equal. Now should I also treat "NAME" and "NAME.local" equal or not?

@michaelrsweet and is the correction of the comparison the only code change needed?

@michaelrsweet
Copy link
Member

@tillkamppeter

@michaelrsweet So how has the comparison yo look like? I Know now that it has to be case-insensitive and with and without dot at the end can be treated equal. Now should I also treat "NAME" and "NAME.local" equal or not?

I wouldn't treat "NAME" and "NAME.local" as the same, since "NAME" doesn't identify a specific domain and might resolve to a different address.

@michaelrsweet and is the correction of the comparison the only code change needed?

I'm still not 100% happy with this change since it depends on the server to detect a local service vs. the client-side code which will also know whether any of the resolved addresses of the service is 127.0.0.1 or ::1 before sending the Create-Local-Printer request...

@tillkamppeter
Copy link
Member Author

@michaelrsweet OK, so what I can only do is to make the comparison case-insensitive and consider only equal if the maximum difference between the host names is a trailing dot or no trailing dot. I do not know ehetjer more can be done server-side. And we cannot bet on the client as as we see with the GTK dialog the client developers do not necessarily use the CUPS APIs (I hope this will improve when the CPDB gets widely adopted).

@michaelrsweet WDYT? Should we for the time being do the case-insensitive comparison plus treatment as equal with or without trailing dot but you will look into a better solution which will be put as soon as you have it?

@michaelrsweet
Copy link
Member

@tillkamppeter For now, sure.

@tillkamppeter
Copy link
Member Author

@michaelrsweet I have updated the code now. If our CUPS actually has a DNSSDServerName (it has Browsing=On, sharing printers) I consider only as equal if the maximum difference is the presence or absence of the trailing dot. Only if we do not have a DNSSDServerName (it has Browsing=Off, not sharing printers) and therefore resort to ServerName I also allow as equal to have the ServerName without and the device URI's host name with .local, as the ServerName is usually without .local. The comparison itself is case-insensitive now.

To print to a temporary CUPS queue for a discovered IPP printer the
client has to send an IPP_OP_CUPS_CREATE_LOCAL_PRINTER IPP request to
the CUPS daemon with the details for creating the temporary queue.
CUPS then calls its create_local_printer() function to actually create
the queue. This is already automatically and correctly done if the
client uses the convenience API of libcups.

The GTK print dialog does not use the convenience API though. It
displays all IPP printers for which CUPS can create temporary queues
correctly, but it fails on services which are only available on the
local machine and not on the network (loopback interface, "localhost")
whereas printing via temporary queue on network/remote services works
perfectly.

The problem is that Avahi advertises the local services not with the
"localhost" host name but with the network host name of the local
machine. The libcups convenience API functions can cope with this and
send correct device URIs with the "localhost" host name to CUPS and so
the temporary queue gets created correctly.

The GTK dialog wants fully asynchronous CUPS operation and throws the
libcups API completely overboard doing all by itself, and sending
incorrect device URIs with the network hostname for the local
services. CUPS creates the temporary queue with this URI then and
fails to do the get-printer-attributes request on the printer to
generate the PPD file, leaving the temporary queue in a non-functional
state.

This commit correct/works around this by checking whether the device
URI's host name is the same as the DNS-SD host name of the local
machine and if so, replaces the device URI's host name by "localhost".

Now one can select local services like IPP-over-USB printers or
Printer Applications in the GTK print dialog and printing on them
through an auto-generated temporary CUPS queue works.

I decided to fix/work around this problem in CUPS as we see that no
every print client developer uses the libcups convenience API.
If cupsd is running without Browsing (when not sharing printers) the
global variable DNSSDHostName of the scheduler is not set, staying
NULL. Therefore the previous commit causes a crash with this
configuration of CUPS.

This commit does a NULL check on DNSSDHostName and falls back to
ServerName if needed, where it also does a NULL check and if this is
also NULL, it refrains from any attempt to correct the device URI's
hostname to "localhost".

As ServerName usually contains the server's hostname without ".local"
suffix but the device URIs coming from Avahi usually have a suffixed
host name (and there are also the ".local" and ".local." variants of
the suffix), we consider hostnames also as equal if one has the
suffix, the other not, or if we have the variants with and without
trailing dot.

In addition, there are also HAVE_DNSSD conditionals added around the
code using DNSSDHostName now.
Improved the comparison of the device URI host name with the CUPS
server's host name to find out whether the temporary queue is for a
local IPP service.

- Compare case-insensitively as host names are case-insensitive

- If we have the DNS-SD host name (DNSSDHostName) of the CUPS server,
  consider names equal if they only differ by the presence or absense
  of a trailing dot ('.')

- If we only have the ServerName (for example with "Browsing = Off",
  not sharing printers), consider also a server name without ".local"
  equal to a device URI host name with ".local" as equal.
@zdohnal
Copy link
Member

zdohnal commented Jun 16, 2022

@tillkamppeter I'll rebase your branch to get the latest cups master branch + your fix, so I can test the latest CUPS master branch with your fix.

@zdohnal zdohnal force-pushed the create-local-printer-localhost-fix branch from 39a23d7 to e5a6bc2 Compare June 16, 2022 09:44
@zdohnal
Copy link
Member

zdohnal commented Jun 16, 2022

Test results - printing via lp using queue based on ps-printer-app (Fedora 37 - Rawhide):

avahi-browse still sees the devices being advertised on all local IP addresses available, but if I print:

D [16/Jun/2022:12:52:56 +0200] [Job 1] Looking up \"localhost\"...
D [16/Jun/2022:12:52:56 +0200] [Job 1] STATE: -connecting-to-device
D [16/Jun/2022:12:52:56 +0200] cupsdMarkDirty(---J-)
D [16/Jun/2022:12:52:56 +0200] cupsdSetBusyState: newbusy="Printing jobs and dirty files", busy="Dirty files"
D [16/Jun/2022:12:52:56 +0200] [Job 1] localhost=[v1.::1]
D [16/Jun/2022:12:52:56 +0200] [Job 1] localhost=127.0.0.1
...
D [16/Jun/2022:12:52:56 +0200] [Job 1] Connecting to localhost:8000
D [16/Jun/2022:12:52:56 +0200] [Job 1] PID 31636 (/usr/lib/cups/filter/texttopdf) exited with no errors.
D [16/Jun/2022:12:52:56 +0200] [Job 1] Connecting to printer.
...
D [16/Jun/2022:12:52:56 +0200] [Job 1] Connected to [v1.::1]:8000...

we use localhost anyway.

If I print from evince (using via ps-printer-app):

D [16/Jun/2022:13:35:58 +0200] [Job 2] Looking up \"localhost\"...
D [16/Jun/2022:13:35:58 +0200] [Job 2] STATE: -connecting-to-device
D [16/Jun/2022:13:35:58 +0200] cupsdMarkDirty(---J-)
D [16/Jun/2022:13:35:58 +0200] cupsdSetBusyState: newbusy="Printing jobs and dirty files", busy="Dirty files"
D [16/Jun/2022:13:35:58 +0200] [Job 2] localhost=[v1.::1]
D [16/Jun/2022:13:35:58 +0200] [Job 2] localhost=127.0.0.1
...
D [16/Jun/2022:13:35:58 +0200] [Job 2] Connecting to localhost:8000
D [16/Jun/2022:13:35:58 +0200] [Job 2] Connecting to printer.
...
D [16/Jun/2022:13:35:58 +0200] [Job 2] Connected to [v1.::1]:8000...

Printing via device created by ipp-usb from evince:

D [16/Jun/2022:14:21:14 +0200] [Job 4] Looking up \"localhost\"...
D [16/Jun/2022:14:21:14 +0200] [Job 4] STATE: -connecting-to-device
D [16/Jun/2022:14:21:14 +0200] cupsdMarkDirty(---J-)
D [16/Jun/2022:14:21:14 +0200] cupsdSetBusyState: newbusy="Printing jobs and dirty files", busy="Dirty files"
D [16/Jun/2022:14:21:14 +0200] [Job 4] localhost=[v1.::1]
D [16/Jun/2022:14:21:14 +0200] [Job 4] localhost=127.0.0.1
...
D [16/Jun/2022:14:21:14 +0200] [Job 4] Connecting to localhost:60000
...
D [16/Jun/2022:14:21:14 +0200] [Job 4] Connected to [v1.::1]:60000...

All jobs ended successfully.

I don't have an IPP Everywhere capable network printer in local network at the office yet (networking still needs to be adjust...), so I'll do the verification with network printer at home.

@zdohnal
Copy link
Member

zdohnal commented Jun 20, 2022

Printing to network printer from evince works as well, using the correct mDNS address.

@zdohnal
Copy link
Member

zdohnal commented Jun 20, 2022

I have tested the PR with DNSSDHostName and ServerName combinations as well, all prints well from evince via temp queue.

The code LGTM, merging for now until we have more complex solution.

@zdohnal zdohnal merged commit ef13e00 into master Jun 20, 2022
@zdohnal
Copy link
Member

zdohnal commented Jun 20, 2022

Thank you for the patch, @tillkamppeter !

@pemensik
Copy link

pemensik commented Oct 11, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request platform issue Issue is specific to an OS or desktop priority-medium
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants