bash# xdg-open /tmp/dw.pdf
Filename "file:///tmp/dw.pdf" does not exist or is not a regular file
A simple check of the default handler shows that everything is fine:
bash# xdg-mime query default application/pdf
evince.desktop
..but for fun, let's try to change it and see what happens.
bash# xdg-mime default apvlv.desktop application/pdf
bash# xdg-open /tmp/dw.pdf
Filename "file:///tmp/dw.pdf" does not exist or is not a regular file
Nothing.
Grepping for the error in /usr/bin/xdg-open comes up empty. It's odd that two unrelated programs (evince and apvlv) would have the incorrect error message (the file does exist and is regular), or that they would both fail to handle file:// URIs. How does xdg-open actually route these requests?
Turns out it depends on your window manager. If you are running Enlightenment, xdg-open performs the following:
open_enlightenment()
{
enlightenment_open "$1"
if [ $? -eq 0 ]; then
exit_success
else
exit_failure_operation_failed
fi
}
Replacing enlightenment_open "$1" with open_generic "$1" works. Can we invoke open_generic when enlightenment_open fails? Turns out we can't, because enlightenment_open returns 0 (success) even when the file isn't opened.
Fixing enlightenment_open might do the trick. The relevant code (enlightenment.git/ src/bin/e_open.c) is here:
char **itr;
int ret = EXIT_SUCCESS;
for (itr = cmds; *itr != NULL; itr++)
{
/* Question: should we execute them in parallel? */
int r = system(*itr);
if (r < 0)
fprintf(stderr, "ERROR: %s executing %s\n", strerror(errno),
*itr);
free(*itr);
if (r > 0) /* Question: should we stop the loop on first faiure? */
ret = r;
}
free(cmds);
return ret;
It turns out that the status of what enlightenment_open is calling is ignored. But what is it calling? Adding the line fprintf(stderr, "Trying %s\n", *itr); after the system() call uncovers what is actually happening:
bash# make src/bin/enlightenment_open
CC src/bin/src_bin_enlightenment_open-e_open.o
CCLD src/bin/enlightenment_open
bash# src/bin/enlightenment_open /tmp/dw.pdf
Filename "file:///tmp/dw.pdf" does not exist or is not a regular file
TRYING evince-previewer 'file:///tmp/dw.pdf
Where the hell did evince-previewer come from? To make a long story short, xdg-open (and enlightenment_open, and all other *_open tools) uses /usr/bin/mimeopen as a backend.
This utility operates on files, not mime-types:
bash# mimeopen -a /tmp/dw.pdf
Please choose an application
1) Print Preview (evince-previewer)
2) Document Viewer (evince)
3) vprerex (vprerex)
4) GNU Image Manipulation Program (gimp)
use application #
Cancelled
OK, so that is where evince-previewer is coming from. A quick test shows that the actual bug is caused by evince-previewer not understanding file URIs:
bash# evince-previewer file:///tmp/dw.pdf
Filename "file:///tmp/dw.pdf" does not exist or is not a regular file
bash# evince file:///tmp/dw.pdf
(evince:21480): Gtk-WARNING **: gtk_widget_size_allocate(): attempt to allocate widget with width -82 and height 15
That Gtk warning accompanies evince loading and displaying the file just fine.
Changing the handler for PDFs using mimeopen turns out to work just fine:
bash# mimeopen -d /tmp/dw.pdf
Please choose a default application for files of type application/pdf
1) Print Preview (evince-previewer)
2) Document Viewer (evince)
3) vprerex (vprerex)
4) GNU Image Manipulation Program (gimp)
5) Other...
use application #2
Opening "/tmp/dw.pdf" with Document Viewer (application/pdf)
(evince:21510): Gtk-WARNING **: gtk_widget_size_allocate(): attempt to allocate widget with width -82 and height 15
bash# xdg-open /tmp/dw.pdf
(evince:21550): Gtk-WARNING **: gtk_widget_size_allocate(): attempt to allocate widget with width -82 and height 15
xdg-open /tmp/a.pdf
(evince:21602): Gtk-WARNING **: gtk_widget_size_allocate(): attempt to allocate widget with width -82 and height 1
Of course, that doesn't mean that evince-previewer is the only bug. Since evince-previewer returns 1 (failure), enlightenment_open should be returning 1 instead of 0:
int ret = EXIT_FAILURE;
for (itr = cmds; *itr != NULL; itr++)
{
int r = system(*itr);
if (r < 0)
fprintf(stderr, "ERROR: %s executing %s\n", strerror(errno),
*itr);
free(*itr);
ret = r;
}
...and xdg-open should check the return value and fallback to open_generic:
enlightenment_open "$1"
if [ $? -eq 0 ]; then
exit_success
else
open_generic "$1"
if [ $? -eq 0 ]; then
exit_success
else
exit_failure_operation_failed
fi
fi
Let's not even get started on why xdg-open doesn't propagate changes back to mimeopen. Wait, why doesn't it?
UPDATE: looks like there's something deeply wrong with with the xdg-* utilities:
bash# xdg-settings get default-web-browser
xdg-settings: unknown desktop environment
The problem here is that xdg-settings performs its own check for desktop environment (modularity, people!) and, of course, implements this poorly. If the desktop environment is detected (as is Enlightenment), but is not KDE|Gnome|XFCE|MATE, it returns "unknown desktop environment". If the environment is not detected, a generic handler is called. There are some very confused people working on this software.
The fix is to modify xdg-settings, changing the default case statement
*)
exit_failure_operation_impossible "unknown desktop environment"
;;
to
*)
dispatch_specific generic "$@"
;;
* For those interested: install tslib and rebuild EFL from source, then run the following on a virtual terminal:
ELM_ENGINE=fb /usr/local/bin/terminology -f=nexus/20
UPDATE: looks like there's something deeply wrong with with the xdg-* utilities:
bash# xdg-settings get default-web-browser
xdg-settings: unknown desktop environment
The problem here is that xdg-settings performs its own check for desktop environment (modularity, people!) and, of course, implements this poorly. If the desktop environment is detected (as is Enlightenment), but is not KDE|Gnome|XFCE|MATE, it returns "unknown desktop environment". If the environment is not detected, a generic handler is called. There are some very confused people working on this software.
The fix is to modify xdg-settings, changing the default case statement
*)
exit_failure_operation_impossible "unknown desktop environment"
;;
to
*)
dispatch_specific generic "$@"
;;
* For those interested: install tslib and rebuild EFL from source, then run the following on a virtual terminal:
ELM_ENGINE=fb /usr/local/bin/terminology -f=nexus/20
Yes, the -b option for a backgroud image will work, as will tytls, tyop, and tycat.
No comments:
Post a Comment