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

[WIP] xdg thumbnails fetching with fallback on mimetype icons #1939

Merged
merged 37 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
37353b7
implemented xdg thumbnails fetching with fallback on mimetype icons f…
Jan 28, 2024
a6271dc
included original license text
Jan 28, 2024
68272ce
added md5 header and source file
Jan 28, 2024
5b64132
implemented xdg compatible thumbnail's creation
Jan 30, 2024
423ee4e
added -preview-cmd string option to program settings
Feb 2, 2024
1b9eec5
support custom command to create images for entries with thumbnail://…
Feb 2, 2024
32a9ffa
fix custom thumbnailer command crash caused by null uri when entry is…
Feb 5, 2024
aa44499
check entry_name is not NULL or empty when generating thumbnails;
Feb 5, 2024
c573765
avoid using gstrvbuilder to build thumbnailer command args
Feb 6, 2024
50d8ed9
fixed static analyzer complain about always wrong condition
Feb 6, 2024
059f748
use g_spawn_check_exit_status to avoid bump to glib 2.70
Feb 6, 2024
e243304
Merge branch 'davatorium:next' into next
giomatfois62 Feb 11, 2024
e6e2f87
removed md5-c dependency and use glib checksum implementation
Feb 12, 2024
600563c
fixed meson build after md5-c library removal
Feb 13, 2024
9d8e0f3
support thumbnail generation in recursivebrowser mode
Feb 13, 2024
b57bc6d
restored check rofi_icon_fetcher_file_is_image
Feb 13, 2024
29a2b39
create thumbnail directories if not existing
Feb 13, 2024
8152a71
use g_malloc0, g_strdup and g_strdup_printf
Feb 13, 2024
c5e13e6
fixed formatting with clang-format
Feb 14, 2024
15e206d
don't wait for jobs in execution when finalizing the icon fetcher wor…
Feb 20, 2024
cfdcc09
destroy and rebuild the icon fetcher worker threadpool when the curre…
Feb 20, 2024
f7fe484
added query_started boolean member to IconFetcherEntry;
Feb 20, 2024
6c5b8be
force icon cache lookup even if the item has a valid icon_fetch_uid (…
Feb 20, 2024
3284837
search binaries in PATH when executing thumbnailer command
Feb 26, 2024
dcf7505
Merge branch 'davatorium:next' into next
giomatfois62 Mar 2, 2024
f5227cc
Merge branch 'next' into next
giomatfois62 Mar 3, 2024
4933d4b
Merge branch 'davatorium:next' into next
giomatfois62 Mar 8, 2024
b179ff0
mark icon query as not started in threadpool item free_func
Mar 9, 2024
58ff766
added listview page_changed_callback; rebuild icon fetcher threadpool…
Mar 9, 2024
97b25eb
[listview] Add missing code documentation param
DaveDavenport Mar 10, 2024
92a7aae
Merge branch 'davatorium:next' into next
giomatfois62 May 16, 2024
5d69c64
Create rofi-thumbnails.5.markdown
giomatfois62 May 16, 2024
46473d4
Updated documentation with apparmor issues and workaround
giomatfois62 May 25, 2024
0d0b476
Merge branch 'next' into next
DaveDavenport Jun 8, 2024
90c4ea8
Merge branch 'next' into next
giomatfois62 Jun 19, 2024
6acf5db
[Doc] Ship rofi-thumbnails.5
lbonn Jun 19, 2024
8a671cb
use a more compact thumbnailer example
giomatfois62 Jun 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ generate-manpage: doc/rofi.1\
doc/rofi-dmenu.5\
doc/rofi-keys.5\
doc/rofi-script.5\
doc/rofi-theme.5
doc/rofi-theme.5 \
doc/rofi-thumbnails.5

doc/rofi.1: doc/rofi.1.markdown
pandoc --standalone --to=man --lua-filter=$(top_srcdir)/doc/man_filter.lua -f markdown-tex_math_dollars -o ./$@ ./$<
Expand All @@ -204,6 +205,8 @@ doc/rofi-script.5: doc/rofi-script.5.markdown
pandoc --standalone --to=man --lua-filter=$(top_srcdir)/doc/man_filter.lua -f markdown-tex_math_dollars -o ./$@ ./$<
doc/rofi-theme.5: doc/rofi-theme.5.markdown
pandoc --standalone --to=man --lua-filter=$(top_srcdir)/doc/man_filter.lua -f markdown-tex_math_dollars -o ./$@ ./$<
doc/rofi-thumbnails.5: doc/rofi-thumbnails.5.markdown
pandoc --standalone --to=man --lua-filter=$(top_srcdir)/doc/man_filter.lua -f markdown-tex_math_dollars -o ./$@ ./$<

endif

Expand All @@ -217,10 +220,12 @@ dist_man5_MANS=\
doc/rofi-dmenu.5\
doc/rofi-keys.5\
doc/rofi-script.5\
doc/rofi-theme.5
doc/rofi-theme.5\
doc/rofi-thumbnails.5

EXTRA_DIST += \
doc/rofi-theme.5.markdown \
doc/rofi-thumbnails.5.markdown \
doc/rofi-debugging.5.markdown \
doc/rofi-script.5.markdown \
doc/rofi-keys.5.markdown \
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ new issue.
- [rofi-debugging](doc/rofi-debugging.5.markdown)
- [rofi-script](doc/rofi-script.5.markdown)
- [rofi-theme-selector](doc/rofi-theme-selector.1.markdown)
- [rofi-thumbnails](doc/rofi-thumbnails.5.markdown)
- [rofi-keys](doc/rofi-keys.5.markdown)
- [rofi-dmenu](doc/rofi-dmenu.5.markdown)

Expand Down
3 changes: 3 additions & 0 deletions config/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ Settings config = {
/** Whether to load and show icons */
.show_icons = FALSE,

/** Custom command to generate preview icons */
.preview_cmd = NULL,

/** Terminal to use. (for ssh and open in terminal) */
.terminal_emulator = "rofi-sensible-terminal",
.ssh_client = "ssh",
Expand Down
1 change: 1 addition & 0 deletions doc/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ man_files = [
'rofi-keys.5',
'rofi-script.5',
'rofi-theme.5',
'rofi-thumbnails.5',
]

fs = import('fs')
Expand Down
85 changes: 85 additions & 0 deletions doc/rofi-thumbnails.5.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# rofi-thumbnails(5)

## NAME

**rofi-thumbnails** - Rofi thumbnails system

## DESCRIPTION

**rofi** is now able to show thumbnails for all file types where an XDG compatible thumbnailer is present in the system.

This is done by default in filebrowser and recursivebrowser mode, if **rofi** is launched with the `-show-icons` argument.

In a custom user script or dmenu mode, it is possible to produce entry icons using XDG thumbnailers by adding the prefix `thumbnail://` to the filename
specified after `\0icon\x1f`, for example:

```bash
echo -en "EntryName\0icon\x1fthumbnail://path/to/file\n" | rofi -dmenu -show-icons
```

### XDG thumbnailers

XDG thumbnailers are files with a ".thumbnailer" suffix and a structure similar to ".desktop" files for launching applications. They are placed in `/usr/share/thumbnailers/` or `$HOME/.local/share/thumbnailers/`, and contain a list of mimetypes, for which is possible to produce the thumbnail image, and a string with the command to create said image. The example below shows the content of `librsvg.thumbnailer`, a thumbnailer for svg files using librsvg:

```
[Thumbnailer Entry]
TryExec=/usr/bin/gdk-pixbuf-thumbnailer
Exec=/usr/bin/gdk-pixbuf-thumbnailer -s %s %u %o
MimeType=image/svg+xml;image/svg+xml-compressed;
```

The images produced are named as the md5sum of the input files and placed, depending on their size, in the XDG thumbnails directories: `$HOME/.cache/thumbnails/{normal,large,x-large,xx-large}`. They are then loaded by **rofi** as entry icons and can also be used by file managers like Thunar, Caja or KDE Dolphin to show their thumbnails. Additionally, if a thumbnail for a file is found in the thumbnails directories (produced previously by **rofi** or a file manager), **rofi** will load it instead of calling the thumbnailer.

If a suitable thumbnailer for a given file is not found, **rofi** will try to use the corresponding mimetype icon from the icon theme.

### Custom command to create thumbnails

It is possible to use a custom command to generate thumbnails for generic entry names, for example a script that downloads an icon given its url or selects different icons depending on the input. This can be done providing the `-preview-cmd` argument followed by a string with the command to execute, with the following syntax:

```
rofi ... -preview-cmd 'path/to/script_or_cmd "{input}" "{output}" "{size}"'
```

**rofi** will call the script or command substituting `{input}` with the input entry icon name (the string after `\0icon\x1fthumbnail://`), `{output}` with the output filename of the thumbnail and `{size}` with the requested thumbnail size. The script or command is responsible of producing a thumbnail image (if possible respecting the requested size) and saving it in the given `{output}` filename.

### Issues with AppArmor

In Linux distributions using AppArmor (such as Ubuntu and Debian), the default rules shipped can cause issues with thumbnails generation. If that is the case, AppArmor can be disabled by issuing the following commands

```
sudo systemctl stop apparmor
sudo systemctl disable apparmor
```

In alternative, the following apparmor profile con be placed in a file named /etc/apparmor.d/usr.bin.rofi

```
#vim:syntax=apparmor
# AppArmor policy for rofi

#include <tunables/global>

/usr/bin/rofi {
#include <abstractions/base>

# TCP/UDP network access for NFS
network inet stream,
network inet6 stream,
network inet dgram,
network inet6 dgram,

/usr/bin/rofi mr,

@{HOME}/ r,
@{HOME}/** rw,
owner @{HOME}/.cache/thumbnails/** rw,
}
```

then run

```
apparmor_parser -r /etc/apparmor.d/usr.bin.rofi
```

to reload the rule. This assumes that **rofi** binary is in /usr/bin, that is the case of a standard package installation.
3 changes: 3 additions & 0 deletions include/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ typedef struct {

/** Whether to load and show icons */
gboolean show_icons;

/** Custom command to generate preview icons */
char *preview_cmd;

/** Terminal to use */
char *terminal_emulator;
Expand Down
11 changes: 10 additions & 1 deletion include/widgets/listview.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,27 @@ typedef void (*listview_selection_changed_callback)(listview *lv,
*/
typedef void (*listview_mouse_activated_cb)(listview *, gboolean, void *);


/**
* Callback when current page is changed.
*/
typedef void (*listview_page_changed_cb)(void);


/**
* @param parent The widget's parent.
* @param name The name of the to be created widget.
* @param cb The update callback.
* @param page_cb The page change callback.
* @param udata The user data to pass to the callback
* @param eh The height of one element
* @param reverse Reverse the listview order.
*
* @returns a new listview
*/
listview *listview_create(widget *parent, const char *name,
listview_update_callback cb, void *udata,
listview_update_callback cb,
listview_page_changed_cb page_cb, void *udata,
unsigned int eh, gboolean reverse);

/**
Expand Down
3 changes: 0 additions & 3 deletions source/modes/dmenu.c
Original file line number Diff line number Diff line change
Expand Up @@ -721,9 +721,6 @@ static cairo_surface_t *dmenu_get_icon(const Mode *sw,
if (dr->icon_name == NULL) {
return NULL;
}
if (dr->icon_fetch_uid > 0 && dr->icon_fetch_size == height) {
return rofi_icon_fetcher_get(dr->icon_fetch_uid);
}
uint32_t uid = dr->icon_fetch_uid =
rofi_icon_fetcher_query(dr->icon_name, height);
dr->icon_fetch_size = height;
Expand Down
7 changes: 4 additions & 3 deletions source/modes/filebrowser.c
Original file line number Diff line number Diff line change
Expand Up @@ -603,11 +603,12 @@ static cairo_surface_t *_get_icon(const Mode *sw, unsigned int selected_line,
(FileBrowserModePrivateData *)mode_get_private_data(sw);
g_return_val_if_fail(pd->array != NULL, NULL);
FBFile *dr = &(pd->array[selected_line]);
if (dr->icon_fetch_uid > 0 && dr->icon_fetch_size == height) {
return rofi_icon_fetcher_get(dr->icon_fetch_uid);
}
if (rofi_icon_fetcher_file_is_image(dr->path)) {
dr->icon_fetch_uid = rofi_icon_fetcher_query(dr->path, height);
} else if (dr->type == RFILE) {
gchar* _path = g_strconcat("thumbnail://", dr->path, NULL);
dr->icon_fetch_uid = rofi_icon_fetcher_query(_path, height);
g_free(_path);
} else {
dr->icon_fetch_uid = rofi_icon_fetcher_query(icon_name[dr->type], height);
}
Expand Down
10 changes: 5 additions & 5 deletions source/modes/recursivebrowser.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,14 +493,14 @@ static cairo_surface_t *_get_icon(const Mode *sw, unsigned int selected_line,
(FileBrowserModePrivateData *)mode_get_private_data(sw);
g_return_val_if_fail(pd->array != NULL, NULL);
FBFile *dr = &(pd->array[selected_line]);
if (dr->icon_fetch_uid > 0 && dr->icon_fetch_size == height) {
return rofi_icon_fetcher_get(dr->icon_fetch_uid);
}
if (rofi_icon_fetcher_file_is_image(dr->path)) {
lbonn marked this conversation as resolved.
Show resolved Hide resolved
dr->icon_fetch_uid = rofi_icon_fetcher_query(dr->path, height);
} else if (dr->type == RFILE) {
gchar* _path = g_strconcat("thumbnail://", dr->path, NULL);
dr->icon_fetch_uid = rofi_icon_fetcher_query(_path, height);
g_free(_path);
} else {
dr->icon_fetch_uid =
rofi_icon_fetcher_query(rb_icon_name[dr->type], height);
dr->icon_fetch_uid = rofi_icon_fetcher_query(rb_icon_name[dr->type], height);
}
dr->icon_fetch_size = height;
return rofi_icon_fetcher_get(dr->icon_fetch_uid);
Expand Down
Loading
Loading