Merge commit '1a1dc7282f5ed010af874398b5b3d70ea7cda8e8' into wayland

This commit is contained in:
lbonn 2021-09-06 13:00:57 +02:00
commit deb9330a0d
178 changed files with 5880 additions and 3057 deletions

View file

@ -5,7 +5,6 @@ tone will be closed without discussion. Everybody has it own way of working;
What might be the norm for you, might not be for others. Therefore be verbose in
your description.
**The issue tracker is for bugs only.**
This is an attempt to keep the issue tracker clean and searchable.
@ -54,8 +53,6 @@ Issue high-jacking, e.g. adding a request/issue to an existing issue, is very
disruptive.
Please create a new issue, if it is similar it will be marked duplicate.
# Creating a feature request
@ -72,10 +69,10 @@ When reporting a feature request include the following information:
* A use-case for the feature.
If possible try to explain how you would expect to use feature.
For example, should it be a configuration option or a hot-key.
For example, should it be a configuration option or a hot-key.
Requesting a feature is no guarantee it will be added.
**Please do not submit reports related to wayland, see
[here](https://github.com/DaveDavenport/rofi/wiki/Wayland) for more
information.**

View file

@ -1,8 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: discussion forum
url: https://github.com/davatorium/rofi/discussions
about: Please ask and answer questions here.
- name: Rofi subreddit
url: https://www.reddit.com/r/qtools/
about: Please ask and answer questions here.
- name: Rofi IRC channel
url: https://webchat.freenode.net/?channels=#rofi
url: https://web.libera.chat/?channels=#rofi
about: Please ask and answer question in real time here.

View file

@ -14,8 +14,10 @@ Any report missing these informations will be labeled as “Incomplete Report -
:exclamation:
## Before creating a feature request
- [ ] I checked the *next* branch to see if the feature has already been
implemented
- [ ] I searched existing reports to see if it is already requested.
@ -48,7 +50,6 @@ Output of `rofi -help` (in a [gist](https://gist.github.com/), please paste the
- Include a link to your private config
- Include screenshots/casts of your issue
**Please do not submit reports related to wayland, see
[here](https://github.com/DaveDavenport/rofi/wiki/Wayland) for more
information.**

View file

@ -6,7 +6,7 @@ before_script:
- apt-get install --force-yes -y autoconf automake make libx11-dev libpango1.0-dev libcairo2-dev libstartup-notification0-dev libxcb-icccm4-dev libxcb-util0-dev libxcb-xinerama0-dev libxcb-xkb-dev libx11-xcb-dev
- apt-get install --force-yes -y libxcb1-dev xvfb discount xdotool fluxbox libxkbcommon-dev libxkbcommon-x11-dev libxcb-ewmh-dev xutils-dev libtool lcov libxcb-randr0-dev doxygen python flex bison librsvg2-dev texinfo
- git clone --recursive https://github.com/Airblader/xcb-util-xrm.git
- cd xcb-util-xrm
- cd xcb-util-xrm
- ./autogen.sh --prefix=/usr
- make
- sudo make install
@ -34,5 +34,5 @@ build-rofi:
artifacts:
expire_in: 2 weeks
paths:
- coverage
- coverage
- doc/html

View file

@ -35,6 +35,7 @@ addons:
- libxcb-xinerama0-dev
- libxcb-xkb-dev
- libxcb-xrm-dev
- libxcb-cursor-dev
- libxkbcommon-dev
- libxkbcommon-dev
- libxkbcommon-x11-dev

24
AUTHORS
View file

@ -1,23 +1,26 @@
Aaron Ash
Adrià Farrés
Aaron Ash
Adrià Farrés
Anton Löfgren
Avatar
bendem
Benjamin Cremer
Benjamin R. Haskell
Bruno Braga
Buglloc
Chris Salzberg
Dan Beste
daemoni
Dan Beste
Daniel Hahler
DanteFireX
Dave Davenport
Deiwin Sarjas
Dimitar Yordanov
Edwin Pujols
eigengrau
Eric Engeström
Fangrui Song
Fangrui Song
fice-t
Florian Franzen
Florian Franzen
Gabriel Holodak
Gareth Poole
Georgios Bitzes
@ -29,11 +32,13 @@ James Vaughan
Jason Pleau
Jasper Lievisse Adriaanse
Klemens Schölhorn
koppa
lbonn
Marcin Sedlak
marduk
Michael Vetter
Moritz Maxeiner
Nick87720z
Niklas Haas
N. Izumi
Paulo Flabiano Smorigo
@ -42,6 +47,7 @@ qedi
Quentin Glidic
Rasmus Steinke
Roomcays
seanpringle
Sebastian Reuße
Simon Hanna
Stanislav Seletskiy
@ -50,11 +56,7 @@ Thorsten Wißmann
Tilman Blumenbach
Tobias Kortkamp
Tom Hinton
TonCherAmi
vimeitor
Wieland Hoffmann
Yaroslav
seanpringle
vimeitor
daemoni
eigengrau
koppa
qedi

View file

@ -139,14 +139,14 @@ v1.5.0:
- Fix drun history implementation. (#579)
- Add gentoo install instruction. (#685)
v1.4.2:
v1.4.2:
- Add sort to manpage. (#682)
- Add tranaparent to theme manpage. (#688)
- Re-add theme headers. (#679)
- Fix super key. (#684)
- Unknown option libnkutils:uuid. (#677)
- Mode window is not found. (#686)
- Fix meson build in dist file.
- Fix meson build in dist file.
v1.4.1: All Hail Rasi
- Bump meson release version
@ -233,7 +233,7 @@ v1.3.0: Dan vs. Greg: The never ending story.
- Add Control+G for cancel (#452)
- Add padding option to textbox (#449)
- Ctrl-click does alternate accept entry. (#429)
- Hide window decoration in normal window mode.
- Hide window decoration in normal window mode.
- Click to exit option. (#460)
- Fix cursor blinking on moving. (#462)
- Remove entry from history if fails to execute (#466)
@ -244,16 +244,16 @@ v1.3.0: Dan vs. Greg: The never ending story.
- Improve scrollbar behaviour.
Removals
- opacity option. The transparency support in the theme can do the same and more.
v1.2.0
New Features
- Highlight matched part of the string.
- Make window switcher string customizable.
Improvements
- Improved selection mode in dmenu with selection counter.
- Improved selection mode in dmenu with selection counter.
- Improved selection mode with 'dot' indicator.
- Fix Current Desktop window switcher.
- Fix launching in terminal.
- Fix launching in terminal.
- Supports include in config.
- Add Control+k remove till eol keybinding.
- Change clear line to Control+w and make Control+u remove till sol (matching readline)
@ -471,7 +471,7 @@ v1.1.0
- Better way to determine font height.
- Fix font vertical centering.
- One-off when pasting text.
- Improve rendering of boxes (fixed height and margins)
- Improve rendering of boxes (fixed height and margins)
- Fix modi switcher boxes size+layout.
- Reduce work on redraws (do not always calculate new size/position), set text, etc.
- OO-ify the switchers.

View file

@ -1,10 +1,10 @@
#!/bin/bash
#!/usr/bin/env bash
MAX_DESKTOPS=20
WORKSPACES=$(seq -s '\n' 1 1 ${MAX_DESKTOPS})
WORKSPACES=$(seq -s '\n' 1 1 "${MAX_DESKTOPS}")
EMPTY_WORKSPACE=$( (i3-msg -t get_workspaces | tr ',' '\n' | grep num | awk -F: '{print int($2)}' ; \
echo -e ${WORKSPACES} ) | sort -n | uniq -u | head -n 1)
EMPTY_WORKSPACE=$( (i3-msg -t get_workspaces | tr ',' '\n' | grep num | awk -F: '{print int($2)}' ; \
echo -e "${WORKSPACES}" ) | sort -n | uniq -u | head -n 1)
i3-msg workspace ${EMPTY_WORKSPACE}
i3-msg workspace "${EMPTY_WORKSPACE}"

View file

@ -1,18 +1,17 @@
#!/bin/bash
#!/usr/bin/env bash
if [ -z $@ ]
then
function gen_workspaces()
gen_workspaces()
{
i3-msg -t get_workspaces | tr ',' '\n' | grep "name" | sed 's/"name":"\(.*\)"/\1/g' | sort -n
}
echo empty; gen_workspaces
else
WORKSPACE=$@
if [ x"empty" = x"${WORKSPACE}" ]
if [ "${WORKSPACE}" = "empty" ]
then
i3_empty_workspace.sh >/dev/null
elif [ -n "${WORKSPACE}" ]

View file

@ -3,7 +3,7 @@
# Various options for the file browser script:
ROFI_FB_GENERIC_FO="xdg-open" # command used for opening the selection
ROFI_FB_PREV_LOC_FILE=~/.local/share/rofi/rofi_fb_prevloc
ROFI_FB_HISTORY_FILE=~/.local/share/rofi/rofi_fb_history
ROFI_FB_HISTORY_FILE=~/.local/share/rofi/rofi_fb_history
ROFI_FB_HISTORY_MAXCOUNT=5 # maximum number of history entries
# Comment the next variable to always start in the last visited directory,
# otherwise rofi_fb will start in the specified directory:
@ -11,14 +11,13 @@ ROFI_FB_START_DIR=$HOME # starting directory
# Uncomment the following line to disable history:
# ROFI_FB_NO_HISTORY=1
# Beginning of the script:
# Create the directory for the files of the script
if [ ! -d $(dirname "${ROFI_FB_PREV_LOC_FILE}") ]
if [ ! -d "$(dirname "${ROFI_FB_PREV_LOC_FILE}")" ]
then
mkdir -p "$(dirname "${ROFI_FB_PREV_LOC_FILE}")"
fi
if [ ! -d $(dirname "${ROFI_FB_HISTORY_FILE}") ]
if [ ! -d "$(dirname "${ROFI_FB_HISTORY_FILE}")" ]
then
mkdir -p "$(dirname "${ROFI_FB_HISTORY_FILE}")"
fi
@ -34,8 +33,8 @@ fi
# Read last location, otherwise we default to $ROFI_FB_START_DIR or $PWD.
if [ -f "${ROFI_FB_PREV_LOC_FILE}" ]
then
ROFI_FB_CUR_DIR=$(cat "${ROFI_FB_PREV_LOC_FILE}")
fi
ROFI_FB_CUR_DIR=$(cat "${ROFI_FB_PREV_LOC_FILE}")
fi
# Handle argument.
if [ -n "$@" ]
@ -53,7 +52,7 @@ if [ ! -d "${ROFI_FB_CUR_DIR}" ]
then
if [ -x "${ROFI_FB_CUR_DIR}" ]
then
coproc ( "${ROFI_FB_CUR_DIR}" > /dev/null 2>&1 )
coproc ( "${ROFI_FB_CUR_DIR}" >/dev/null 2>&1 )
exec 1>&-
exit;
elif [ -f "${ROFI_FB_CUR_DIR}" ]
@ -64,13 +63,13 @@ then
sed -i "s|${ROFI_FB_CUR_DIR}|##deleted##|g" "${ROFI_FB_HISTORY_FILE}"
sed -i '/##deleted##/d' "${ROFI_FB_HISTORY_FILE}"
echo "${ROFI_FB_CUR_DIR}" >> "${ROFI_FB_HISTORY_FILE}"
if [ $( wc -l < "${ROFI_FB_HISTORY_FILE}" ) -gt ${ROFI_FB_HISTORY_MAXCOUNT} ]
if [ "$( wc -l < "${ROFI_FB_HISTORY_FILE}" )" -gt "${ROFI_FB_HISTORY_MAXCOUNT}" ]
then
sed -i 1d "${ROFI_FB_HISTORY_FILE}"
fi
fi
# Open the selected entry with $ROFI_FB_GENERIC_FO
coproc ( "${ROFI_FB_GENERIC_FO}" "${ROFI_FB_CUR_DIR}" > /dev/null 2>&1 )
coproc ( "${ROFI_FB_GENERIC_FO}" "${ROFI_FB_CUR_DIR}" >/dev/null 2>&1 )
if [ -d "${ROFI_FB_START_DIR}" ]
then
echo "${ROFI_FB_START_DIR}" > "${ROFI_FB_PREV_LOC_FILE}"

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash
if [ x"$@" = x"quit" ]
if [ "$@" = "quit" ]
then
exit 0
fi

View file

@ -10,36 +10,35 @@ You can also use [Meson](https://mesonbuild.com/) as an alternative.
### For building:
* C compiler that supports the c99 standard. (gcc or clang)
* make
* autoconf
* automake (1.11.3 or up)
* pkg-config
* flex 2.5.39 or higher
* bison
* check (Can be disabled using the `--disable-check` configure flag)
check is used for build-time tests and does not affect functionality.
* Developer packages of the external libraries
* glib-compile-resources
* C compiler that supports the c99 standard. (gcc or clang)
* make
* autoconf
* automake (1.11.3 or up)
* pkg-config
* flex 2.5.39 or higher
* bison
* check (Can be disabled using the `--disable-check` configure flag)
check is used for build-time tests and does not affect functionality.
* Developer packages of the external libraries
* glib-compile-resources
### External libraries
* libpango
* libpangocairo
* libcairo
* libcairo-xcb
* libglib2.0 >= 2.40
* gmodule-2.0
* gio-unix-2.0
* libgdk-pixbuf-2.0
* libstartup-notification-1.0
* libxkbcommon >= 0.4.1
* libxkbcommon-x11
* libxcb (sometimes split, you need libxcb, libxcb-xkb and libxcb-randr libxcb-xinerama)
* xcb-util
* xcb-util-wm (sometimes split as libxcb-ewmh and libxcb-icccm)
* xcb-util-xrm [new module might not be available in your distribution. The source can be found
here](https://github.com/Airblader/xcb-util-xrm/)
* libpango
* libpangocairo
* libcairo
* libcairo-xcb
* libglib2.0 >= 2.40
* gmodule-2.0
* gio-unix-2.0
* libgdk-pixbuf-2.0
* libstartup-notification-1.0
* libxkbcommon >= 0.4.1
* libxkbcommon-x11
* libxcb (sometimes split, you need libxcb, libxcb-xkb and libxcb-randr libxcb-xinerama)
* xcb-util
* xcb-util-wm (sometimes split as libxcb-ewmh and libxcb-icccm)
* xcb-util-cursor
On debian based systems, the developer packages are in the form of: `<package>-dev` on rpm based
`<package>-devel`.
@ -50,27 +49,19 @@ On debian based systems, the developer packages are in the form of: `<package>-d
Create a build directory and enter it:
```
mkdir build && cd build
```
mkdir build && cd build
Check dependencies and configure build system:
```
../configure
```
../configure
Build Rofi:
```
make
```
make
The actual install, execute as root (if needed):
```
make install
```
make install
The default installation prefix is: `/usr/local/` use `./configure --prefix={prefix}` to install into another location.
@ -78,21 +69,15 @@ The default installation prefix is: `/usr/local/` use `./configure --prefix={pre
Check dependencies and configure build system:
```
meson setup build
```
meson setup build
Build Rofi:
```
ninja -C build
```
ninja -C build
The actual install, execute as root (if needed):
```
ninja -C build install
```
ninja -C build install
The default installation prefix is: `/usr/local/` use `meson setup build --prefix={prefix}` to install into another location.
@ -105,29 +90,21 @@ The GitHub Pages version of these directions may be out of date. Please use
If you don't have a checkout:
```
git clone --recursive https://github.com/DaveDavenport/rofi
cd rofi/
```
git clone --recursive https://github.com/DaveDavenport/rofi
cd rofi/
If you already have a checkout:
```
cd rofi/
git pull
git submodule update --init
```
cd rofi/
git pull
git submodule update --init
For Autotools you have an extra step, to generate build system:
```
autoreconf -i
```
autoreconf -i
From this point, use the same steps you use for a release.
## Options for configure
When you run the configure step there are several options you can configure.
@ -137,36 +114,29 @@ After the initial setup, use `meson configure build`.
The most useful one to set the installation prefix:
```
# Autotools
../configure --prefix=<installation path>
# Autotools
../configure --prefix=<installation path>
# Meson
meson setup build --prefix <installation path>
```
# Meson
meson setup build --prefix <installation path>
f.e.
```
# Autotools
../configure --prefix=/usr/
# Autotools
../configure --prefix=/usr/
# Meson
meson setup build --prefix /usr
```
# Meson
meson setup build --prefix /usr
### Install locally
or to install locally:
```
# Autotools
../configure --prefix=${HOME}/.local/
# Meson
meson setup build --prefix ${HOME}/.local
```
# Autotools
../configure --prefix=${HOME}/.local/
# Meson
meson setup build --prefix ${HOME}/.local
## Options for make
@ -176,26 +146,22 @@ When you run make you can tweak the build process a little.
Show the commands called:
```
# Autotools
make V=1
# Autotools
make V=1
# Meson
ninja -C build -v
```
# Meson
ninja -C build -v
### Debug build
Compile with debug symbols and no optimization, this is useful for making backtraces:
```
# Autotools
make CFLAGS="-O0 -g3" clean rofi
# Autotools
make CFLAGS="-O0 -g3" clean rofi
# Meson
meson configure build --debug
ninja -C build
```
# Meson
meson configure build --debug
ninja -C build
### Get a backtrace
@ -204,13 +170,11 @@ mouse. So if it crashes in GDB you are stuck.
The best way to go is to enable core file. (ulimit -c unlimited in bash) then make rofi crash. You
can then load the core in GDB.
```
# Autotools
gdb rofi core
# Autotools
gdb rofi core
# Meson (because it uses a separate build directory)
gdb build/rofi core
```
# Meson (because it uses a separate build directory)
gdb build/rofi core
> Where the core file is located and what its exact name is different on each distributions. Please consult the
> relevant documentation.
@ -219,37 +183,26 @@ gdb build/rofi core
### Debian or Ubuntu
```
apt install rofi
```
apt install rofi
### Fedora
rofi from [russianfedora repository](http://ru.fedoracommunity.org/repository)
and also
[Yaroslav's COPR (Cool Other Package Repo)](https://copr.fedorainfracloud.org/coprs/yaroslav/i3desktop/)
dnf install rofi
### ArchLinux
```
pacman -S rofi
```
pacman -S rofi
### Gentoo
An ebuild is available, `x11-misc/rofi`. It's up to date, but you may need to
enable ~arch to get the latest release:
```
echo 'x11-misc/rofi ~amd64' >> /etc/portage/package.accept_keywords
```
echo 'x11-misc/rofi ~amd64' >> /etc/portage/package.accept_keywords
for amd64 or:
```
echo 'x11-misc/rofi ~x86' >> /etc/portage/package.accept_keywords
```
echo 'x11-misc/rofi ~x86' >> /etc/portage/package.accept_keywords
for i386.
@ -259,12 +212,8 @@ To install it, simply issue `emerge rofi`.
On both openSUSE Leap and openSUSE Tumbleweed rofi can be installed using:
```
sudo zypper install rofi
```
sudo zypper install rofi
### FreeBSD
```
sudo pkg install rofi
```
sudo pkg install rofi

View file

@ -1,5 +1,5 @@
# Specify automake version.
AUTOMAKE_OPTIONS = 1.11.3
AUTOMAKE_OPTIONS = 1.11.3
ACLOCAL_AMFLAGS = -I subprojects/libnkutils -I subprojects/libgwater ${ACLOCAL_FLAGS}
@ -19,7 +19,6 @@ include $(top_srcdir)/libgwater-xcb-nolibtool.mk
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = pkgconfig/rofi.pc
BUILT_SOURCES=\
lexer/theme-parser.h\
lexer/theme-parser.c\
@ -155,7 +154,6 @@ rofi_CFLAGS=\
-I$(top_builddir)/\
-Werror=missing-prototypes\
-DSYSCONFDIR=\"$(sysconfdir)\"\
-DTHEME_CONVERTER\
-DPLUGIN_PATH=\"${libdir}/rofi\"\
-DTHEME_DIR=\"$(themedir)\"
@ -188,7 +186,6 @@ EXTRA_DIST += \
doc/rofi-sensible-terminal.1.markdown \
doc/rofi.1.markdown
##
# Readme.md
##
@ -224,6 +221,7 @@ theme_DATA=\
themes/blue.rasi\
themes/c64.rasi\
themes/dmenu.rasi\
themes/docu.rasi\
themes/glue_pro_blue.rasi\
themes/gruvbox-common.rasi\
themes/gruvbox-dark-hard.rasi\
@ -238,7 +236,9 @@ theme_DATA=\
themes/sidebar.rasi\
themes/solarized.rasi\
themes/solarized_alternate.rasi\
themes/fancy.rasi
themes/fancy.rasi\
themes/iggy.rasi\
themes/iggy.jpg
##
# Extra DIST
@ -256,12 +256,12 @@ EXTRA_DIST+=\
script/get_git_rev.sh\
$(theme_DATA)\
doc/default_theme.rasi\
doc/default_configuration.rasi\
Changelog
##
# Indent
##
update-manpage: $(top_srcdir)/doc/rofi-theme-selector.1.markdown $(top_srcdir)/doc/rofi.1.markdown $(top_srcdir)/doc/rofi-theme.5.markdown $(top_srcdir)/doc/rofi-script.5.markdown ${top_srcdir}/doc/rofi-sensible-terminal.1.markdown
go-md2man -in $(top_srcdir)/doc/rofi.1.markdown -out $(top_srcdir)/doc/rofi.1
go-md2man -in $(top_srcdir)/doc/rofi-theme-selector.1.markdown -out $(top_srcdir)/doc/rofi-theme-selector.1
@ -287,8 +287,6 @@ if USE_CHECK
check_PROGRAMS+=mode_test theme_parser_test helper_tokenize
endif
history_test_CFLAGS=\
$(AM_CFLAGS)\
$(glib_CFLAGS)\
@ -305,7 +303,6 @@ history_test_LDADD=\
$(glib_LIBS)\
$(NKUTILS_LIBS)
history_test_SOURCES=\
source/history.c\
config/config.c\
@ -349,6 +346,7 @@ helper_pidfile_SOURCES=\
include/mode.h\
include/mode-private.h\
source/helper.c\
source/theme.c\
source/rofi-types.c\
include/rofi-types.h\
include/helper.h\
@ -385,7 +383,7 @@ box_test_SOURCES=\
source/css-colors.c\
include/theme.h\
include/css-colors.h\
config/config.c\
config/config.c\
test/box-test.c
scrollbar_test_LDADD=$(textbox_test_LDADD)
@ -401,7 +399,7 @@ scrollbar_test_SOURCES=\
source/css-colors.c\
include/theme.h\
include/css-colors.h\
config/config.c\
config/config.c\
test/scrollbar-test.c
textbox_test_SOURCES=\
@ -463,11 +461,11 @@ helper_test_SOURCES=\
include/helper-theme.h\
include/xrmoptions.h\
source/xrmoptions.c\
source/theme.c\
source/rofi-types.c\
include/rofi-types.h\
test/helper-test.c
helper_test_CFLAGS=\
$(AM_CFLAGS)\
$(glib_CFLAGS)\
@ -493,13 +491,13 @@ helper_test_LDADD=\
$(libsn_LIBS)\
$(cairo_LIBS)
helper_expand_SOURCES=\
config/config.c\
include/rofi.h\
include/mode.h\
include/mode-private.h\
source/helper.c\
source/theme.c\
include/helper.h\
include/helper-theme.h\
include/xrmoptions.h\
@ -521,6 +519,7 @@ helper_config_cmdline_parser_SOURCES=\
include/mode.h\
include/mode-private.h\
source/helper.c\
source/theme.c\
source/rofi-types.c\
include/rofi-types.h\
include/helper.h\
@ -529,15 +528,15 @@ helper_config_cmdline_parser_SOURCES=\
source/xrmoptions.c\
test/helper-config-cmdline-parser.c
if USE_CHECK
mode_test_CFLAGS=$(textbox_test_CFLAGS) $(check_CFLAGS)
mode_test_LDADD=$(textbox_test_LDADD) $(check_LIBS)
mode_test_SOURCES=\
config/config.c\
test/mode-test.c\
source/dialogs/help-keys.c\
source/dialogs/help-keys.c\
source/helper.c\
source/theme.c\
source/mode.c\
source/rofi-types.c\
include/rofi-types.h\
@ -553,6 +552,7 @@ helper_tokenize_SOURCES=\
include/mode.h\
include/mode-private.h\
source/helper.c\
source/theme.c\
source/rofi-types.c\
include/rofi-types.h\
include/helper.h\
@ -560,7 +560,6 @@ helper_tokenize_SOURCES=\
include/xrmoptions.h\
source/xrmoptions.c\
test/helper-tokenize.c
endif
TESTS+=\
@ -586,18 +585,15 @@ test-x: $(bin_PROGRAMS)
MESON_BUILD_ROOT="$(top_builddir)" \
$(top_srcdir)/test/run_all_tests.sh
.PHONY: indent
indent: $(SOURCES)
uncrustify -c $(top_srcdir)/data/uncrustify.cfg --replace $^
.PHONY: cppcheck
cppcheck: $(rofi_SOURCES)
cppcheck --std=c99 --platform=unix64 --enable=all -Uerror_dialog --inconclusive -I $(top_srcdir)/include/ $^
.PHONY: ohcount
ohcount: $(rofi_SOURCES)
ohcount -i $(top_srcdir)/source/ $(top_srcdir)/include/
@ -621,7 +617,7 @@ coverage: coverage/index.html
coverage-cli: coverage.info
lcov -l $^
coverage.info: $(top_builddir)/test/*.gcda $(top_builddir)/source/*.gcda $(top_builddir)/source/**/*.gcda
lcov --capture --directory $(top_builddir) --output-file coverage.info
lcov --capture --directory $(top_builddir) --output-file coverage.info
lcov -r $@ /usr/include/\* -o $@
coverage/index.html: coverage.info
@ -641,5 +637,4 @@ EXTRA_DIST += \
subprojects/libnkutils/meson_options.txt \
subprojects/libgwater/xcb/meson.build \
meson_options.txt \
subprojects/xcb \
meson.build

281
README.md
View file

@ -1,4 +1,4 @@
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/ca0310962a7c4b829d0c57f1ab023531)](https://app.codacy.com/app/davatorium/rofi?utm_source=github.com&utm_medium=referral&utm_content=davatorium/rofi&utm_campaign=Badge_Grade_Settings)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/ca0310962a7c4b829d0c57f1ab023531)](https://app.codacy.com/app/davatorium/rofi?utm_source=github.com\&utm_medium=referral\&utm_content=davatorium/rofi\&utm_campaign=Badge_Grade_Settings)
[![Build Status](https://travis-ci.org/davatorium/rofi.svg?branch=master)](https://travis-ci.org/davatorium/rofi)
[![codecov.io](https://codecov.io/github/davatorium/rofi/coverage.svg?branch=master)](https://codecov.io/github/davatorium/rofi?branch=master)
[![Issues](https://img.shields.io/github/issues/davatorium/rofi.svg)](https://github.com/davatorium/rofi/issues)
@ -7,7 +7,7 @@
[![Downloads](https://img.shields.io/github/downloads/davatorium/rofi/total.svg)](https://github.com/davatorium/rofi/releases)
[![Coverity](https://scan.coverity.com/projects/3850/badge.svg)](https://scan.coverity.com/projects/davedavenport-rofi)
[![Forum](https://img.shields.io/badge/forum-online-green.svg)](https://reddit.com/r/qtools/)
[![Packages](https://repology.org/badge/tiny-repos/rofi.svg)](https://repology.org/metapackage/rofi/versions)
[![Packages](https://repology.org/badge/tiny-repos/rofi.svg)](https://repology.org/metapackage/rofi/versions)
# A window switcher, Application launcher and dmenu replacement
@ -17,7 +17,7 @@
**Rofi** started as a clone of simpleswitcher, written by [Sean Pringle](http://github.com/seanpringle/simpleswitcher) - a
popup window switcher roughly based on [superswitcher](http://code.google.com/p/superswitcher/).
Simpleswitcher laid the foundations, and therefore Sean Pringle deserves most of the credit for this tool. **Rofi**
(renamed, as it lost the *simple* property) has been extended with extra features, like an application launcher and
(renamed, as it lost the *simple* property) has been extended with extra features, like an application launcher and
ssh-launcher, and can act as a drop-in dmenu replacement, making it a very versatile tool.
**Rofi**, like dmenu, will provide the user with a textual list of options where one or more can be selected.
@ -25,181 +25,45 @@ This can either be running an application, selecting a window, or options provid
Its main features are:
* Fully configurable keyboard navigation
* Type to filter
- Tokenized: type any word in any order to filter
- Case insensitive (togglable)
- Support for fuzzy-, regex-, and glob matching
* UTF-8 enabled
- UTF-8-aware string collating
- International keyboard support (`e -> è)
* RTL language support
* Cairo drawing and Pango font rendering
* Built-in modes:
- Window switcher mode
- EWMH compatible WM
- Application launcher
- Desktop file application launcher
- SSH launcher mode
- Combi mode, allowing several modes to be merged into one list
* History-based ordering — last 25 choices are ordered on top based on use (optional)
* Levenshtein distance ordering of matches (optional)
* Drop-in dmenu replacement
- Many added improvements
* Easily extensible using scripts
* Theming
* Fully configurable keyboard navigation
* Type to filter
* Tokenized: type any word in any order to filter
* Case insensitive (togglable)
* Support for fuzzy-, regex-, and glob matching
* UTF-8 enabled
* UTF-8-aware string collating
* International keyboard support (\`e -> è)
* RTL language support
* Cairo drawing and Pango font rendering
* Built-in modes:
* Window switcher mode
* EWMH compatible WM
* Application launcher
* Desktop file application launcher
* SSH launcher mode
* Combi mode, allowing several modes to be merged into one list
* History-based ordering — last 25 choices are ordered on top based on use (optional)
* Levenshtein distance or fzf like sorting of matches (optional)
* Drop-in dmenu replacement
* Many added improvements
* Easily extensible using scripts and plugins
* Advanced Theming
**Rofi** has several built-in modes implementing common use cases and can be extended by scripts (either called from
**Rofi** or calling **Rofi**).
**Rofi** has several built-in modi implementing common use cases and can be extended by scripts (either called from
**Rofi** or calling **Rofi**) or plugins.
Below is a list of the different modes:
Below is a list of the different modi:
## Window Switcher
* **run**: launch applications from $PATH, with option to launch in terminal.
* **drun**: launch applications based on desktop files. It tries to be compliant to the XDG standard.
* **window**: Switch between windows on an EWMH compatible window manager.
* **ssh**: Connect to a remote host via ssh.
* **file-browser**: A basic file-browser for opening files.
* **keys**: list internal keybindings.
* **script**: Write (limited) custom mode using simple scripts.
* **combi**: Combine multiple modi into one.
![Window List](https://davatorium.github.io/rofi/images/rofi/window-list.png)
The window switcher shows the following informations in columns (can be customized):
1. Desktop name
2. Window class
3. Window title
Window mode features:
* Closing applications with `Shift-Delete`
* Custom command with `Shift-Return`
## Application launcher
![run mode](https://davatorium.github.io/rofi/images/rofi/run-dialog.png)
The run mode allows users to quickly search for and launch a program.
Run mode features:
* `Shift-Return` to run the selected program in a terminal
* Favorites list, with frequently used programs sorted on top
* Custom entries, like aliases, added by executing a command
## Desktop File Application launcher
The desktop run mode allows users to quickly search and launch an application from the *freedesktop.org* Desktop
Entries. These are used by most Desktop Environments to populate launchers and menus.
Drun mode features:
* Favorites list, with frequently used programs sorted on top
* Auto starting terminal applications in a terminal
## SSH launcher
![SSH Launcher](https://davatorium.github.io/rofi/images/rofi/ssh-dialog.png)
Quickly `ssh` into remote machines. Parses `~/.ssh/config` and `~/.ssh/known_hosts` to find hosts.
## Script mode
Loads external scripts to add modes to **Rofi**, for example a file-browser.
```
rofi -show fb -modi fb:../Examples/rofi-file-browser.sh
```
## COMBI mode
Combine multiple modes in one view. This is especially useful when merging the window and run mode into one view.
Allowing to quickly switch to an application, either by switching to it when it is already running or starting it.
Example to combine Desktop run and the window switcher:
```
rofi -combi-modi window,drun -show combi -modi combi
```
## dmenu replacement
![DMENU replacement (running teiler)](https://davatorium.github.io/rofi/images/rofi/dmenu-replacement.png)
Drop in dmenu replacement. (Screenshot shows rofi used by
[teiler](https://github.com/carnager/teiler) ).
**Rofi** features several improvements over dmenu to improve usability. There is the option to add
an extra message bar (`-mesg`), pre-entering of text (`-filter`), or selecting entries based on a
pattern (`-select`). Also highlighting (`-u` and `-a`) options and modi to force user to select one
provided option (`-only-match`). In addition to this, rofi's dmenu mode can select multiple lines and
write them to stdout.
# Usage
If used with `-show [mode]`, rofi will immediately open in the specified [mode].
If used with `-dmenu`, rofi will use data from STDIN to let the user select an option.
For example, to show a run dialog:
`rofi -show run`
To show a ssh dialog:
`rofi -show ssh`
## dmenu
If rofi is passed the `-dmenu` option, or run as `dmenu` (ie, /usr/bin/dmenu is symlinked to /usr/bin/rofi),
it will use the data passed from STDIN.
```
~/scripts/my_script.sh | rofi -dmenu
echo -e "Option #1\nOption #2\nOption #3" | rofi -dmenu
```
In both cases, rofi will output the user's selection to STDOUT.
## Switching Between Modi
Type `Shift-/Left/Right` to switch between active modi.
## Key bindings
| Key | Action |
|:-------------------------------------|:-------------------------------------------------------------------|
|`Ctrl-v, Insert` | Paste from clipboard |
|`Ctrl-Shift-v, Shift-Insert` | Paste primary selection |
|`Ctrl-w` | Clear the line |
|`Ctrl-u` | Delete till the start of line |
|`Ctrl-a` | Move to beginning of line |
|`Ctrl-e` | Move to end of line |
|`Ctrl-f, Right` | Move forward one character |
|`Alt-f, Ctrl-Right` | Move forward one word |
|`Ctrl-b, Left` | Move back one character |
|`Alt-b, Ctrl-Left` | Move back one word |
|`Ctrl-d, Delete` | Delete character |
|`Ctrl-Alt-d` | Delete word |
|`Ctrl-h, Backspace, Shift-Backspace` | Backspace (delete previous character) |
|`Ctrl-Alt-h` | Delete previous word |
|`Ctrl-j,Ctrl-m,Enter` | Accept entry |
|`Ctrl-n,Down` | Select next entry |
|`Ctrl-p,Up` | Select previous entry |
|`Page Up` | Go to the previous page |
|`Page Down` | Go to the next page |
|`Ctrl-Page Up` | Go to the previous column |
|`Ctrl-Page Down` | Go to the next column |
|`Ctrl-Enter` | Use entered text as a command (in `ssh/run modi`) |
|`Shift-Enter` | Launch the application in a terminal (in run mode) |
|`Shift-Enter` | Return the selected entry and move to the next item while keeping Rofi open. (in dmenu) |
|`Shift-Right` | Switch to the next modi. The list can be customized with the -modi option. |
|`Shift-Left` | Switch to the previous modi. The list can be customized with the -modi option. |
|`Ctrl-Tab` | Switch to the next modi. The list can be customized with the -modi option. |
|`Ctrl-Shift-Tab` | Switch to the previous modi. The list can be customized with the -modi option. |
|`Ctrl-space` | Set selected item as input text. |
|`Shift-Del` | Delete entry from history. |
|`grave` | Toggle case sensitivity. |
|`Alt-grave` | Toggle levenshtein sort. |
|`Alt-Shift-S` | Take a screenshot and store it in the Pictures directory. |
For the full list of key bindings, see: `rofi -show keys` or `rofi -help`.
**Rofi** is known to work on Linux and BSD.
# Wayland support
@ -232,52 +96,26 @@ If you find something does not work and is not listed here, please open a PR.
I do not intend to make releases from this fork at the moment, but will simply try to keep it regularly in sync with the develop branch upstream.
# Configuration
# Screenshots
There are currently three methods of setting configuration options:
* Local configuration. Normally, depending on XDG, in `~/.config/rofi/config`. This uses the Xresources format.
* Xresources: A method of storing key values in the Xserver. See
[here](https://en.wikipedia.org/wiki/X_resources) for more information.
* Command line options: Arguments are passed to **Rofi**.
A distribution can ship defaults in `/etc/rofi.conf`.
The Xresources options and the command line options are aliased. To define option X set:
`rofi.X: value`
In the Xresources file. To set/override this from command line pass the same key
prefixed with '-':
`rofi -X value`
To get a list of available options formatted as Xresources entries, run:
`rofi -dump-Xresources`
or in a more readable format:
`rofi -help`
The configuration system supports the following types:
* String
* Integer (signed and unsigned)
* Char
* Boolean
The Boolean option has a non-default command line syntax, to enable option X you do:
`rofi -X`
to disable it:
`rofi -no-X`
![screenshot](https://raw.githubusercontent.com/davatorium/rofi/next/releasenotes/1.6.0/icons.png)
![screenshot2](https://raw.githubusercontent.com/davatorium/rofi/next/releasenotes/1.6.0/icons2.png)
![default](https://raw.githubusercontent.com/davatorium/rofi/next/releasenotes/1.4.0/rofi-no-fzf.png)
# Manpage
For more detailed information, please see the [manpage](doc/rofi.1.markdown), the [wiki](https://github.com/davatorium/rofi/wiki), or the [forum](https://reddit.com/r/qtools/).
For more up to date information, please see the manpages:
* Manpages:
* [rofi](doc/rofi.1.markdown)
* [rofi-theme](doc/rofi-theme.5.markdown)
* [rofi-script](doc/rofi-script.5.markdown)
* [rofi-theme-selector](doc/rofi-theme-selector.1.markdown)
* Discussion places:
* [Reddit](https://reddit.com/r/qtools/)
* [GitHub Discussions](https://github.com/davatorium/rofi/discussions)
* IRC (#rofi on irc.libera.chat)
* [wiki](https://github.com/davatorium/rofi/wiki) (Currently unmaintained).
# Installation
@ -288,9 +126,8 @@ install **Rofi**.
Rofi is not:
* A preview application. In other words, it will not show a (small) preview of images, movies or other files.
* A UI toolkit.
* A library to be used in other applications.
* An application that can support every possible use-case. It tries to be generic enough to be usable by everybody.
Specific functionality can be added using scripts.
* Just a dmenu replacement. The dmenu functionality is a nice 'extra' to **rofi**, not its main purpose.
* A UI toolkit.
* A library to be used in other applications.
* An application that can support every possible use-case. It tries to be generic enough to be usable by everybody.
* Specific functionality can be added using scripts or plugins, many exists.
* Just a dmenu replacement. The dmenu functionality is a nice 'extra' to **rofi**, not its main purpose.

View file

@ -46,14 +46,6 @@ Settings config = {
#else
.modi = "run,ssh",
#endif
/** Border width around the window. */
.menu_bw = 1,
/** The width of the switcher. (0100 in % > 100 in pixels) */
.menu_width = 50,
/** Maximum number of options to show. */
.menu_lines = 15,
/** Number of columns */
.menu_columns = 1,
/** Font */
.menu_font = "mono 12",
@ -87,8 +79,6 @@ Settings config = {
*
*/
.location = WL_CENTER,
/** Padding between elements */
.padding = 5,
/** Y offset */
.y_offset = 0,
/** X offset */
@ -118,10 +108,10 @@ Settings config = {
/** Parse ~/.ssh/known_hosts file in ssh view. */
.parse_known_hosts = TRUE,
/** Modi to combine into one view. */
.combi_modi = "window,run",
.tokenize = TRUE,
.matching = "normal",
.matching_method = MM_NORMAL,
.combi_modi = "window,run",
.tokenize = TRUE,
.matching = "normal",
.matching_method = MM_NORMAL,
/** Desktop entries to match in drun */
.drun_match_fields = "name,generic,exec,categories,keywords",
@ -138,38 +128,22 @@ Settings config = {
.window_match_fields = "all",
/** Monitor */
.monitor = "-5",
/** set line margin */
.line_margin = 2,
.line_padding = 1,
/** Set filter */
.filter = NULL,
/** Separator style: dash/solid */
.separator_style = "dash",
/** Hide scrollbar */
.hide_scrollbar = FALSE,
.fullscreen = FALSE,
.fake_transparency = FALSE,
.dpi = -1,
.threads = 0,
.scroll_method = 0,
.scrollbar_width = 8,
.fake_background = "screenshot",
.window_format = "{w} {c} {t}",
.click_to_exit = TRUE,
.show_match = TRUE,
.theme = NULL,
.color_normal = NULL,
.color_active = NULL,
.color_urgent = NULL,
.color_window = NULL,
.plugin_path = PLUGIN_PATH,
.max_history_size = 25,
.combi_hide_mode_prefix = FALSE,
.dpi = -1,
.threads = 0,
.scroll_method = 0,
.window_format = "{w} {c} {t}",
.click_to_exit = TRUE,
.theme = NULL,
.plugin_path = PLUGIN_PATH,
.max_history_size = 25,
.combi_hide_mode_prefix = FALSE,
.matching_negate_char = '-',
.cache_dir = NULL,
.window_thumbnail = FALSE,
.cache_dir = NULL,
.window_thumbnail = FALSE,
/** drun cache */
.drun_use_desktop_cache = FALSE,
@ -179,5 +153,9 @@ Settings config = {
.benchmark_ui = FALSE,
/** normalize match */
.normalize_match = FALSE
.normalize_match = FALSE,
/** steal focus */
.steal_focus = FALSE,
/** fallback icon */
.application_fallback_icon = NULL
};

View file

@ -1,4 +1,4 @@
AC_INIT([rofi], [1.6.1], [https://github.com/davatorium/rofi/],[],[https://reddit.com/r/qtools/])
AC_INIT([rofi], [1.6.1-dev], [https://github.com/davatorium/rofi/],[],[https://reddit.com/r/qtools/])
AC_CONFIG_SRCDIR([source/rofi.c])
AC_CONFIG_HEADER([config.h])
@ -7,7 +7,7 @@ AH_BOTTOM([#include "gitconfig.h"])
dnl ---------------------------------------------------------------------
dnl Lex & Bison language parser.
dnl ---------------------------------------------------------------------
AC_PROG_LEX([flex])
AC_PROG_LEX
AC_PROG_YACC
@ -144,9 +144,9 @@ NK_INIT([bindings xdg-theme])
PKG_CHECK_MODULES([glib], [glib-2.0 >= ${glib_min_version} gio-unix-2.0 gmodule-2.0])
AC_DEFINE_UNQUOTED([GLIB_VERSION_MIN_REQUIRED], [(G_ENCODE_VERSION(${glib_min_major},${glib_min_minor}))], [The lower GLib version supported])
AC_DEFINE_UNQUOTED([GLIB_VERSION_MAX_ALLOWED], [(G_ENCODE_VERSION(${glib_min_major},${glib_min_minor}))], [The highest GLib version supported])
GW_CHECK_XCB([xcb-aux xcb-xkb xkbcommon xkbcommon-x11 xcb-ewmh xcb-icccm xcb-xrm xcb-randr xcb-xinerama])
GW_CHECK_XCB([xcb-aux xcb-xkb xkbcommon xkbcommon-x11 xcb-ewmh xcb-icccm xcb-cursor xcb-randr xcb-xinerama])
PKG_CHECK_MODULES([pango], [pango pangocairo])
PKG_CHECK_MODULES([cairo], [cairo cairo-xcb])
PKG_CHECK_MODULES([cairo], [cairo cairo-xcb])
PKG_CHECK_MODULES([libsn], [libstartup-notification-1.0 ])
PKG_CHECK_MODULES([gdkpixbuf], [gdk-pixbuf-2.0])

View file

@ -1,85 +1,84 @@
#
# My favorite format
#
code_width = 240
nl_max = 2
ls_func_split_full = True
indent_with_tabs = 0 # 1=indent to level only, 2=indent with tabs
input_tab_size = 8 # original tab size
output_tab_size = 4 # new tab size
indent_columns = output_tab_size
indent_label = 2 # pos: absolute col, neg: relative column
indent_align_string = False # align broken strings
indent_brace = 0
code_width = 240
nl_max = 2
ls_func_split_full = True
indent_with_tabs = 0 # 1=indent to level only, 2=indent with tabs
input_tab_size = 8 # original tab size
output_tab_size = 4 # new tab size
indent_columns = output_tab_size
indent_label = 2 # pos: absolute col, neg: relative column
indent_align_string = False # align broken strings
indent_brace = 0
nl_enum_brace = add # "enum {" vs "enum \n {"
nl_union_brace = add # "union {" vs "union \n {"
nl_struct_brace = add # "struct {" vs "struct \n {"
nl_do_brace = remove # "do {" vs "do \n {"
nl_if_brace = remove # "if () {" vs "if () \n {"
nl_for_brace = remove # "for () {" vs "for () \n {"
nl_else_brace = remove # "else {" vs "else \n {"
nl_while_brace = remove # "while () {" vs "while () \n {"
nl_switch_brace = add # "switch () {" vs "switch () \n {"
# nl_func_var_def_blk = 1
# nl_before_case = 1
nl_fcall_brace = add # "foo() {" vs "foo()\n{"
nl_fdef_brace = add # "int foo() {" vs "int foo()\n{"
# nl_after_return = TRUE
nl_brace_while = remove
nl_brace_else = add
nl_squeeze_ifdef = FALSE
nl_enum_brace = add # "enum {" vs "enum \n {"
nl_union_brace = add # "union {" vs "union \n {"
nl_struct_brace = add # "struct {" vs "struct \n {"
nl_do_brace = remove # "do {" vs "do \n {"
nl_if_brace = remove # "if () {" vs "if () \n {"
nl_for_brace = remove # "for () {" vs "for () \n {"
nl_else_brace = remove # "else {" vs "else \n {"
nl_while_brace = remove # "while () {" vs "while () \n {"
nl_switch_brace = add # "switch () {" vs "switch () \n {"
# nl_func_var_def_blk = 1
# nl_before_case = 1
nl_fcall_brace = add # "foo() {" vs "foo()\n{"
nl_fdef_brace = add # "int foo() {" vs "int foo()\n{"
# nl_after_return = TRUE
nl_brace_while = remove
nl_brace_else = add
nl_squeeze_ifdef = FALSE
mod_paren_on_return = remove # "return 1;" vs "return (1);"
mod_full_brace_if = add # "if (a) a--;" vs "if (a) { a--; }"
mod_full_brace_for = add # "for () a--;" vs "for () { a--; }"
mod_full_brace_do = add # "do a--; while ();" vs "do { a--; } while ();"
mod_full_brace_while = add # "while (a) a--;" vs "while (a) { a--; }"
mod_paren_on_return = remove # "return 1;" vs "return (1);"
mod_full_brace_if = add # "if (a) a--;" vs "if (a) { a--; }"
mod_full_brace_for = add # "for () a--;" vs "for () { a--; }"
mod_full_brace_do = add # "do a--; while ();" vs "do { a--; } while ();"
mod_full_brace_while = add # "while (a) a--;" vs "while (a) { a--; }"
sp_before_semi = remove
sp_paren_paren = add # space between (( and ))
sp_return_paren = add # "return (1);" vs "return(1);"
sp_sizeof_paren = add # "sizeof (int)" vs "sizeof(int)"
sp_before_sparen = add # "if (" vs "if("
sp_after_sparen = force # "if () {" vs "if (){"
sp_after_cast = add # "(int) a" vs "(int)a"
sp_inside_braces = add # "{ 1 }" vs "{1}"
sp_inside_braces_struct = force # "{ 1 }" vs "{1}"
sp_inside_braces_enum = force # "{ 1 }" vs "{1}"
sp_inside_paren = add
sp_inside_fparen = add
sp_inside_sparen = add
#sp_type_func = ignore
sp_assign = force
sp_arith = force
sp_bool = force
sp_compare = force
sp_assign = force
sp_after_comma = force
sp_func_def_paren = add # "int foo (){" vs "int foo(){"
sp_func_call_paren = add # "foo (" vs "foo("
sp_func_proto_paren = add # "int foo ();" vs "int foo();"
sp_before_semi = remove
sp_paren_paren = add # space between (( and ))
sp_return_paren = add # "return (1);" vs "return(1);"
sp_sizeof_paren = add # "sizeof (int)" vs "sizeof(int)"
sp_before_sparen = add # "if (" vs "if("
sp_after_sparen = force # "if () {" vs "if (){"
sp_after_cast = add # "(int) a" vs "(int)a"
sp_inside_braces = add # "{ 1 }" vs "{1}"
sp_inside_braces_struct = force # "{ 1 }" vs "{1}"
sp_inside_braces_enum = force # "{ 1 }" vs "{1}"
sp_inside_paren = add
sp_inside_fparen = add
sp_inside_sparen = add
#sp_type_func = ignore
sp_assign = force
sp_arith = force
sp_bool = force
sp_compare = force
sp_assign = force
sp_after_comma = force
sp_func_def_paren = add # "int foo (){" vs "int foo(){"
sp_func_call_paren = add # "foo (" vs "foo("
sp_func_proto_paren = add # "int foo ();" vs "int foo();"
align_with_tabs = FALSE # use tabs to align
align_on_tabstop = FALSE # align on tabstops
align_enum_equ_span = 4
align_nl_cont = TRUE
align_var_def_span = 2
align_var_def_inline = TRUE
align_var_def_star_style = 1
align_var_def_colon = TRUE
align_assign_span = 1
align_struct_init_span = 3
align_var_struct_span = 3
align_right_cmt_span = 3
align_pp_define_span = 3
align_pp_define_gap = 4
align_number_left = TRUE
align_typedef_span = 5
align_typedef_gap = 3
align_with_tabs = FALSE # use tabs to align
align_on_tabstop = FALSE # align on tabstops
align_enum_equ_span = 4
align_nl_cont = TRUE
align_var_def_span = 2
align_var_def_inline = TRUE
align_var_def_star_style = 1
align_var_def_colon = TRUE
align_assign_span = 1
align_struct_init_span = 3
align_var_struct_span = 3
align_right_cmt_span = 3
align_pp_define_span = 3
align_pp_define_gap = 4
align_number_left = TRUE
align_typedef_span = 5
align_typedef_gap = 3
# cmt_star_cont = TRUE
eat_blanks_before_close_brace = TRUE
eat_blanks_after_open_brace = TRUE
# cmt_star_cont = TRUE
eat_blanks_before_close_brace = TRUE
eat_blanks_after_open_brace = TRUE

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash
function shout()
shout()
{
echo -en "Normal Row\nAlternateRow\nNormal Row active\nAlternateRow Active\nNormal Row urgent\nAlternateRow urgent"
echo -en "\nSelected Row"
@ -14,4 +14,4 @@ sleep 5
scrot
sleep 1
killall rofi
wait $P
wait "$P"

View file

@ -0,0 +1,16 @@
configuration {
// Timeout from user input.
timeout {
// The delay after inactivity to execute action.
delay: 0;
// The action to execute once the delay expires.
action: "kb-cancel";
}
// File browser modi.
filebrowser {
sorting-method: "name";
directories-first: true;
}
}

View file

@ -35,6 +35,7 @@ element {
padding: 1px ;
spacing: 5px ;
border: 0;
cursor: pointer;
}
element normal.normal {
background-color: var(normal-background);
@ -76,11 +77,13 @@ element-text {
background-color: rgba ( 0, 0, 0, 0 % );
text-color: inherit;
highlight: inherit;
cursor: inherit;
}
element-icon {
background-color: rgba ( 0, 0, 0, 0 % );
size: 1.0000em ;
text-color: inherit;
cursor: inherit;
}
window {
padding: 5;
@ -121,6 +124,7 @@ sidebar {
button {
spacing: 0;
text-color: var(normal-foreground);
cursor: pointer;
}
button selected {
background-color: var(selected-normal-background);
@ -129,12 +133,12 @@ button selected {
num-filtered-rows, num-rows {
text-color: grey;
expand: false;
expand: false;
}
textbox-num-sep {
text-color: grey;
expand: false;
str: "/";
expand: false;
str: "/";
}
inputbar {
padding: 1px ;
@ -147,10 +151,11 @@ case-indicator {
text-color: var(normal-foreground);
}
entry {
spacing: 0;
text-color: var(normal-foreground);
spacing: 0;
text-color: var(normal-foreground);
placeholder-color: grey;
placeholder: "Type to filter";
placeholder: "Type to filter";
cursor: text;
}
prompt {
spacing: 0;

View file

@ -64,6 +64,8 @@ Rofi sets the following environment variable when executing the script:
.SS \fB\fCROFI\_RETV\fR
.PP
An integer number with the current state:
.RS
.IP \(bu 2
\fB0\fP: Initial call of script.
.IP \(bu 2
@ -71,7 +73,9 @@ An integer number with the current state:
.IP \(bu 2
\fB2\fP: Selected a custom entry.
.IP \(bu 2
\fB10\-28\fP: Custom keybinding 1\-19
\fB10\-28\fP: Custom keybinding 1\-19 ( need to be explicitly enabled by script ).
.RE
.SS \fB\fCROFI\_INFO\fR
.PP
@ -96,6 +100,8 @@ For example to set the prompt:
.PP
The following extra options exists:
.RS
.IP \(bu 2
\fBprompt\fP: Update the prompt text.
.IP \(bu 2
@ -109,7 +115,11 @@ The following extra options exists:
.IP \(bu 2
\fBdelim\fP: Set the delimiter for for next rows. Default is '\\n' and this option should finish with this. Only call this on first call of script, it is remembered for consecutive calls.
.IP \(bu 2
\fBno\-custom\fP: Only accept listed entries, ignore custom input.
\fBno\-custom\fP: If set to 'true'; only accept listed entries, ignore custom input.
.IP \(bu 2
\fBuse\-hot\-keys\fP: If set to true, it enabled the Custom keybindings for script. Warning this breaks the normal rofi flow.
.RE
.SH Parsing row options
.PP
@ -130,6 +140,8 @@ For example:
.PP
The following options are supported:
.RS
.IP \(bu 2
\fBicon\fP: Set the icon for that row.
.IP \(bu 2
@ -139,6 +151,8 @@ The following options are supported:
.IP \(bu 2
\fBinfo\fP: Info that, on selection, gets placed in the \fB\fCROFI\_INFO\fR environment variable. This entry does not get searched.
.RE
.PP
multiple entries can be passed using the \fB\fC\\x1f\fR separator.
@ -151,6 +165,23 @@ multiple entries can be passed using the \fB\fC\\x1f\fR separator.
.fi
.RE
.SH Executing external program
.PP
If you want to launch an external program from the script, you need to make sure it is launched in the background.
If not rofi will wait for its output (to display).
.PP
In bash the best way to do this is using \fB\fCcoproc\fR\&.
.PP
.RS
.nf
coproc ( myApp > /dev/null 2>\&1 )
.fi
.RE
.SH DASH shell
.PP
If you use the \fB\fCdash\fR shell for your script, take special care with how dash handles escaped values for the separators.

View file

@ -2,7 +2,7 @@
## NAME
**rofi script mode** - Rofi format for scriptable modi.
**rofi script mode** - Rofi format for scriptable modi.
## DESCRIPTION
@ -57,7 +57,7 @@ An integer number with the current state:
* **0**: Initial call of script.
* **1**: Selected an entry.
* **2**: Selected a custom entry.
* **10-28**: Custom keybinding 1-19
* **10-28**: Custom keybinding 1-19 ( need to be explicitly enabled by script ).
### `ROFI_INFO`
@ -82,7 +82,8 @@ The following extra options exists:
* **urgent**: Mark rows as urgent. (for syntax see the urgent option in dmenu mode)
* **active**: Mark rows as active. (for syntax see the active option in dmenu mode)
* **delim**: Set the delimiter for for next rows. Default is '\n' and this option should finish with this. Only call this on first call of script, it is remembered for consecutive calls.
* **no-custom**: Only accept listed entries, ignore custom input.
* **no-custom**: If set to 'true'; only accept listed entries, ignore custom input.
* **use-hot-keys**: If set to true, it enabled the Custom keybindings for script. Warning this breaks the normal rofi flow.
## Parsing row options
@ -108,6 +109,18 @@ multiple entries can be passed using the `\x1f` separator.
echo -en "aap\0icon\x1ffolder\x1finfo\x1ftest\n"
```
## Executing external program
If you want to launch an external program from the script, you need to make sure it is launched in the background.
If not rofi will wait for its output (to display).
In bash the best way to do this is using `coproc`.
```bash
coproc ( myApp > /dev/null 2>&1 )
```
## DASH shell
If you use the `dash` shell for your script, take special care with how dash handles escaped values for the separators.

View file

@ -16,6 +16,8 @@ shipping this script in a way which is appropriate for the distribution.
.PP
It tries to start one of the following (in that order):
.RS
.IP \(bu 2
\fB\fC$TERMINAL\fR (this is a non\-standard variable)
.IP \(bu 2
@ -53,6 +55,8 @@ alacritty
.IP \(bu 2
kitty
.RE
.SH SEE ALSO
.PP
rofi(1)

View file

@ -2,7 +2,7 @@
## NAME
**rofi-sensible-terminal** - launches $TERMINAL with fallbacks
**rofi-sensible-terminal** - launches $TERMINAL with fallbacks
## SYNOPSIS
@ -21,7 +21,7 @@ It tries to start one of the following (in that order):
* x-terminal-emulator
* urxvt
* rxvt
* st
* st
* terminology
* qterminal
* Eterm
@ -47,4 +47,3 @@ Dave Davenport and contributors
Copied script from i3:
Michael Stapelberg and contributors

View file

@ -18,6 +18,8 @@ It lets you preview each theme with the Enter key and apply the theme to your
.SH Theme directories
.PP
\fBrofi\-theme\-selector\fP searches the following directories for themes:
.RS
.IP \(bu 2
${PREFIX}/share/rofi/themes
.IP \(bu 2
@ -25,6 +27,8 @@ $XDG\_CONFIG\_HOME/rofi/themes
.IP \(bu 2
$XDG\_DATA\_HOME/share/rofi/themes
.RE
.PP
${PREFIX} reflects the install location of rofi. In most cases this will be "/usr".<br>
$XDG\_CONFIG\_HOME is normally unset. Default path is "$HOME/.config".<br>

View file

@ -19,11 +19,15 @@ preferred.
.SH Comments
.PP
C and C++ file comments are supported.
.RS
.IP \(bu 2
Anything after \fB\fC//\fR and before a newline is considered a comment.
.IP \(bu 2
Everything between \fB\fC/*\fR and \fB\fC*/\fR is a comment.
.RE
.PP
Comments can be nested and the C comments can be inline.
@ -242,6 +246,8 @@ When used, values with the wrong type that cannot be converted are ignored.
.PP
The current theme format supports different types:
.RS
.IP \(bu 2
a string
.IP \(bu 2
@ -253,6 +259,8 @@ a boolean value
.IP \(bu 2
a color
.IP \(bu 2
image
.IP \(bu 2
text style
.IP \(bu 2
line style
@ -269,18 +277,26 @@ a reference
.IP \(bu 2
an orientation
.IP \(bu 2
a cursor
.IP \(bu 2
a list of keywords
.IP \(bu 2
an environment variable
.IP \(bu 2
Inherit
.RE
.PP
Some of these types are a combination of other types.
.SH String.IP \(bu 2
.SH String
.RS
.IP \(bu 2
Format: \fB\fC"[:print:]+"\fR
.RE
.PP
A string is always surrounded by double quotes (\fB\fC"\fR). Between the quotes there can be any printable character.
@ -299,9 +315,13 @@ font: "Awasome 12";
.PP
The string must be valid UTF\-8.
.SH Integer.IP \(bu 2
.SH Integer
.RS
.IP \(bu 2
Format: \fB\fC[\-+]?[:digit:]+\fR
.RE
.PP
An integer may contain any number.
@ -317,9 +337,13 @@ lines: 12;
.fi
.RE
.SH Real.IP \(bu 2
.SH Real
.RS
.IP \(bu 2
Format: \fB\fC[\-+]?[:digit:]+(\\.[:digit:]+)?\fR
.RE
.PP
A real is an integer with an optional fraction.
@ -338,9 +362,13 @@ real: 3.4;
.PP
The following is not valid: \fB\fC\&.3\fR, \fB\fC3.\fR or scientific notation: \fB\fC3.4e\-3\fR\&.
.SH Boolean.IP \(bu 2
.SH Boolean
.RS
.IP \(bu 2
Format: \fB\fC(true|false)\fR
.RE
.PP
Boolean value is either \fB\fCtrue\fR or \fB\fCfalse\fR\&. This is case\-\&sensitive.
@ -356,9 +384,35 @@ dynamic: false;
.fi
.RE
.SH Image
.PP
\fBrofi\fP support a limited set of background\-image formats.
.RS
.IP \(bu 2
Format: url("path to image");
.IP \(bu 2
Format: url("path to image", scale);
where scale is: none, both, width, height
.IP \(bu 2
Format: linear\-gradient(stop color,stop1, color, stop2 color, ...);
.IP \(bu 2
Format: linear\-gradient(to direction, stop color,stop1, color, stop2 color, ...);
where direction is: top,left,right,bottom.
.IP \(bu 2
Format: linear\-gradient(angle, stop color,stop1, color, stop2 color, ...);
Angle in deg,rad,grad (as used in color).
.RE
.PP
Where the \fB\fCpath\fR is a string, and \fB\fCstop\fR color is of type color.
.SH Color
.PP
\fBrofi\fP supports the color formats as specified in the CSS standard (1,2,3 and some of CSS 4)
.RS
.IP \(bu 2
Format: \fB\fC#{HEX}{3}\fR (rgb)
.IP \(bu 2
@ -380,11 +434,15 @@ Format: \fB\fCcmyk( {PERCENTAGE}, {PERCENTAGE}, {PERCENTAGE}, {PERCENTAGE} [, {P
.IP \(bu 2
Format: \fB\fC{named\-color} [ / {PERCENTAGE} ]\fR
.RE
.PP
The white\-space format proposed in CSS4 is also supported.
.PP
The different values are:
.RS
.IP \(bu 2
\fB\fC{HEX}\fR is a hexadecimal number ('0\-9a\-f' case insensitive).
.IP \(bu 2
@ -413,6 +471,8 @@ PapayaWhip, PeachPuff, Peru, Pink, Plum, PowderBlue, Purple, RebeccaPurple, Red,
Salmon, SandyBrown, SeaGreen, SeaShell, Sienna, Silver, SkyBlue, SlateBlue, SlateGray, SlateGrey, Snow, SpringGreen,
SteelBlue, Tan, Teal, Thistle, Tomato, Turquoise, Violet, Wheat, White, WhiteSmoke, Yellow, YellowGreen,transparent
.RE
.PP
For example:
@ -440,12 +500,18 @@ text\-color: Black;
.fi
.RE
.SH Text style.IP \(bu 2
.SH Text style
.RS
.IP \(bu 2
Format: \fB\fC(bold|italic|underline|strikethrough|none)\fR
.RE
.PP
Text style indicates how the highlighted text is emphasized. \fB\fCNone\fR indicates that no emphasis
should be applied.
.RS
.IP \(bu 2
\fB\fCbold\fR: make the text thicker then the surrounding text.
.IP \(bu 2
@ -454,26 +520,25 @@ should be applied.
\fB\fCunderline\fR: put a line under the highlighted text.
.IP \(bu 2
\fB\fCstrikethrough\fR: put a line through the highlighted text.
.IP \(bu 2
\fB\fCsmall caps\fR: emphasise the text using capitalization.
.PP
.RS
.PP
For some reason \fB\fCsmall caps\fR does not work on some systems.
.RE
.SH Line style.IP \(bu 2
.SH Line style
.RS
.IP \(bu 2
Format: \fB\fC(dash|solid)\fR
.RE
.PP
Indicates how a line should be drawn.
It currently supports:
* \fB\fCdash\fR: a dashed line, where the gap is the same width as the dash
* \fB\fCsolid\fR: a solid line
.SH Distance.IP \(bu 2
.SH Distance
.RS
.IP \(bu 2
Format: \fB\fC{Integer}px\fR
.IP \(bu 2
Format: \fB\fC{Real}em\fR
@ -484,8 +549,12 @@ Format: \fB\fC{Real}%\fR
.IP \(bu 2
Format: \fB\fC{Integer}mm\fR
.RE
.PP
A distance can be specified in 3 different units:
.RS
.IP \(bu 2
\fB\fCpx\fR: Screen pixels.
.IP \(bu 2
@ -497,6 +566,8 @@ A distance can be specified in 3 different units:
.IP \(bu 2
\fB\fC%\fR: Percentage of the \fBmonitor\fP size.
.RE
.PP
Distances used in the horizontal direction use the monitor width. Distances in
the vertical direction use the monitor height.
@ -530,6 +601,8 @@ width: calc( 100% \- 37px );
.PP
It supports the following operations:
.RS
.IP \(bu 2
\fB\fC+\fR : Add
.IP \(bu 2
@ -545,10 +618,14 @@ It supports the following operations:
.IP \(bu 2
\fB\fCmax\fR : Maximum of l or rvalue;
.RE
.PP
It uses the C precedence ordering.
.SH Padding.IP \(bu 2
.SH Padding
.RS
.IP \(bu 2
Format: \fB\fC{Integer}\fR
.IP \(bu 2
Format: \fB\fC{Distance}\fR
@ -559,11 +636,15 @@ Format: \fB\fC{Distance} {Distance} {Distance}\fR
.IP \(bu 2
Format: \fB\fC{Distance} {Distance} {Distance} {Distance}\fR
.RE
.PP
If no unit is specified, pixels are assumed.
.PP
The different number of fields in the formats are parsed like:
.RS
.IP \(bu 2
1 field: \fB\fCall\fR
.IP \(bu 2
@ -573,7 +654,11 @@ The different number of fields in the formats are parsed like:
.IP \(bu 2
4 fields: \fB\fCtop\fR, \fB\fCright\fR, \fB\fCbottom\fR, \fB\fCleft\fR
.SH Border.IP \(bu 2
.RE
.SH Border
.RS
.IP \(bu 2
Format: \fB\fC{Integer}\fR
.IP \(bu 2
Format: \fB\fC{Distance}\fR
@ -592,6 +677,8 @@ Format: \fB\fC{Distance} {Line style} {Distance} {Line style} {Distance} {Line s
.IP \(bu 2
Format: \fB\fC{Distance} {Line style} {Distance} {Line style} {Distance} {Line style} {Distance} {Line style}\fR
.RE
.PP
Borders are identical to padding, except that each distance field has a line
style property.
@ -606,9 +693,12 @@ When no unit is specified, pixels are assumed.
.SH Position
.PP
Indicate a place on the window/monitor.
.IP \(bu 2
Format: \fB\fC(center|east|north|west|south|north east|north west|south west|south east)\fR
.RS
.IP \(bu 2
.PP
Format: \fB\fC(center|east|north|west|south|north east|north west|south west|south east)\fR
.PP
.RS
@ -616,13 +706,15 @@ Format: \fB\fC(center|east|north|west|south|north east|north west|south west|sou
north west | north | north east
\-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\-
west | center | east
west | center | east
\-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\-
south west | south | south east
.fi
.RE
.RE
.SH Visibility
.PP
It is possible to hide widgets:
@ -632,9 +724,13 @@ inputbar {
enabled: false;
}
.SH Reference.IP \(bu 2
.SH Reference
.RS
.IP \(bu 2
Format: \fB\fC@{PROPERTY NAME}\fR
.RE
.PP
A reference can point to another reference. Currently, the maximum number of redirects is 20.
A property always refers to another property. It cannot be used for a subpart of the property.
@ -667,22 +763,44 @@ window {
.fi
.RE
.SH Orientation.IP \(bu 2
.SH Orientation
.RS
.IP \(bu 2
Format: \fB\fC(horizontal|vertical)\fR
.RE
.PP
Specify the orientation of the widget.
.SH List of keywords.IP \(bu 2
.SH Cursor
.RS
.IP \(bu 2
Format: \fB\fC(default|pointer|text)\fR
.RE
.PP
Specify the type of mouse cursor that is set when the mouse pointer is over the widget.
.SH List of keywords
.RS
.IP \(bu 2
Format: \fB\fC[ keyword, keyword ]\fR
.RE
.PP
A list starts with a '[' and ends with a ']'. The entries in the list are comma\-separated.
The \fB\fCkeyword\fR in the list refers to an widget name.
.SH Environment variable.IP \(bu 2
.SH Environment variable
.RS
.IP \(bu 2
Format: \fB\fC${:alnum:}\fR
.RE
.PP
This will parse the environment variable as the property value. (that then can be any of the above types).
The environment variable should be an alphanumeric string without white\-space.
@ -698,9 +816,13 @@ The environment variable should be an alphanumeric string without white\-space.
.fi
.RE
.SH Inherit.IP \(bu 2
.SH Inherit
.RS
.IP \(bu 2
Format: \fB\fCinherit\fR
.RE
.PP
Inherits the property from its parent widget.
@ -757,14 +879,20 @@ element selected {
.SH Name
.PP
The current widgets available in \fBrofi\fP:
.RS
.IP \(bu 2
\fB\fCwindow\fR
.RS
.IP \(bu 2
\fB\fCoverlay\fR: the overlay widget.
.IP \(bu 2
\fB\fCmainbox\fR: The mainbox box.
.IP \(bu 2
\fB\fCinputbar\fR: The input bar box.
.RS
.IP \(bu 2
\fB\fCbox\fR: the horizontal @box packing the widgets
.IP \(bu 2
@ -777,27 +905,49 @@ The current widgets available in \fBrofi\fP:
\fB\fCnum\-rows\fR: Shows the total number of rows.
.IP \(bu 2
\fB\fCnum\-filtered\-rows\fR: Shows the total number of rows after filtering.
.RE
.IP \(bu 2
\fB\fClistview\fR: The listview.
.RS
.IP \(bu 2
\fB\fCscrollbar\fR: the listview scrollbar
.IP \(bu 2
\fB\fCelement\fR: a box in the listview holding the entries
.RS
.IP \(bu 2
\fB\fCelement\-icon\fR: the widget in the listview's entry showing the (optional) icon
.IP \(bu 2
\fB\fCelement\-index\fR: the widget in the listview's entry keybindable index (1,2,3..0)
.IP \(bu 2
\fB\fCelement\-text\fR: the widget in the listview's entry showing the text.
.RE
.RE
.IP \(bu 2
\fB\fCmode\-switcher\fR: the main horizontal @box packing the buttons.
.RS
.IP \(bu 2
\fB\fCbutton\fR: the buttons @textbox for each mode
.RE
.IP \(bu 2
\fB\fCmessage\fR: The container holding the textbox.
.RS
.IP \(bu 2
\fB\fCtextbox\fR: the message textbox
.RE
.RE
.RE
.PP
Note that these path names match the default theme. Themes that provide a custom layout will have different
elements, and structure.
@ -869,7 +1019,9 @@ This allows the colors used for drawing the handle to be set independently.
.PP
The following properties are currently supported:
.SS all widgets:.IP \(bu 2
.SS all widgets:
.RS
.IP \(bu 2
\fBenabled\fP: enable/disable the widget
.IP \(bu 2
\fBpadding\fP: padding
@ -887,10 +1039,20 @@ Sets a radius on the corners of the borders.
\fBbackground\-color\fP: color
Background color
.IP \(bu 2
\fBbackground\-image\fP: image
Background image
.IP \(bu 2
\fBborder\-color\fP: color
Color of the border
.IP \(bu 2
\fBcursor\fP: cursor
Type of mouse cursor that is set when the mouse pointer is hovered over the widget.
.SS window:.IP \(bu 2
.RE
.SS window:
.RS
.IP \(bu 2
.PP
\fBfont\fP: string
@ -934,7 +1096,11 @@ The width of the window
\fBy\-offset\fP: distance
The offset of the window to the anchor point, allowing you to push the window left/right/up/down
.SS scrollbar:.IP \(bu 2
.RE
.SS scrollbar:
.RS
.IP \(bu 2
\fBbackground\-color\fP: color
.IP \(bu 2
\fBhandle\-width\fP: distance
@ -943,14 +1109,22 @@ The offset of the window to the anchor point, allowing you to push the window le
.IP \(bu 2
\fBborder\-color\fP: color
.SS box:.IP \(bu 2
.RE
.SS box:
.RS
.IP \(bu 2
\fBorientation\fP: orientation
Set the direction the elements are packed.
.IP \(bu 2
\fBspacing\fP: distance
Distance between the packed elements.
.SS textbox:.IP \(bu 2
.RE
.SS textbox:
.RS
.IP \(bu 2
\fBbackground\-color\fP: color
.IP \(bu 2
\fBborder\-color\fP: the color used for the border around the widget.
@ -959,9 +1133,9 @@ The offset of the window to the anchor point, allowing you to push the window le
.IP \(bu 2
\fBstr\fP: the string to display by this textbox (string).
.IP \(bu 2
\fBvertical\-align\fP: vertical alignment of the text (\fB\fC0\fR top, \fB\fC1\fR bottom).
\fBvertical\-align\fP: Vertical alignment of the text. A number between 0 (top) and 1 (bottom).
.IP \(bu 2
\fBhorizontal\-align\fP: horizontal alignment of the text (\fB\fC0\fR left, \fB\fC1\fR right).
\fBhorizontal\-align\fP: Horizontal alignment of the text. A number between 0 (left) and 1 (right).
.IP \(bu 2
\fBtext\-color\fP: the text color to use.
.IP \(bu 2
@ -977,8 +1151,14 @@ color is optional, multiple highlight styles can be added like: bold underline i
\fBplaceholder\-color\fP: Color of the placeholder text.
.IP \(bu 2
\fBblink\fP: Enable/Disable blinking on an input textbox (Boolean).
.IP \(bu 2
\fBmarkup\fP: Force markup on, beware that only valid pango markup strings are shown.
.SS listview:.IP \(bu 2
.RE
.SS listview:
.RS
.IP \(bu 2
\fBcolumns\fP: integer
Number of columns to show (at least 1)
.IP \(bu 2
@ -1012,6 +1192,8 @@ Reverse the ordering (top down to bottom up).
\fBfixed\-columns\fP: boolean
Do not reduce the number of columns shown when number of visible elements is not enough to fill them all.
.RE
.PP
Each element is a \fB\fCbox\fR called \fB\fCelement\fR\&. Each \fB\fCelement\fR can contain an \fB\fCelement\-icon\fR and \fB\fCelement\-text\fR\&.
@ -1075,9 +1257,9 @@ The current layout of \fBrofi\fP is structured as follows:
| | mainbox {BOX:vertical} | |
| | |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-| | |
| | | inputbar {BOX:horizontal} | | |
| | | |\-\-\-\-\-\-\-\-\-| |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-| |\-\-\-| | | |
| | | | prompt | | entry | |ci | | | |
| | | |\-\-\-\-\-\-\-\-\-| |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-| |\-\-\-| | | |
| | | |\-\-\-\-\-\-\-\-\-| |\-| |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-| |\-\-\-| |\-\-\-| |\-\-\-| | | |
| | | | prompt | |:| | entry |#fr| | / | |#ns| |ci | | | |
| | | |\-\-\-\-\-\-\-\-\-| |\_| |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-| |\-\-\-| |\-\-\-| |\-\-\-| | | |
| | |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-| | |
| | | |
| | |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-| | |
@ -1108,8 +1290,16 @@ The current layout of \fBrofi\fP is structured as follows:
.PP
.RS
.PP
.RS
.IP \(bu 2
ci is the case\-indicator
.IP \(bu 2
fr is the num\-filtered\-rows
.IP \(bu 2
ns is the num\-rows
.RE
.RE
.SS Error message structure
@ -1123,6 +1313,9 @@ ci is the case\-indicator
| | error\-message {BOX:vertical} | |
| | |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-| | |
| | | textbox | | |
| | | |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-| |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-| | | |
| | | |element\-icon | |element\-text | | | |
| | | |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-| |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-| | | |
| | |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-| | |
| |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-| |
|\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-|
@ -1138,6 +1331,8 @@ The layout of \fBrofi\fP can be tweaked by packing the 'fixed' widgets in a cust
.PP
The following widgets are fixed, as they provide core \fBrofi\fP functionality:
.RS
.IP \(bu 2
prompt
.IP \(bu 2
@ -1157,9 +1352,13 @@ num\-rows
.IP \(bu 2
num\-filtered\-rows
.RE
.PP
The following keywords are defined and can be used to automatically pack a subset of the widgets.
These are used in the default theme as depicted in the figure above.
.RS
.IP \(bu 2
mainbox
Packs: \fB\fCinputbar, message, listview, mode\-switcher\fR
@ -1167,26 +1366,81 @@ Packs: \fB\fCinputbar, message, listview, mode\-switcher\fR
inputbar
Packs: \fB\fCprompt,entry,case\-indicator\fR
.RE
.PP
Any widget name starting with \fB\fCtextbox\fR is a textbox widget, others are box widgets and can pack other widgets.
.PP
There are several special widgets that can be used by prefixing the name of the widget:
.IP \(bu 2
\fB\fCtextbox\fR:
This is a textbox widget. The displayed string can be set with \fB\fCstr\fR\&.
.IP \(bu 2
\fB\fCicon\fR:
.SS textbox
.PP
This is a read\-only textbox widget. The displayed string can be set with \fB\fCcontent\fR\&.
.PP
Example:
.PP
.RS
.nf
textbox\-custom {
expand: false;
content: "My Message";
}
.fi
.RE
.SS Icon
.PP
This is an icon widget. The displayed icon can be set with \fB\fCfilename\fR and size with \fB\fCsize\fR\&.
.IP \(bu 2
\fB\fCbutton\fR:
If the property \fB\fCaction\fR is set, it acts as a button.
\fB\fCaction\fR can be set to a keybinding name and completes that action. (see rofi \-show keys for a list).
.PP
If the \fB\fCsquared\fR property is set to \fBfalse\fP the widget height and width are not forced to be equal.
.PP
Example:
.PP
.RS
.nf
icon\-paste {
expand: false;
filename: "gtk\-paste";
size: 24;
vertical\-align: 0.5;
action: "kb\-primary\-paste";
}
.fi
.RE
.SS button
.PP
This is a textbox widget that can have a 'clickable' action.
The \fB\fCaction\fR can be set to:
\fB\fCok\fR accept entry.
\fB\fCcustom\fR accept custom input.
\fB\fCok|alternate\fR: accept entry and launch alternate action (for run launch in terminal).
\fB\fCcustom|alternate\fR: accept custom input and launch alternate action.
\fB\fCkeybinding\fR: accepts a keybinding name and completes that action. (see rofi \-show keys for a list).
.PP
.RS
.nf
button\-paste {
expand: false;
content: "My Clickable Message";
vertical\-align: 0.5;
action: "kb\-primary\-paste";
}
.fi
.RE
.SS Children
.PP
To specify children, set the \fB\fCchildren\fR
property (this always happens on the \fB\fCbox\fR child, see example below):
@ -1195,7 +1449,9 @@ property (this always happens on the \fB\fCbox\fR child, see example below):
.RS
.nf
children: [prompt,entry,overlay,case\-indicator];
inputbar {
children: [prompt,entry,overlay,case\-indicator];
}
.fi
.RE
@ -1277,6 +1533,8 @@ Just like CSS, \fBrofi\fP uses the box model for each widget.
.PP
Explanation of the different parts:
.RS
.IP \(bu 2
Content \- The content of the widget.
.IP \(bu 2
@ -1289,6 +1547,8 @@ The border use the border\-color of the widget.
Margin \- Clears an area outside the border.
The margin is transparent.
.RE
.PP
The box model allows us to add a border around elements, and to define space between elements.
@ -1379,7 +1639,7 @@ To test minor changes, part of the theme can be passed on the command line, for
.RS
.nf
rofi \-theme\-str '#window { fullscreen:true;}' \-show run
rofi \-theme\-str 'window { fullscreen:true;}' \-show run
.fi
.RE
@ -1413,6 +1673,8 @@ Parts of the theme can be conditionally loaded, like the CSS \fB\fC@media\fR opt
.PP
It supports the following keys as constraint:
.RS
.IP \(bu 2
\fB\fCmin\-width\fR: load when width is bigger or equal then value.
.IP \(bu 2
@ -1428,6 +1690,8 @@ It supports the following keys as constraint:
.IP \(bu 2
\fB\fCmonitor\-id\fR: The monitor id, see rofi \-help for id's.
.RE
.PP
@media takes an integer number or a fraction, for integer number \fB\fCpx\fR can be added.
@ -1442,15 +1706,47 @@ It supports the following keys as constraint:
.fi
.RE
.SH Font Parsing
.PP
Rofi uses pango
\[la]https://pango.gnome.org/\[ra] for font rendering. The font should be specified in a format that pango
understands.
This normally is the font name followed by the font size. For example:
.PP
.RS
.nf
mono 18
.fi
.RE
.PP
Or
.PP
.RS
.nf
FontAwesome 22
.fi
.RE
.SH Multiple file handling
.PP
The rasi file format offers two methods of including other files.
This can be used to modify existing themes, or have multiple variations on a theme.
.RS
.IP \(bu 2
import: Import and parse a second file.
.IP \(bu 2
theme: Discard theme, and load file as a fresh theme.
.RE
.PP
Syntax:
@ -1469,6 +1765,8 @@ The specified file can either by \fIname\fP, \fIfilename\fP,\fIfull path\fP\&.
.PP
If a filename is provided, it will try to resolve it in the following order:
.RS
.IP \(bu 2
\fB\fC${XDG\_CONFIG\_HOME}/rofi/themes/\fR
.IP \(bu 2
@ -1478,6 +1776,8 @@ If a filename is provided, it will try to resolve it in the following order:
.IP \(bu 2
\fB\fC${INSTALL PREFIX}/share/rofi/themes/\fR
.RE
.PP
A name is resolved as a filename by appending the \fB\fC\&.rasi\fR extension.

View file

@ -29,14 +29,14 @@ Comments can be nested and the C comments can be inline.
The following is valid:
```
```css
// Magic comment.
property: /* comment */ value;
```
However, this is not:
```
```css
prop/*comment*/erty: value;
```
@ -46,13 +46,13 @@ White space and newlines, like comments, are ignored by the parser.
This:
```
```css
property: name;
```
Is identical to:
```
```css
property :
name
@ -72,7 +72,7 @@ Sub-section names begin with a hash symbol `#`.
It is advised to define the *global properties section* on top of the file to
make inheritance of properties clearer.
```
```css
/* Global properties section */
* {
// list of properties
@ -112,7 +112,7 @@ Multiple elements can be specified by a `,`.
This is a valid element name:
```
```css
element normal.normal {
background-color: blue;
}
@ -123,7 +123,7 @@ button {
And is identical to:
```
```css
element normal normal, button {
background-color: blue;
}
@ -133,7 +133,7 @@ Each section inherits the global properties. Properties can be explicitly inheri
`inherit` keyword.
In the following example:
```
```css
window {
a: 1;
b: 2;
@ -148,7 +148,7 @@ mainbox {
The element `mainbox` will have the following set of properties (if `mainbox` is a child of `window`):
```
```css
a: 1;
b: 4;
c: 8;
@ -162,7 +162,7 @@ the last encountered property is used.
The properties in a section consist of:
```
```css
{identifier}: {value};
```
@ -181,6 +181,7 @@ The current theme format supports different types:
* a fractional number
* a boolean value
* a color
* image
* text style
* line style
* a distance
@ -189,6 +190,7 @@ The current theme format supports different types:
* a position
* a reference
* an orientation
* a cursor
* a list of keywords
* an environment variable
* Inherit
@ -203,7 +205,7 @@ A string is always surrounded by double quotes (`"`). Between the quotes there c
For example:
```
```css
font: "Awasome 12";
```
@ -217,7 +219,7 @@ An integer may contain any number.
For examples:
```
```css
lines: 12;
```
@ -229,7 +231,7 @@ A real is an integer with an optional fraction.
For example:
```
```css
real: 3.4;
```
@ -244,10 +246,25 @@ Boolean value is either `true` or `false`. This is case-sensitive.
For example:
```
```css
dynamic: false;
```
## Image
**rofi** support a limited set of background-image formats.
* Format: url("path to image");
* Format: url("path to image", scale);
where scale is: none, both, width, height
* Format: linear-gradient(stop color,stop1, color, stop2 color, ...);
* Format: linear-gradient(to direction, stop color,stop1, color, stop2 color, ...);
where direction is: top,left,right,bottom.
* Format: linear-gradient(angle, stop color,stop1, color, stop2 color, ...);
Angle in deg,rad,grad (as used in color).
Where the `path` is a string, and `stop` color is of type color.
## Color
**rofi** supports the color formats as specified in the CSS standard (1,2,3 and some of CSS 4)
@ -292,14 +309,14 @@ The different values are:
For example:
```
```css
background-color: #FF0000;
border-color: rgba(0,0,1, 0.5);
text-color: SeaGreen;
```
or
```
```css
background-color: transparent;
text-color: Black;
```
@ -315,9 +332,6 @@ should be applied.
* `italic`: put the highlighted text in script type (slanted).
* `underline`: put a line under the highlighted text.
* `strikethrough`: put a line through the highlighted text.
* `small caps`: emphasise the text using capitalization.
> For some reason `small caps` does not work on some systems.
## Line style
@ -348,7 +362,7 @@ Distances used in the horizontal direction use the monitor width. Distances in
the vertical direction use the monitor height.
For example:
```
```css
padding: 10%;
```
On a full-HD (1920x1080) monitor, it defines a padding of 192 pixels on the left
@ -358,7 +372,7 @@ and right side and 108 pixels on the top and bottom.
Rofi supports some maths in calculating sizes. For this it uses the CSS syntax:
```
```css
width: calc( 100% - 37px );
```
@ -440,13 +454,13 @@ A reference can point to another reference. Currently, the maximum number of red
A property always refers to another property. It cannot be used for a subpart of the property.
For example, this is not valid:
```
```css
highlight: bold @pink;
```
But this is:
```
```css
* {
myhigh: bold #FAA;
}
@ -462,6 +476,12 @@ window {
Specify the orientation of the widget.
## Cursor
* Format: `(default|pointer|text)`
Specify the type of mouse cursor that is set when the mouse pointer is over the widget.
## List of keywords
* Format: `[ keyword, keyword ]`
@ -476,7 +496,7 @@ The `keyword` in the list refers to an widget name.
This will parse the environment variable as the property value. (that then can be any of the above types).
The environment variable should be an alphanumeric string without white-space.
```
```css
* {
background-color: ${BG};
}
@ -488,7 +508,7 @@ The environment variable should be an alphanumeric string without white-space.
Inherits the property from its parent widget.
```
```css
mainbox {
border-color: inherit;
}
@ -502,7 +522,7 @@ Some widgets have an extra state.
For example:
```
```css
element selected {
}
```
@ -511,7 +531,7 @@ Here `element selected` is the name of the widget, `selected` is the state of th
The difference between dots and spaces is purely cosmetic. These are all the same:
```
```css
element .selected {
element.selected {
@ -585,7 +605,7 @@ These can be mixed.
Example:
```
```css
nametotextbox selected.active {
background-color: #003642;
text-color: #008ed4;
@ -618,8 +638,12 @@ The following properties are currently supported:
Sets a radius on the corners of the borders.
* **background-color**: color
Background color
* **background-image**: image
Background image
* **border-color**: color
Color of the border
* **cursor**: cursor
Type of mouse cursor that is set when the mouse pointer is hovered over the widget.
### window:
@ -666,8 +690,8 @@ The following properties are currently supported:
* **border-color**: the color used for the border around the widget.
* **font**: the font used by this textbox (string).
* **str**: the string to display by this textbox (string).
* **vertical-align**: vertical alignment of the text (`0` top, `1` bottom).
* **horizontal-align**: horizontal alignment of the text (`0` left, `1` right).
* **vertical-align**: Vertical alignment of the text. A number between 0 (top) and 1 (bottom).
* **horizontal-align**: Horizontal alignment of the text. A number between 0 (left) and 1 (right).
* **text-color**: the text color to use.
* **highlight**: text style {color}.
color is optional, multiple highlight styles can be added like: bold underline italic #000000;
@ -676,6 +700,7 @@ The following properties are currently supported:
* **placeholder**: Set the displayed text (String) when nothing is entered.
* **placeholder-color**: Color of the placeholder text.
* **blink**: Enable/Disable blinking on an input textbox (Boolean).
* **markup**: Force markup on, beware that only valid pango markup strings are shown.
### listview:
* **columns**: integer
@ -746,9 +771,9 @@ The current layout of **rofi** is structured as follows:
| | mainbox {BOX:vertical} | |
| | |---------------------------------------------------------------------------| | |
| | | inputbar {BOX:horizontal} | | |
| | | |---------| |-----------------------------------------------------| |---| | | |
| | | | prompt | | entry | |ci | | | |
| | | |---------| |-----------------------------------------------------| |---| | | |
| | | |---------| |-| |---------------------------------|---| |---| |---| |---| | | |
| | | | prompt | |:| | entry |#fr| | / | |#ns| |ci | | | |
| | | |---------| |_| |---------------------------------|---| |---| |---| |---| | | |
| | |---------------------------------------------------------------------------| | |
| | | |
| | |---------------------------------------------------------------------------| | |
@ -773,7 +798,9 @@ The current layout of **rofi** is structured as follows:
```
> ci is the case-indicator
> * ci is the case-indicator
> * fr is the num-filtered-rows
> * ns is the num-rows
### Error message structure
@ -784,6 +811,9 @@ The current layout of **rofi** is structured as follows:
| | error-message {BOX:vertical} | |
| | |-------------------------------------------------------------------------| | |
| | | textbox | | |
| | | |-----------------| |-------------------------------------------------| | | |
| | | |element-icon | |element-text | | | |
| | | |-----------------| |-------------------------------------------------| | | |
| | |-------------------------------------------------------------------------| | |
| |------------------------------------------------------------------------------| |
|-----------------------------------------------------------------------------------|
@ -819,23 +849,66 @@ Any widget name starting with `textbox` is a textbox widget, others are box widg
There are several special widgets that can be used by prefixing the name of the widget:
* `textbox`:
This is a textbox widget. The displayed string can be set with `str`.
* `icon`:
This is an icon widget. The displayed icon can be set with `filename` and size with `size`.
* `button`:
This is a textbox widget that can have a 'clickable' action.
The `action` can be set to:
`ok` accept entry.
`custom` accept custom input.
`ok|alternate`: accept entry and launch alternate action (for run launch in terminal).
`custom|alternate`: accept custom input and launch alternate action.
#### textbox
This is a read-only textbox widget. The displayed string can be set with `content`.
Example:
```css
textbox-custom {
expand: false;
content: "My Message";
}
```
#### Icon
This is an icon widget. The displayed icon can be set with `filename` and size with `size`.
If the property `action` is set, it acts as a button.
`action` can be set to a keybinding name and completes that action. (see rofi -show keys for a list).
If the `squared` property is set to **false** the widget height and width are not forced to be equal.
Example:
```css
icon-paste {
expand: false;
filename: "gtk-paste";
size: 24;
vertical-align: 0.5;
action: "kb-primary-paste";
}
```
#### button
This is a textbox widget that can have a 'clickable' action.
The `action` can be set to:
`keybinding`: accepts a keybinding name and completes that action. (see rofi -show keys for a list).
```css
button-paste {
expand: false;
content: "My Clickable Message";
vertical-align: 0.5;
action: "kb-primary-paste";
}
```
#### Children
To specify children, set the `children`
property (this always happens on the `box` child, see example below):
```
children: [prompt,entry,overlay,case-indicator];
```css
inputbar {
children: [prompt,entry,overlay,case-indicator];
}
```
The theme needs to be updated to match the hierarchy specified.
@ -973,7 +1046,7 @@ G_MESSAGES_DEBUG=Theme rofi -show run
To test minor changes, part of the theme can be passed on the command line, for example to set it to full-screen:
```
rofi -theme-str '#window { fullscreen:true;}' -show run
rofi -theme-str 'window { fullscreen:true;}' -show run
```
To print the current theme, run:
@ -1011,6 +1084,23 @@ It supports the following keys as constraint:
}
```
## Font Parsing
Rofi uses [pango](https://pango.gnome.org/) for font rendering. The font should be specified in a format that pango
understands.
This normally is the font name followed by the font size. For example:
```
mono 18
```
Or
```
FontAwesome 22
```
## Multiple file handling
The rasi file format offers two methods of including other files.
@ -1033,7 +1123,7 @@ If a filename is provided, it will try to resolve it in the following order:
* `${XDG_CONFIG_HOME}/rofi/themes/`
* `${XDG_CONFIG_HOME}/rofi/`
* `${XDG_DATA_HOME}/rofi/themes/`
* `${INSTALL PREFIX}/share/rofi/themes/`
* `${INSTALL PREFIX}/share/rofi/themes/`
A name is resolved as a filename by appending the `.rasi` extension.

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
## NAME
**rofi** - A window switcher, application launcher, ssh dialog and dmenu replacement
**rofi** - A window switcher, application launcher, ssh dialog, dmenu replacement and more
## SYNOPSIS
@ -33,7 +33,7 @@ To show the `run` dialog:
### Emulating dmenu
**rofi** can emulate **dmenu(1)** (a dynamic menu for X) when launched with the `-dmenu` flag.
**rofi** can emulate **dmenu(1)** (a dynamic menu for X11) when launched with the `-dmenu` flag.
The website for `dmenu` can be found [here](http://tools.suckless.org/dmenu/).
@ -53,47 +53,28 @@ Markup support can be enabled, see CONFIGURATION options.
There are currently three methods of setting configuration options (evaluated in order below):
* System configuration file (for example `/etc/rofi.rasi` or old format `/etc/rofi.conf`).
It first checks XDG_CONFIG_DIRS and then SYSCONFDIR (that is passed at compile time).
* System configuration file (for example `/etc/rofi.rasi`).
It first checks XDG\_CONFIG\_DIRS and then SYSCONFDIR (that is passed at compile time).
It loads the first config file it finds, it does not merge multiple system configuration files.
* Xresources: A method of storing key values in the Xserver. See
[here](https://en.wikipedia.org/wiki/X_resources) for more information.
* Rasi theme file: The new *theme* format can be used to set configuration values.
* Configuration File: This uses the same format as the Xresources file.
By default it looks in `XDG_CONFIG_HOME`/rofi/config, but can be overridden on commandline.
By default `XDG_CONFIG_HOME` defaults to `$HOME/.config`. (See `rofi -h` for current location).
This is the recommended way of configuring **rofi**.
* Command-line options: Arguments passed to **rofi**.
**TIP**: To get a template config file run: `rofi -dump-xresources > rofi-example.config`.
To get a template config file run: `rofi -dump-config > config.rasi`
**NOTE**: In version 1.4.0 we support configuration in a new format, a config for this can be generated by:
`rofi -dump-config > config.rasi`
**NOTE**: If you want to use the new configuration format, the config file should be named `config.rasi`.
**NOTE**: You can upgrade to the new configuration file format using `rofi -upgrade-config`
The Xresources file expects options starting with `rofi.` followed by its name. An example to set the number of lines:
rofi.lines: 10
Command-line options override settings from the Xresources file. The same option set as argument — prefixed with a '-':
rofi -lines 10
To get a list of available options formatted as Xresources entries, run:
rofi -dump-xresources
This will contain (commented) all current configuration options, modified options are uncommented.
The configuration system supports the following types:
* string
* integer (signed and unsigned)
* char
* Boolean
* boolean
* lists
Boolean options have a non-default command-line syntax. Example to enable option X:
For the syntax of these options see the **rofi-theme(5)** manpage.
For use on the commandline, Boolean options have a non-default command-line
syntax. Example to enable option X:
-X
@ -123,10 +104,9 @@ Information about the rasi format can be found in the **rofi-theme(5)** manpage.
Dump the current active theme, in rasi format, to stdout and exit.
`-dump-xresources`
`-rasi-validate` *filename*
Dump the current active configuration, in Xresources format, to stdout.
This does not validate all passed values (for example, colors).
Try to parse the file and return 0 when successful, non-zero when failed.
`-threads` *num*
@ -136,6 +116,8 @@ Specify the number of threads **rofi** should use:
* 1: Disable threading
* 2..N: Specify the maximum number of threads to use in the thread pool.
Default: Autodetect
`-display` *display*
The X server to contact. Default is `$DISPLAY`.
@ -162,6 +144,8 @@ To show the run-dialog:
rofi -show run
If `-show` is the last option passed to rofi, the first enabled modi is shown.
`-modi` *mode1,mode2*
Specify an ordered, comma-separated list of modes to enable.
@ -182,6 +166,10 @@ Example: Have a mode called 'Workspaces' using the `i3_switch_workspaces.sh` scr
Notes: The i3 window manager does not like commas in the command when specifying an exec command.
For that case '#' can be used as an separator.
**TIP**: The name is allowed to contain spaces:
rofi -modi "My File Browser:fb.sh" -show "My File Browser"
`-case-sensitive`
Start in case sensitive mode.
@ -203,22 +191,15 @@ Load an alternative configuration file.
Directory that is used to place temporary files, like history.
`-scroll-method` *method*
Select the scrolling method. 0: Per page, 1: continuous.
`-[no-]show-match`
Show the indicator that shows what part of the string is matched.
Default: *true*
`-normalize-match`
Normalize the string before matching, so o will match ö, and é matches e.
This is not a perfect implementation, but works.
For now it disabled highlighting of the matched part.
For now it disabled highlighting of the matched part.
`-no-lazy-grab`
@ -242,6 +223,10 @@ Specify icon theme to be used.
If not specified default theme from DE is used, *Adwaita* and *gnome* themes act as
fallback themes.
`-fallback-application-icon`
Specify an icon to be used when the application icon in run/drun are not yet loaded or is not available.
`-markup`
Use Pango markup to format output wherever possible.
@ -250,6 +235,10 @@ Use Pango markup to format output wherever possible.
Make **rofi** react like a normal application window. Useful for scripts like Clerk that are basically an application.
`-[no-]steal-focus`
Make rofi steal focus on launch and restore close to window that held it when launched.
### Matching
`-matching` *method*
@ -261,6 +250,7 @@ Current the following methods are supported.
* **regex**: match a regex input
* **glob**: match a glob pattern
* **fuzzy**: do a fuzzy match
* **prefix**: match prefix
Default: *normal*
@ -332,45 +322,18 @@ Set to '\x0' to disable.
Default: '-'
### Layout
### Layout and Theming
**IMPORTANT:**
In newer **rofi** releases, all the theming options have been moved into the new theme format. They are no longer normal
**rofi** options that can be passed directly on the commandline (there are too many).
Small snippets can be passed on the commandline: `rofi -theme-str 'window {width: 50%;}'` to override a single
setting. They are merged into the current theme.
They can also be appended at the end of the **rofi** config file to override parts of the theme.
Most of the following options are **deprecated** and should not be used. Please use the new theme format to customize
**rofi**. More information about the new format can be found in the **rofi-theme(5)** manpage.
`-lines`
Maximum number of lines to show before scrolling.
rofi -lines 25
Default: *15*
`-columns`
Number of columns to show before scrolling.
rofi -columns 2
Default: *1*
`-width` [value]
Set width of menu. `[value]` is specified in percentage.
rofi -width 60
If `[value]` is larger then 100, size is set in pixels. Example to span a full-HD monitor:
rofi -width 1920
If `[value]` is negative, it tries to estimates a character width. To show 30 characters in a row:
rofi -width -30
Character width is a rough estimate, and might not be correct, but should work for most monospaced fonts.
Default: *50*
`-location`
Specify where the window should be located. The numbers map to the following locations on screen:
@ -385,16 +348,6 @@ Default: *0*
Keep a fixed number of visible lines (See the `-lines` option.)
`-padding`
Define the inner margin of the window.
Default: *5*
`-fullscreen`
Use the full-screen height and width.
`-sidebar-mode`
Open in sidebar-mode. In this mode a list of all enabled modes is shown at the bottom.
@ -403,6 +356,13 @@ To show sidebar, use:
rofi -show run -sidebar-mode -lines 0
`-hover-select`
Automatically select the entry the mouse is hovering over. This option is best combined with custom mouse bindings.
To utilize hover-select and accept an entry in a single click, use:
rofi -show run -hover-select -me-select-entry '' -me-accept-entry MousePrimary
`-eh` *number*
Set row height (in chars)
@ -449,6 +409,7 @@ For example:
rofi -theme-str '#window { fullscreen: true; }'
This option can be specified multiple times.
This is now the method to tweak the theme via the commandline.
`-dpi` *number*
@ -564,6 +525,16 @@ Default: *"wmctrl -i -R {window}"*
Show window thumbnail (if available) as icon in the window switcher.
You can stop rofi from exiting when closing a window (allowing multiple to be closed in a row).
```css
configuration {
window {
close-on-delete: false;
}
}
```
### Combi settings
`-combi-modi` *mode1*,*mode2*
@ -597,6 +568,9 @@ There are 2 sorting method:
* levenshtein (Default)
* fzf sorting.
`-max-history-size` *number*
Maximum number of entries to store in history. Defaults to 25. (WARNING: can cause slowdowns when set too high)
### Dmenu specific
@ -732,6 +706,29 @@ Set ellipsize mode to start. So end of string is visible.
Pops up a message dialog (used internally for showing errors) with *message*.
Message can be multi-line.
### File browser settings
File browser behavior can be controlled via the following options:
```css
configuration {
filebrowser {
/** Directory the file browser starts in. */
directory: "/some/directory";
/**
* Sorting method. Can be set to:
* - "name"
* - "mtime" (modification time)
* - "atime" (access time)
* - "ctime" (change time)
*/
sorting-method: "name";
/** Group directories before files. */
directories-first: true;
}
}
```
### Other
`-drun-use-desktop-cache`
@ -742,23 +739,29 @@ Build and use a cache with the content of desktop files. Usable for systems with
If `drun-use-desktop-cache` is enabled, rebuild a cache with the content of desktop files.
`-drun-url-launcher` *command*
Command to open a Desktop Entry that is a Link.
`-pid` *path*
Make **rofi** create a pid file and check this on startup. The pid file prevents multiple **rofi** instances from running simultaneously. This is useful when running **rofi** from a key-binding daemon.
`-fake-transparency`
Enable fake transparency. This only works with transparent background color in the theme.
`-fake-background`
Select what to use as background for fake transparency. This can be 'background', 'screenshot' or a path to an image
file (currently only supports png).
`-display-{mode}` *string*
Set the name to use for mode. This is used as prompt and in combi-browser.
It is now preferred to use the configuration file:
```css
configuration {
{mode} {
display-name: *string*;
}
}
```
`-click-to-exit`
`-no-click-to-exit`
@ -766,30 +769,6 @@ Click the mouse outside of the **rofi** window to exit.
Default: *enabled*
### Debug
`-no-config`
Disable parsing of configuration. This runs rofi in *stock* mode.
`-no-plugins`
Disables the loading of plugins.
To get a trace with (lots of) debug information, set the following environment variable when executing **rofi**:
```
G_MESSAGES_DEBUG=all
```
The trace can be filtered by only outputting the relevant domains, for example:
```
G_MESSAGES_DEBUG=Dialogs.DRun
```
For more information on debugging, see the [wiki](https://github.com/DaveDavenport/rofi/wiki/Debugging%20Rofi)
## PATTERN
To launch commands (for example, when using the ssh launcher), the user can enter the used command-line. The following keys can be used that will be replaced at runtime:
@ -809,63 +788,7 @@ This way it can be used as a drop-in replacement for dmenu. Just copy or symlink
## THEMING
The theme format below describes the old (pre version 1.4) theme format. Please see rofi-theme(5) manpage for an updated
manual.
The theme setup allows you to specify colors per state, similar to **i3**
Currently 3 states exist:
* **normal**: normal row
* **urgent**: highlighted row (urgent)
* **active**: highlighted row (active)
For each state, the following 5 colors must be set:
* **bg**: background color row
* **fg**: text color
* **bgalt**: background color alternating row
* **hlfg**: foreground color selected row
* **hlbg**: background color selected row
The window background and border color should be specified separately. The key `color-window` contains
a tuple `background,border,separator`.
An example `Xresources` file:
! State: 'bg', 'fg', 'bgalt', 'hlbg', 'hlfg'
rofi.color-normal: #fdf6e3, #002b36, #eee8d5, #586e75, #eee8d5
rofi.color-urgent: #fdf6e3, #dc322f, #eee8d5, #dc322f, #fdf6e3
rofi.color-active: #fdf6e3, #268bd2, #eee8d5, #268bd2, #fdf6e3
! 'background', 'border', 'separator'
rofi.color-window: #fdf6e3, #002b36, #002b36
Same settings can also be specified on the command-line:
rofi -color-normal "#fdf6e3,#002b36,#eee8d5,#586e75,#eee8d5"
## COLORS
RGB colors can be specified by either their X11 name or hexadecimal notation.
For example:
white
Or:
#FFFFFF
ARGB colors are also supported. These can be used to create a transparent window if (1) your Xserver supports TrueColor, and (2) you are running a composite manager.
For example:
argb:FF444444
Or:
#FF444444
The first two fields specify the alpha level. This determines the amount of transparency (00 everything, FF nothing). The other fields represent the actual color, in hex.
Transparency can be used within **rofi**, for example if the selected background color is 50% transparent, the background color
of the window will be visible through it.
Please see **rofi-theme(5)** manpage for more information on theming.
## KEY BINDINGS
@ -893,6 +816,7 @@ of the window will be visible through it.
* `Ctrl-Page Down`: Go to next column
* `Ctrl-Enter`: Use entered text as a command (in `ssh/run modi`)
* `Shift-Enter`: Launch the application in a terminal (in run mode)
* `Ctrl-Shift-Enter`: As Ctrl-Enter and run the command in terminal (in run mode)
* `Shift-Enter`: Return the selected entry and move to the next item while keeping **rofi** open. (in dmenu)
* `Shift-Right`: Switch to the next mode. The list can be customized with the `-switchers` argument.
* `Shift-Left`: Switch to the previous mode. The list can be customized with the `-switchers` argument.
@ -903,6 +827,7 @@ of the window will be visible through it.
* `grave`: Toggle case sensitivity.
* `Alt-grave`: Toggle sorting.
* `Alt-Shift-S`: Take a screenshot and store it in the Pictures directory.
* `Ctrl-l`: File complete for run dialog.
To get a full list of key bindings on the commandline, see `rofi -h`.
The options starting with `-kb` are keybindings.
@ -920,6 +845,8 @@ Pressing the `delete-entry` binding (`shift-delete`) will close the window.
Pressing the `accept-custom` binding (`control-enter` or `shift-enter`) will run a command on the window.
(See option `window-command` );
If there is no match, it will try to launch the input.
### windowcd
Shows a list of the windows on the current desktop and allows switching between them.
@ -933,14 +860,44 @@ If there is no match, it will try to launch the input.
Shows a list of executables in `$PATH` and can launch them (optional in a terminal).
Pressing the `delete-entry` binding (`shift-delete`) will remove this entry from the run history.
Pressing the `accept-custom` binding (`control-enter` or `shift-enter`) will run the command in a terminal.
Pressing the `accept-custom` binding (`control-enter`) will run the command as entered in the entry box.
Pressing the `accept-alt` binding (`shift-enter`) will run the command in a terminal.
When pressing the `mode-complete` binding (`Control-l`), you can use the File Browser mode to launch the application
with a file as the first argument.
### drun
Same as the **run** launches, but the list is created from the installed desktop files. It automatically launches them
in a terminal if specified in the Desktop File.
Pressing the `delete-entry` binding (`shift-delete`) will remove this entry from the run history.
Pressing the `accept-custom` binding (`control-enter` or `shift-enter`) will run the command in a terminal.
Pressing the `accept-custom` binding (`control-enter`) will run the command as entered in the entry box.
Pressing the `accept-alt` binding (`shift-enter`) will run the command in a terminal.
When pressing the `mode-complete` binding (`Control-l`), you can use the File Browser mode to launch the application
passing a file as argument if specified in the desktop file.
The DRUN mode tries to follows the [XDG Desktop Entry
Specification](https://freedesktop.org/wiki/Specifications/desktop-entry-spec/) and should be compatible with
applications using this standard. Some application create invalid desktop files, **rofi** will discard these entries.
See de debugging section how to get more information from the DRUN mode, this will print why desktop files are
discarded.
There are two advanced options to tweak the behaviour:
```css
configuration {
drun {
/** Parse user desktop files. */
parse-user: true;
/** Parse system desktop files. */
parse-system: false;
}
}
```
### ssh
@ -952,7 +909,7 @@ Shows a searchable list of key bindings.
### script
Allows custom scripted Modi to be added.
Allows custom scripted Modi to be added, see the **rofi-script(5)** manpage for more information.
### combi
@ -1005,10 +962,6 @@ Combine the run and Desktop File run dialog (`drun`), and allow switching to win
rofi -modi combi,window -show combi -combi-modi run,drun
Run **rofi** full monitor width at the top of the monitor like a dropdown menu:
rofi -show run -width 100 -location 1 -lines 5 -bw 2 -yoffset -2
Pop up a text message claiming that this is the end:
rofi -e "This is the end"
@ -1063,12 +1016,51 @@ been released.
## SUPPORT
**rofi** support can be obtained [here](irc://irc.freenode.net/#rofi) (#rofi on irc.freenode.net), or via the
[forum](https://reddit.com/r/qtools//)
**rofi** support can be obtained:
* [GitHub Discussions](https://github.com/davatorium/rofi/discussions)
* [Forum (reddit)](https://reddit.com/r/qtools//)
* [IRC](irc://irc.libera.chat:6697/#rofi) (#rofi on irc.libera.chat),
## DEBUGGING
Please see [this](https://github.com/DaveDavenport/rofi/wiki/Debugging Rofi) wiki entry.
To debug it is smart to first try disabling your custom configuration:
`-no-config`
Disable parsing of configuration. This runs rofi in *stock* mode.
If you run custom C plugins, you can disable them using:
`-no-plugins`
Disables the loading of plugins.
To further debug the plugin, you can get a trace with (lots of) debug information. This debug output can be enabled for
multiple parts in rofi using the glib debug framework. Debug domains can be enabled by setting the G_MESSAGES_DEBUG
environment variable. At creation of this page the following debug domains exists:
* all: Show debug information from all domains.
* X11Helper: The X11 Helper functions.
* View: The main window view functions.
* Widgets.Box: The Box widget.
* Dialogs.DMenu: The dmenu mode.
* Dialogs.Run: The run mode.
* Dialogs.DRun: The desktop file run mode.
* Dialogs.Window: The window mode.
* Dialogs.Script: The script mode.
* Dialogs.Combi: The script mode.
* Dialogs.Ssh: The ssh mode.
* Rofi: The main application.
* Timings: Get timing output.
* Theme: Theme engine debug output. (warning lots of output).
* Widgets.Icon: The Icon widget.
* Widgets.Box: The box widget.
* Widgets.Container: The container widget.
* Widgets.Window: The window widget.
* Helpers.IconFetcher: Information about icon lookup.
The output of this can provide useful information when writing an issue.
More information (possibly outdated) see [this](https://github.com/DaveDavenport/rofi/wiki/Debugging Rofi) wiki entry.
## ISSUE TRACKER
@ -1083,10 +1075,10 @@ first.
## AUTHOR
* Qball Cow <qball@gmpclient.org>
* Qball Cow <qball@blame.services>
* Rasmus Steinke <rasi@xssn.at>
* Quentin Glidic <sardemff7+rofi@sardemff7.net>
Original code based on work by: Sean Pringle <sean.pringle@gmail.com>
Original code based on work by: [Sean Pringle](https://github.com/seanpringle/simpleswitcher) <sean.pringle@gmail.com>
For a full list of authors, check the `AUTHORS` file.

View file

@ -31,7 +31,7 @@ rofi.ssh-command: {terminal} -e {ssh-client} {host}
! "Run command to execute" Set from: File
rofi.run-command: bash -c "{cmd}"
! "Command to get extra run targets" Set from: Default
! rofi.run-list-command:
! rofi.run-list-command:
! "Run command to execute that runs in shell" Set from: File
rofi.run-shell-command: {terminal} -e {cmd}
! "Command executed on accep-entry-custom for window modus" Set from: File
@ -39,11 +39,11 @@ rofi.window-command: xkill -id {window}
! "Window fields to match in window mode" Set from: Default
! rofi.window-match-fields: all
! "Theme to use to look for icons" Set from: Default
! rofi.icon-theme:
! rofi.icon-theme:
! "Desktop entry fields to match in drun" Set from: Default
! rofi.drun-match-fields: name,generic,exec,categories,keywords
! "Only show Desktop entry from these categories" Set from: Default
! rofi.drun-categories:
! rofi.drun-categories:
! "Desktop entry show actions." Set from: Default
! rofi.drun-show-actions: false
! "DRUN format string. (Supports: generic,name,comment,exec,categories)" Set from: Default
@ -51,11 +51,11 @@ rofi.window-command: xkill -id {window}
! "Disable history in run/ssh" Set from: File
rofi.disable-history: false
! "Programs ignored for history" Set from: Default
! rofi.ignored-prefixes:
! rofi.ignored-prefixes:
! "Use sorting" Set from: Default
! rofi.sort: false
! "Choose the strategy used for sorting: normal (levenshtein) or fzf." Set from: Default
! rofi.sorting-method:
! rofi.sorting-method:
! "Set case-sensitivity" Set from: File
rofi.case-sensitive: false
! "Cycle through the results list" Set from: File
@ -72,7 +72,7 @@ rofi.parse-hosts: false
rofi.parse-known-hosts: true
! "Set the modi to combine in combi mode" Set from: File
rofi.combi-modi: window,drun,run,ssh
! "Set the matching algorithm. (normal, regex, glob, fuzzy)" Set from: Default
! "Set the matching algorithm. (normal, regex, glob, fuzzy, prefix)" Set from: Default
! rofi.matching: normal
! "Tokenize input string" Set from: File
rofi.tokenize: true
@ -83,7 +83,7 @@ rofi.m: -1
! "Padding within rows *DEPRECATED*" Set from: Default
! rofi.line-padding: 1
! "Pre-set filter" Set from: Default
! rofi.filter:
! rofi.filter:
! "Separator style (none, dash, solid) *DEPRECATED*" Set from: Default
! rofi.separator-style: dash
! "Hide scroll-bar *DEPRECATED*" Set from: Default
@ -106,26 +106,24 @@ rofi.scroll-method: 0
! rofi.window-format: {w} {c} {t}
! "Click outside the window to exit" Set from: Default
! rofi.click-to-exit: true
! "Indicate how it match by underlining it." Set from: Default
! rofi.show-match: true
! "New style theme file" Set from: Default
! rofi.theme:
! rofi.theme:
! "Color scheme for normal row" Set from: Default
! rofi.color-normal:
! rofi.color-normal:
! "Color scheme for urgent row" Set from: Default
! rofi.color-urgent:
! rofi.color-urgent:
! "Color scheme for active row" Set from: Default
! rofi.color-active:
! rofi.color-active:
! "Color scheme window" Set from: Default
! rofi.color-window:
! "Max history size (WARNING: can cause slowdowns when set to high)." Set from: Default
! rofi.color-window:
! "Max history size (WARNING: can cause slowdowns when set too high)." Set from: Default
! rofi.max-history-size: 25
! "Hide the prefix mode prefix on the combi view." Set from: Default
! rofi.combi-hide-mode-prefix: false
! "Set the character used to negate the matching. ('\0' to disable)" Set from: Default
! rofi.matching-negate-char: -
! "Directory where history and temporary files are stored." Set from: Default
! rofi.cache-dir:
! rofi.cache-dir:
! "Show window thumbnail in window switcher if availalbe." Set from: Default
! rofi.window-thumbnail: false
! "Pidfile location" Set from: File

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -38,7 +38,20 @@
/** #Mode object representing the run dialog. */
extern Mode file_browser_mode;
/**
* Create a new filebrowser.
* @returns a new filebrowser structure.
*/
Mode *create_new_file_browser ( void );
/**
* @param sw Mode object.
* @param mretv return value passed in.
* @param input The user input string.
* @param selected_line The user selected line.
* @param path The full path as output.
*
* @returns the state the user selected.
*/
ModeMode file_browser_mode_completer ( Mode *sw, int mretv, char **input, unsigned int selected_line, char **path );
/**@}*/
#endif // ROFI_DIALOG_FILE_BROWSER_H

View file

@ -43,6 +43,10 @@ typedef struct _display_proxy {
void (*dump_monitor_layout) ( void );
void (*startup_notification) ( RofiHelperExecuteContext *context, GSpawnChildSetupFunc *child_setup, gpointer *user_data );
int (*monitor_active) ( struct _workarea *mon );
void (*set_input_focus) ( guint window );
void (*revert_input_focus) ( void );
guint (*scale) ( void );
const struct _view_proxy* (*view) ( void );

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -116,6 +116,9 @@ void display_dump_monitor_layout ( void );
*/
void display_startup_notification ( RofiHelperExecuteContext *context, GSpawnChildSetupFunc *child_setup, gpointer *user_data );
void display_set_input_focus ( guint w );
void display_revert_input_focus ( void );
guint display_scale ( void );
#endif

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -240,7 +240,24 @@ gchar *rofi_escape_markup ( gchar *text );
* @param str The input to match against pattern.
* @param slen Length of str.
*
* FZF like fuzzy sorting algorithm.
* rofi_scorer_fuzzy_evaluate implements a global sequence alignment algorithm to find the maximum accumulated score by
* aligning `pattern` to `str`. It applies when `pattern` is a subsequence of `str`.
*
* Scoring criteria
* - Prefer matches at the start of a word, or the start of subwords in CamelCase/camelCase/camel123 words. See WORD_START_SCORE/CAMEL_SCORE.
* - Non-word characters matter. See NON_WORD_SCORE.
* - The first characters of words of `pattern` receive bonus because they usually have more significance than the rest.
* See PATTERN_START_MULTIPLIER/PATTERN_NON_START_MULTIPLIER.
* - Superfluous characters in `str` will reduce the score (gap penalty). See GAP_SCORE.
* - Prefer early occurrence of the first character. See LEADING_GAP_SCORE/GAP_SCORE.
*
* The recurrence of the dynamic programming:
* dp[i][j]: maximum accumulated score by aligning pattern[0..i] to str[0..j]
* dp[0][j] = leading_gap_penalty(0, j) + score[j]
* dp[i][j] = max(dp[i-1][j-1] + CONSECUTIVE_SCORE, max(dp[i-1][k] + gap_penalty(k+1, j) + score[j] : k < j))
*
* The first dimension can be suppressed since we do not need a matching scheme, which reduces the space complexity from
* O(N*M) to O(M)
*
* @returns the sorting weight.
*/
@ -330,12 +347,22 @@ cairo_surface_t *cairo_image_surface_create_from_svg ( const gchar* file, int he
void parse_ranges ( char *input, rofi_range_pair **list, unsigned int *length );
/**
* @param format The format string
* @param string The string
* @param selected_line selected line
* @param filter filter stringr
* @param format The format string used. See below for possible syntax.
* @param string The selected entry.
* @param selected_line The selected line index.
* @param filter The entered filter.
*
* Output formatted line
* Function that outputs the selected line in the user-specified format.
* Currently the following formats are supported:
* * i: Print the index (0-(N-1))
* * d: Print the index (1-N)
* * s: Print input string.
* * q: Print quoted input string.
* * f: Print the entered filter.
* * F: Print the entered filter, quoted
*
* This functions outputs the formatted string to stdout, appends a newline (\n) character and
* calls flush on the file descriptor.
*/
void rofi_output_formatted_line ( const char *format, const char *string, int selected_line, const char *filter );
@ -353,6 +380,17 @@ void rofi_output_formatted_line ( const char *format, const char *string, int se
* @returns a new string with the keys replaced.
*/
char *helper_string_replace_if_exists ( char * string, ... );
/**
* @param file File name passed to option.
* @param ext File extension passed to option.
*
* @returns path to theme or copy of filename if not found.
*/
char *helper_get_theme_path ( const char *file, const char *ext );
G_END_DECLS
/**@} */

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -91,7 +91,9 @@ typedef enum
ACCEPT_ENTRY,
ACCEPT_ALT,
ACCEPT_CUSTOM,
ACCEPT_CUSTOM_ALT,
MODE_NEXT,
MODE_COMPLETE,
MODE_PREVIOUS,
TOGGLE_CASE_SENSITIVITY,
DELETE_ENTRY,
@ -184,5 +186,11 @@ gboolean parse_keys_abe ( NkBindings *bindings );
*/
void setup_abe ( void );
/**
* @param name Don't have the name.
*
* @returns id, or UINT32_MAX if not found.
*/
guint key_binding_get_action_from_name ( const char *name );
/**@}*/
#endif // ROFI_KEYB_H

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -66,25 +66,27 @@ typedef enum
typedef enum
{
/** Entry is selected. */
MENU_OK = 0x00010000,
MENU_OK = 0x00010000,
/** User canceled the operation. (e.g. pressed escape) */
MENU_CANCEL = 0x00020000,
MENU_CANCEL = 0x00020000,
/** User requested a mode switch */
MENU_NEXT = 0x00040000,
MENU_NEXT = 0x00040000,
/** Custom (non-matched) input was entered. */
MENU_CUSTOM_INPUT = 0x00080000,
MENU_CUSTOM_INPUT = 0x00080000,
/** User wanted to delete entry from history. */
MENU_ENTRY_DELETE = 0x00100000,
MENU_ENTRY_DELETE = 0x00100000,
/** User wants to jump to another switcher. */
MENU_QUICK_SWITCH = 0x00200000,
MENU_QUICK_SWITCH = 0x00200000,
/** User wants to jump to custom command. */
MENU_CUSTOM_COMMAND= 0x00800000,
MENU_CUSTOM_COMMAND = 0x00800000,
/** Go to the previous menu. */
MENU_PREVIOUS = 0x00400000,
MENU_PREVIOUS = 0x00400000,
/** Go to the complete. */
MENU_COMPLETE = 0x01000000,
/** Bindings specifics */
MENU_CUSTOM_ACTION = 0x10000000,
MENU_CUSTOM_ACTION = 0x10000000,
/** Mask */
MENU_LOWER_MASK = 0x0000FFFF
MENU_LOWER_MASK = 0x0000FFFF
} MenuReturn;
/**

View file

@ -36,6 +36,21 @@ void rofi_icon_fetcher_destroy ( void );
*/
uint32_t rofi_icon_fetcher_query ( const char *name, const int size );
/**
* @param name The name of the icon to fetch.
* @param wsize The width of the icon to fetch.
* @param hsize The height of the icon to fetch.
*
* Query the icon-theme for icon with name and size.
* The returned icon will be the best match for the requested size, it should still be resized to the actual size.
* For icons it will take the min of wsize and hsize.
*
* name can also be a full path, if prefixed with file://.
*
* @returns the uid identifying the request.
*/
uint32_t rofi_icon_fetcher_query_advanced ( const char *name, const int wsize, const int hsize );
/**
* @param uid The unique id representing the matching request.
*
@ -45,6 +60,13 @@ uint32_t rofi_icon_fetcher_query ( const char *name, const int size );
*/
cairo_surface_t * rofi_icon_fetcher_get ( const uint32_t uid );
/**
* @param path the image path to check.
*
* Checks if a file is a supported image. (by looking at extension).
*
* @returns true if image, false otherwise.
*/
gboolean rofi_icon_fetcher_file_is_image ( const char * const path );
/** @} */
#endif // ROFI_ICON_FETCHER_H

View file

@ -2,6 +2,7 @@
#define INCLUDE_ROFI_TYPES_H
#include <glib.h>
#include <stdint.h>
G_BEGIN_DECLS
/**
@ -21,6 +22,8 @@ typedef enum
P_BOOLEAN,
/** Color */
P_COLOR,
/** Image */
P_IMAGE,
/** RofiPadding */
P_PADDING,
/** Link to global setting */
@ -33,6 +36,8 @@ typedef enum
P_LIST,
/** Orientation */
P_ORIENTATION,
/** Cursor */
P_CURSOR,
/** Inherit */
P_INHERIT,
/** Number of types. */
@ -140,6 +145,16 @@ typedef enum
ROFI_ORIENTATION_HORIZONTAL
} RofiOrientation;
/**
* Cursor type.
*/
typedef enum
{
ROFI_CURSOR_DEFAULT,
ROFI_CURSOR_POINTER,
ROFI_CURSOR_TEXT
} RofiCursorType;
/**
* Represent the color in theme.
*/
@ -155,6 +170,50 @@ typedef struct
double alpha;
} ThemeColor;
/**
* Theme Image
*/
typedef enum
{
ROFI_IMAGE_URL,
ROFI_IMAGE_LINEAR_GRADIENT
} RofiImageType;
typedef enum
{
ROFI_DIRECTION_LEFT,
ROFI_DIRECTION_RIGHT,
ROFI_DIRECTION_TOP,
ROFI_DIRECTION_BOTTOM,
ROFI_DIRECTION_ANGLE,
} RofiDirection;
typedef enum
{
ROFI_SCALE_NONE,
ROFI_SCALE_BOTH,
ROFI_SCALE_HEIGHT,
ROFI_SCALE_WIDTH,
} RofiScaleType;
typedef struct
{
RofiImageType type;
char *url;
RofiScaleType scaling;
int wsize;
int hsize;
RofiDirection dir;
double angle;
/** colors */
GList *colors;
/** cached image */
uint32_t surface_id;
} RofiImage;
/**
* RofiPadding
*/
@ -236,6 +295,8 @@ typedef union _PropertyValue
} link;
/** Highlight Style */
RofiHighlightColorStyle highlight;
/** Image */
RofiImage image;
/** List */
GList *list;
} PropertyValue;

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -70,6 +70,7 @@ const Mode * rofi_get_mode ( unsigned int index );
*/
void rofi_add_error_message ( GString *str );
void rofi_clear_error_messages ( void );
/**
* @param code the code to return
*
@ -101,7 +102,7 @@ Mode * rofi_collect_modi_search ( const char *name );
#define ERROR_MSG( a ) a "\n" \
"If you suspect this is caused by a bug in rofi,\n" \
"please report the following information to rofi's github page:\n" \
" * The generated commandline output when the error occored.\n" \
" * The generated commandline output when the error occurred.\n" \
" * Output of -dump-xresource\n" \
" * Steps to reproduce\n" \
" * The version of rofi you are running\n\n" \

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -40,7 +40,8 @@ typedef enum
MM_NORMAL = 0,
MM_REGEX = 1,
MM_GLOB = 2,
MM_FUZZY = 3
MM_FUZZY = 3,
MM_PREFIX = 4
} MatchingMethod;
/**
@ -66,23 +67,9 @@ typedef struct
{
/** List of enabled modi */
char *modi;
/** Border width */
unsigned int menu_bw;
/** Width (0-100 in %, > 100 in pixels, < 0 in char width.) */
int menu_width;
/** # lines */
unsigned int menu_lines;
/** # Columns */
unsigned int menu_columns;
/** Font string (pango format) */
char * menu_font;
/** New row colors */
char * color_normal;
char * color_active;
char * color_urgent;
char * color_window;
/** Whether to load and show icons */
gboolean show_icons;
@ -110,8 +97,6 @@ typedef struct
/** Windows location/gravity */
WindowLocation location;
/** Padding between elements */
unsigned int padding;
/** Y offset */
int y_offset;
/** X offset */
@ -148,6 +133,8 @@ typedef struct
int element_height;
/** Sidebar mode, show the modi */
unsigned int sidebar_mode;
/** Mouse hover automatically selects */
gboolean hover_select;
/** Lazy filter limit. */
unsigned int lazy_filter_limit;
/** Auto select. */
@ -163,32 +150,17 @@ typedef struct
unsigned int tokenize;
/** Monitors */
char *monitor;
/** Line margin */
unsigned int line_margin;
unsigned int line_padding;
/** filter */
char *filter;
/** style */
char *separator_style;
/** hide scrollbar */
unsigned int hide_scrollbar;
/** fullscreen */
unsigned int fullscreen;
/** bg image */
unsigned int fake_transparency;
/** dpi */
int dpi;
/** Number threads (1 to disable) */
unsigned int threads;
unsigned int scroll_method;
unsigned int scrollbar_width;
/** Background type */
char *fake_background;
char *window_format;
/** Click outside the window to exit */
int click_to_exit;
gboolean show_match;
char *theme;
/** Path where plugins can be found. */
@ -214,7 +186,16 @@ typedef struct
gboolean benchmark_ui;
gboolean normalize_match;
/** Steal focus */
gboolean steal_focus;
/** fallback icon */
char *application_fallback_icon;
} Settings;
#define DEFAULT_MENU_LINES 15
#define DEFAULT_MENU_COLUMNS 1
#define DEFAULT_MENU_WIDTH 50.0f
/** Global Settings structure. */
extern Settings config;
#endif // ROFI_SETTINGS_H

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -87,6 +87,13 @@ typedef struct ThemeWidget
*/
extern ThemeWidget *rofi_theme;
/**
* Used to store config options.
*/
extern ThemeWidget *rofi_theme;
extern ThemeWidget *rofi_configuration;
/**
* @param base Handle to the current level in the theme.
* @param name Name of the new element.
@ -103,6 +110,7 @@ ThemeWidget *rofi_theme_find_or_create_name ( ThemeWidget *base, const char *nam
* Print out the widget to the commandline.
*/
void rofi_theme_print ( ThemeWidget *widget );
void rofi_theme_print_index ( ThemeWidget *widget, int index );
/**
* @param type The type of the property to create.
@ -125,7 +133,7 @@ void rofi_theme_property_free ( Property *p );
*
* @returns a copy of p
*/
Property* rofi_theme_property_copy ( Property *p );
Property* rofi_theme_property_copy ( const Property *p );
/**
* @param widget
*
@ -183,7 +191,7 @@ RofiDistance rofi_theme_get_distance ( const widget *widget, const char *propert
*
* @returns The integer value of this property for this widget.
*/
int rofi_theme_get_integer ( const widget *widget, const char *property, int def );
int rofi_theme_get_integer ( const widget *widget, const char *property, int def );
/**
* @param widget The widget to query
@ -205,7 +213,7 @@ int rofi_theme_get_position ( const widget *widget, const char *property, int de
*
* @returns The boolean value of this property for this widget.
*/
int rofi_theme_get_boolean ( const widget *widget, const char *property, int def );
int rofi_theme_get_boolean ( const widget *widget, const char *property, int def );
/**
* @param widget The widget to query
@ -217,6 +225,17 @@ int rofi_theme_get_boolean ( const widget *widget, const char *property, int
* @returns The orientation of this property for this widget or %def not found.
*/
RofiOrientation rofi_theme_get_orientation ( const widget *widget, const char *property, RofiOrientation def );
/**
* @param widget The widget to query
* @param property The property to query.
* @param def The default value.
*
* Obtain the cursor indicated by %property of the widget.
*
* @returns The cursor for this widget or %def if not found.
*/
RofiCursorType rofi_theme_get_cursor_type ( const widget *widget, const char *property, RofiCursorType def );
/**
* @param widget The widget to query
* @param property The property to query.
@ -226,7 +245,7 @@ RofiOrientation rofi_theme_get_orientation ( const widget *widget, const char *p
*
* @returns The string value of this property for this widget.
*/
const char *rofi_theme_get_string ( const widget *widget, const char *property, const char *def );
const char *rofi_theme_get_string ( const widget *widget, const char *property, const char *def );
/**
* @param widget The widget to query
@ -237,7 +256,7 @@ const char *rofi_theme_get_string ( const widget *widget, const char *property
*
* @returns The double value of this property for this widget.
*/
double rofi_theme_get_double ( const widget *widget, const char *property, double def );
double rofi_theme_get_double ( const widget *widget, const char *property, double def );
/**
* @param widget The widget to query
@ -249,6 +268,17 @@ double rofi_theme_get_double ( const widget *widget, const char *property, doub
*/
void rofi_theme_get_color ( const widget *widget, const char *property, cairo_t *d );
/**
* @param widget The widget to query
* @param property The property to query.
* @param d The drawable to apply color.
*
* Obtain the image of the widget and applies this to the drawable d.
*
* @return true if image is set.
*/
gboolean rofi_theme_get_image ( const widget *widget, const char *property, cairo_t *d );
/**
* @param widget The widget to query
* @param property The property to query.
@ -310,6 +340,7 @@ void distance_get_linestyle ( RofiDistance d, cairo_t *draw );
* @returns the ThemeWidget if found, otherwise NULL.
*/
ThemeWidget *rofi_theme_find_widget ( const char *name, const char *state, gboolean exact );
ThemeWidget *rofi_config_find_widget ( const char *name, const char *state, gboolean exact );
/**
* @param widget The widget to find the property on.
@ -343,19 +374,7 @@ gboolean rofi_theme_is_empty ( void );
* Reset the current theme.
*/
void rofi_theme_reset ( void );
#ifdef THEME_CONVERTER
/**
* Convert old theme colors into default one.
*/
void rofi_theme_convert_old ( void );
#endif
/**
* @param file File name passed to option.
*
* @returns path to theme or copy of filename if not found.
*/
char *helper_get_theme_path ( const char *file );
/**
* @param file File name to prepare.
@ -386,5 +405,19 @@ void rofi_theme_parse_merge_widgets ( ThemeWidget *parent, ThemeWidget *child );
* Returns the media type described by type.
*/
ThemeMediaType rofi_theme_parse_media_type ( const char *type );
RofiDistance rofi_theme_property_copy_distance ( RofiDistance const distance );
/**
* @param distance The distance object to copy.
*
* @returns a copy of the distance.
*/
RofiDistance rofi_theme_property_copy_distance ( RofiDistance const distance );
/**
* @param filename The file to validate.
*
* @returns the program exit code.
*/
int rofi_theme_rasi_validate ( const char *filename );
#endif

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -73,7 +73,7 @@ struct RofiViewState
/** #textbox containing the message entry */
textbox *mesg_tb;
/** Array with the levenshtein distance for each eleemnt. */
/** Array with the levenshtein distance for each element. */
int *distance;
/** Array with the translation between the filtered and unfiltered list. */
unsigned int *line_map;
@ -142,7 +142,7 @@ struct RofiViewState
int x;
/** Y position */
int y;
/** Widget being targetted. */
/** Widget being targeted. */
widget *motion_target;
} mouse;
@ -166,6 +166,8 @@ typedef struct _view_proxy
void ( *calculate_window_width )( RofiViewState *state );
int ( *calculate_window_height )( RofiViewState *state );
void ( *window_update_size )( RofiViewState *state );
void ( *set_cursor )( RofiCursorType type );
void ( *ping_mouse )( RofiViewState *state );
void ( *cleanup )( void );
void ( *hide )( void );
@ -193,6 +195,8 @@ struct _rofi_view_cache_state
MenuFlags flags;
/** List of stacked views */
GQueue views;
/** User timeout */
guint user_timeout;
};
extern struct _rofi_view_cache_state CacheState;

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -33,7 +33,11 @@
* @defgroup View View
*
* The rofi Menu view.
*
* @{
* @}
*/
/**
* @defgroup ViewHandle ViewHandle
* @ingroup View
*
@ -58,7 +62,7 @@ typedef enum
* @param sw the Mode to show.
* @param input A pointer to a string where the inputted data is placed.
* @param menu_flags Flags indicating state of the menu.
* @param finalize the finailze callback
* @param finalize the finalize callback
*
* Main menu callback.
*
@ -100,10 +104,11 @@ void rofi_view_handle_text ( RofiViewState *state, char *text );
* @param state the Menu handle
* @param x The X coordinates of the motion
* @param y The Y coordinates of the motion
* @param find_mouse_target if we should handle pure mouse motion
*
* Update the state if needed.
*/
void rofi_view_handle_mouse_motion ( RofiViewState *state, gint x, gint y );
void rofi_view_handle_mouse_motion ( RofiViewState *state, gint x, gint y, gboolean find_mouse_target );
/**
* @param state the Menu handle
*
@ -210,7 +215,7 @@ void rofi_view_remove_active ( RofiViewState *state );
*
* The error message to show.
*/
int rofi_view_error_dialog ( const char *msg, int markup );
int rofi_view_error_dialog ( const char *msg, int markup );
/**
* Queue a redraw.
@ -245,7 +250,7 @@ void rofi_view_hide ( void );
*
* The reloading happens 'lazy', multiple calls might be handled at once.
*/
void rofi_view_reload ( void );
void rofi_view_reload ( void );
/**
* @param state The handle to the view
@ -305,9 +310,11 @@ void rofi_view_workers_initialize ( void );
void rofi_view_workers_finalize ( void );
/**
* @param width the width of the monitor.
* @param height the height of the monitor.
*
* Return the current monitor workarea.
*
* @returns the current monitor workarea
*/
void rofi_view_get_current_monitor ( int *width, int *height );
@ -318,7 +325,7 @@ void rofi_capture_screenshot ( void );
/**
* Set the window title.
*/
void rofi_view_set_window_title ( const char * title );
void rofi_view_set_window_title ( const char * title );
/**
* set ellipsize mode to start.
@ -329,9 +336,13 @@ void rofi_view_set_size ( RofiViewState * state, gint width, gint height );
void rofi_view_get_size ( RofiViewState * state, gint *width, gint *height );
void rofi_view_set_window_tilte ( const char * title );
void rofi_view_ping_mouse ( RofiViewState *state );
void rofi_view_set_window_title ( const char * title );
void rofi_view_pool_refresh ( void );
void rofi_view_set_cursor ( RofiCursorType type );
struct _view_proxy;
/* Implementations */
@ -342,5 +353,5 @@ extern const struct _view_proxy *wayland_view_proxy;
void view_init ( const struct _view_proxy *view_in );
/** @}*/
/** @} */
#endif

View file

@ -41,7 +41,7 @@
/**
* Abstract handle to the container widget internal state.
*/
typedef struct _window container;
typedef struct _container container;
/**
* @param parent The widget's parent

View file

@ -250,7 +250,7 @@ double textbox_get_estimated_ch ( void );
*
* @returns the height of a character in pixels.
*/
double textbox_get_estimated_char_height ( void );
double textbox_get_estimated_char_height ( void );
/**
* @param tb Handle to the textbox

View file

@ -54,6 +54,9 @@ struct _widget
RofiPadding border;
RofiPadding border_radius;
/** Cursor that is set when the widget is hovered */
RofiCursorType cursor_type;
/** enabled or not */
gboolean enabled;
/** Expand the widget when packed */

View file

@ -244,7 +244,7 @@ int widget_get_x_pos ( widget *widget );
* @param x A pointer to the absolute X coordinates
* @param y A pointer to the absolute Y coordinates
*
* Will modify @param x and @param y to make them relative to @param widget .
* Will modify param x and param y to make them relative to param widget .
*/
void widget_xy_to_relative ( widget *widget, gint *x, gint *y );
@ -288,7 +288,7 @@ widget *widget_find_mouse_target ( widget *wid, WidgetType type, gint x, gint y
* @param y A pointer to the y coordinate of the click
*
* Trigger an action on widget.
* @param x and @param y are relative to @param wid .
* param x and param y are relative to param wid .
*
* @returns Whether the action was handled or not
*/
@ -347,6 +347,5 @@ int widget_get_absolute_xpos ( widget *wid );
* @returns the absolute y-position of widget of the widget in pixels.
*/
int widget_get_absolute_ypos ( widget *wid );
/**@}*/
#endif // ROFI_WIDGET_H

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -61,6 +61,7 @@ struct _xcb_stuff
xcb_timestamp_t last_timestamp;
NkBindingsSeat *bindings_seat;
gboolean mouse_seen;
xcb_window_t focus_revert;
};
#endif

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -84,6 +84,7 @@ void window_set_atom_prop ( xcb_window_t w, xcb_atom_t prop, xcb_atom_t *atoms,
X ( WM_WINDOW_ROLE ), \
X ( _XROOTPMAP_ID ), \
X ( _MOTIF_WM_HINTS ), \
X ( WM_TAKE_FOCUS ), \
X ( ESETROOT_PMAP_ID )
/** enumeration of the atoms. */
@ -93,6 +94,18 @@ extern const char *netatom_names[];
/** atoms */
extern xcb_atom_t netatoms[NUM_NETATOMS];
/**
* @param w rofis window
*
* Stores old input focus for reverting and set focus to rofi.
*/
void rofi_xcb_set_input_focus ( xcb_window_t w );
/**
* IF set, revert the focus back to the original applications.
*/
void rofi_xcb_revert_input_focus ( void );
/**
* Depth of visual
*/
@ -129,6 +142,28 @@ cairo_surface_t *x11_helper_get_screenshot_surface ( void );
*/
void x11_disable_decoration ( xcb_window_t window );
/**
* List of cursor types.
*/
typedef enum
{
/** Default arrow cursor */
CURSOR_DEFAULT = 0,
/** Cursor denoting a clickable area */
CURSOR_POINTER,
/** Cursor denoting an input field / selectable text */
CURSOR_TEXT,
NUM_CURSORS
} X11CursorType;
/**
* @param window
* @param type
*
* Change mouse cursor
*/
void x11_set_cursor ( xcb_window_t window, X11CursorType type );
/**
* List of window managers that need different behaviour to functioning.
*/
@ -140,6 +175,8 @@ typedef enum
WM_DO_NOT_CHANGE_CURRENT_DESKTOP = 1,
/** PANGO WORKSPACE NAMES */
WM_PANGO_WORKSPACE_NAMES = 2,
/** Root window offset (for bspwm) */
WM_ROOT_WINDOW_OFFSET = 4,
} WindowManagerQuirk;
/**
@ -157,4 +194,14 @@ extern WindowManagerQuirk current_window_manager;
* @returns NULL if window was not found, or unmapped, otherwise returns a cairo_surface.
*/
cairo_surface_t *x11_helper_get_screenshot_surface_window ( xcb_window_t window, int size );
/**
* @param surface
* @param radius
* @param deviation
*
* Blur the content of the surface with radius and deviation.
*/
void cairo_image_surface_blur ( cairo_surface_t* surface, double radius, double deviation );
#endif

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -80,24 +80,6 @@ typedef enum
xrm_Char = 4
} XrmOptionType;
/**
* @param xcb Handler object holding connection used to fetch the settings from.
*
* Parse the rofi related X resource options of the
* connected X server.
*
* @ingroup CONFXServer
*/
void config_parse_xresource_options ( xcb_stuff *xcb );
/**
* @param filename The xresources file to parse
*
* Parses filename and updates the config
* @ingroup CONFFile
*/
void config_parse_xresource_options_file ( const char *filename );
/**
* Parse commandline options.
* @ingroup CONFCommandline
@ -111,14 +93,6 @@ void config_parse_cmd_options ( void );
*/
void config_xresource_free ( void );
/**
* Dump the settings in a Xresources compatible way to
* stdout.
*
* @ingroup CONFXResources
*/
void config_parse_xresource_dump ( void );
/**
* @param type The type of the value
* @param key The key referring to this configuration option

View file

@ -116,7 +116,7 @@ static double rofi_theme_parse_convert_hex ( char high, char low)
errno =0; \
while ( (result = (int) fread(buf, 1, max_size, current->filein))==0 && ferror(current->filein)) \
{ \
if( errno != EINTR) \
if ( errno != EINTR ) \
{ \
YY_FATAL_ERROR( "input in flex scanner failed" ); \
break; \
@ -130,7 +130,7 @@ static double rofi_theme_parse_convert_hex ( char high, char low)
case PT_STRING:\
{\
yy_size_t len = MIN (max_size, current->str_len);\
if ( len > 0 ){\
if ( len > 0 ) {\
memcpy (buf, current->input_str, len);\
current->input_str+=len;\
current->str_len-=len;\
@ -227,12 +227,33 @@ LS_SOLID (?i:solid)
ORIENTATION_HORI (?i:horizontal)
ORIENTATION_VERT (?i:vertical)
/* Cursor */
CURSOR_DEF (?i:default)
CURSOR_PTR (?i:pointer)
CURSOR_TXT (?i:text)
/* Color schema */
RGBA (?i:rgb[a]?)
HWB (?i:hwb)
CMYK (?i:cmyk)
HSL (?i:hsl[a]?)
/* Image type */
URL (?i:url?)
LINEAR_GRADIENT (?i:linear-gradient?)
WIDTH (?i:width?)
HEIGHT (?i:height?)
BOTH (?i:both?)
TO (?i:to?)
RIGHT (?i:right?)
LEFT (?i:left?)
TOP (?i:top?)
BOTTOM (?i:bottom?)
COLOR_TRANSPARENT (?i:transparent)
S_T_PARENT_LEFT \(
@ -274,7 +295,7 @@ CONFIGURATION (?i:configuration)
YY_LLOC_START
%}
%{
if ( queue == NULL ){
if ( queue == NULL ) {
queue = g_queue_new ( );
yylloc->filename = current->filename;
// unsure why todo this.
@ -290,8 +311,8 @@ if ( queue == NULL ){
<*>{CPP_COMMENT} {
int c = input();
while ( c != 0 && c != EOF){
if (c == '\n') {
while ( c != 0 && c != EOF) {
if ( c == '\n' ) {
yylloc->last_column = 1;
yylloc->last_line ++;
break;
@ -308,8 +329,8 @@ if ( queue == NULL ){
p = c;
c = input();
switch (c) {
case '*': yylloc->last_column++; if (p == '/') { c = 0; nesting_depth++; } break;
case '/': yylloc->last_column++; if (p == '*') { c = 0; nesting_depth--; } break;
case '*': yylloc->last_column++; if ( p == '/' ) { c = 0; nesting_depth++; } break;
case '/': yylloc->last_column++; if ( p == '*' ) { c = 0; nesting_depth--; } break;
case '\n': {
yylloc->last_column = 1;
yylloc->last_line ++;
@ -333,9 +354,10 @@ if ( queue == NULL ){
BEGIN(INCLUDE);
}
<INITIAL>{THEME} {
rofi_theme_reset();
//rofi_theme_reset();
g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) );
BEGIN(INCLUDE);
return T_RESET_THEME;
}
/** Skip all whitespace */
<INCLUDE>{WHITESPACE} {}
@ -345,7 +367,7 @@ if ( queue == NULL ){
yytext[yyleng-1] = '\0';
ParseObject *top = g_queue_peek_head ( file_queue );
g_assert ( top != NULL );
char *file2 = helper_get_theme_path ( &yytext[1] );
char *file2 = helper_get_theme_path ( &yytext[1], ".rasi" );
char *filename = rofi_theme_parse_prepare_file ( file2, top->filename );
g_free ( file2 );
if ( g_list_find_custom ( imported_files, filename, (GCompareFunc)g_strcmp0 ) != NULL ) {
@ -457,6 +479,14 @@ if ( queue == NULL ){
return T_LINK;
}
<SECTION>"\{" {
// Double to fit in scheme.
g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) );
g_queue_push_head ( queue, GINT_TO_POINTER (SECTION) );
BEGIN(SECTION);
return T_BOPEN;
}
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{EM} { return T_UNIT_EM; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{CH} { return T_UNIT_CH; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT,MEDIA_CONTENT>{PX} { return T_UNIT_PX; }
@ -537,6 +567,18 @@ if ( queue == NULL ){
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>argb:{HEX}{7} {
return T_ERROR_ARGB_SPEC;
}
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{URL} { return T_URL; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{LINEAR_GRADIENT} { return T_LINEAR_GRADIENT; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{WIDTH} { return T_WIDTH; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{HEIGHT} { return T_HEIGHT; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{BOTH} { return T_BOTH; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{TO} { return T_TO; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{LEFT} { return T_LEFT; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{RIGHT} { return T_RIGHT; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{TOP} { return T_TOP; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{BOTTOM} { return T_BOTTOM; }
/* Color schemes */
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{RGBA} { return T_COL_RGBA; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{HSL} { return T_COL_HSL; }
@ -598,11 +640,15 @@ if ( queue == NULL ){
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{ORIENTATION_HORI} { return ORIENTATION_HORI; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{ORIENTATION_VERT} { return ORIENTATION_VERT; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{CURSOR_DEF} { return CURSOR_DEF; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{CURSOR_PTR} { return CURSOR_PTR; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{CURSOR_TXT} { return CURSOR_TXT; }
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{COLOR_TRANSPARENT} {
return T_COLOR_TRANSPARENT;
}
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT>{COLOR_NAME} {
for ( unsigned int iter = 0; iter < num_CSSColors; iter++){
for ( unsigned int iter = 0; iter < num_CSSColors; iter++) {
if ( strcasecmp(yytext, CSSColors[iter].name )== 0 ) {
yylval->colorval.alpha = 1.0;
yylval->colorval.red = CSSColors[iter].r/255.0;
@ -617,10 +663,10 @@ if ( queue == NULL ){
<INITIAL,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT><<EOF>> {
ParseObject *po = g_queue_pop_head ( file_queue );
if ( po ) {
if ( po->type == PT_FILE ){
if ( po->type == PT_FILE ) {
fclose ( po->filein );
}
g_free ( po );
g_free ( po );
}
po = g_queue_peek_head ( file_queue );
if ( po == NULL ) {
@ -721,12 +767,10 @@ if ( queue == NULL ){
<PROPERTIES,PROPERTIES_ENV,PROPERTIES_VAR_DEFAULT,PROPERTIES_LIST>. {
yytext[yyleng-1] = '\0';
fprintf(stderr,"prop found: |%s|\n", yytext);
return T_ERROR_PROPERTY;
}
<NAMESTR>. {
yytext[yyleng-1] = '\0';
fprintf(stderr,"namestr found: |%s|\n", yytext);
return T_ERROR_NAMESTRING;
}
%%
@ -734,7 +778,7 @@ if ( queue == NULL ){
gboolean rofi_theme_parse_file ( const char *file )
{
char *file2 = helper_get_theme_path ( file );
char *file2 = helper_get_theme_path ( file, ".rasi" );
char *filename = rofi_theme_parse_prepare_file ( file2, NULL );
g_free ( file2 );
@ -765,7 +809,7 @@ gboolean rofi_theme_parse_file ( const char *file )
while ( (po = g_queue_pop_head ( file_queue ) )) {
if ( po ) {
if ( po->type == PT_FILE ){
if ( po->type == PT_FILE ) {
fclose ( po->filein );
}
g_free ( po );
@ -800,7 +844,7 @@ gboolean rofi_theme_parse_string ( const char *string )
while ( (po = g_queue_pop_head ( file_queue ) )) {
if ( po ) {
if ( po->type == PT_FILE ){
if ( po->type == PT_FILE ) {
fclose ( po->filein );
}
g_free ( po );

View file

@ -79,7 +79,7 @@ int yylex (YYSTYPE *, YYLTYPE *);
static int check_in_range ( double index, double low, double high, YYLTYPE *loc )
{
if ( index > high || index < low ){
if ( index > high || index < low ) {
gchar *str = g_strdup_printf("Value out of range: \n\t\tValue: X = %.2lf;\n\t\tRange: %.2lf <= X <= %.2lf.", index, low, high );
yyerror ( loc, loc->filename, str);
g_free(str);
@ -89,16 +89,17 @@ static int check_in_range ( double index, double low, double high, YYLTYPE *loc
return TRUE;
}
static double hue2rgb(double p, double q, double t){
static double hue2rgb ( double p, double q, double t )
{
t += (t<0)?1.0:0.0;
t -= (t>1)?1.0:0.0;
if( t < (1/6.0) ) {
if ( t < (1/6.0) ) {
return p + (q - p) * 6 * t;
}
if( t < (1/2.0) ) {
if ( t < (1/2.0) ) {
return q;
}
if( t < (2/3.0) ) {
if ( t < (2/3.0) ) {
return p + (q - p) * (2/3.0 - t) * 6;
}
return p;
@ -108,9 +109,9 @@ static ThemeColor hsl_to_rgb ( double h, double s, double l )
ThemeColor colour;
colour.alpha = 1.0;
if(s < 0.001 && s > -0.001){
if (s < 0.001 && s > -0.001) {
colour.red = colour.green = colour.blue = l; // achromatic
}else{
} else {
double q = l < 0.5 ? l * (1 + s) : l + s - l * s;
double p = 2 * l - q;
@ -121,7 +122,7 @@ static ThemeColor hsl_to_rgb ( double h, double s, double l )
return colour;
}
static ThemeColor hwb_to_rgb ( double h, double w, double b)
static ThemeColor hwb_to_rgb ( double h, double w, double b )
{
ThemeColor retv = hsl_to_rgb ( h, 1.0, 0.5);
retv.red *= ( 1. - w - b );
@ -135,8 +136,8 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
%}
%union {
int ival;
double fval;
int ival;
double fval;
char *sval;
char cval;
int bval;
@ -200,15 +201,33 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
%token ORIENTATION_HORI "Horizontal"
%token ORIENTATION_VERT "Vertical"
%token CURSOR_DEF "Default"
%token CURSOR_PTR "Pointer"
%token CURSOR_TXT "Text"
%token T_COL_RGBA "rgb[a] colorscheme"
%token T_COL_HSL "hsl colorscheme"
%token T_COL_HWB "hwb colorscheme"
%token T_COL_CMYK "cmyk colorscheme"
%token T_URL "an URL"
%token T_WIDTH "an WIDTH"
%token T_HEIGHT "an HEIGHT"
%token T_BOTH "an BOTH"
%token T_TO "an TO"
%token T_LEFT "an LEFT"
%token T_RIGHT "an RIGHT"
%token T_TOP "an TOP"
%token T_BOTTOM "an BOTTOM"
%type <ival> t_property_direction
%type <ival> t_property_scale_type
%token T_LINEAR_GRADIENT "a linear gradient"
%token T_PARENT_LEFT "Parent left ('(')"
%token T_PARENT_RIGHT "Parent right (')')"
%token T_COMMA "comma separator (',')"
%token T_OPTIONAL_COMMA "Optional comma separator (',')"
%token T_OPTIONAL_COMMA "Optional comma separator (',')"
%token T_FORWARD_SLASH "forward slash ('/')"
%token T_PERCENT "Percent sign ('%')"
%token T_LIST_OPEN "List open ('[')"
@ -233,6 +252,7 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
%token T_WHITESPACE "White space"
%token T_PDEFAULTS "Default settings section ( '* { ... }')"
%token T_CONFIGURATION "Configuration block"
%token T_RESET_THEME "Reset Theme"
%token T_COLOR_TRANSPARENT "Transparent"
@ -249,6 +269,7 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
%type <theme> t_entry_list
%type <list> t_entry_name_path
%type <list> t_entry_name_path_selectors
%type <list> t_color_list
%type <property> t_property
%type <property> t_property_element
%type <property_list> t_property_list
@ -276,6 +297,7 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
%type <list> t_property_element_list
%type <list> t_property_element_list_optional
%type <ival> t_property_orientation
%type <ival> t_property_cursor
%type <ival> t_name_prefix_optional
%start t_main
@ -287,13 +309,13 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b)
t_main
: t_configuration_list t_entry_list {
// Dummy at this point.
if (rofi_theme == NULL ){
if ( rofi_theme == NULL ) {
rofi_theme_reset();
}
rofi_theme_widget_add_properties ( rofi_theme, $2->properties );
for ( unsigned int i = 0; i < $2->num_widgets;i++) {
for ( unsigned int i = 0; i < $2->num_widgets; i++ ) {
ThemeWidget *d = $2->widgets[i];
rofi_theme_parse_merge_widgets(rofi_theme, d);
}
@ -301,7 +323,12 @@ t_main
;
t_configuration_list:
%empty {}
%empty {
if ( rofi_configuration == NULL ) {
rofi_configuration = g_slice_new0 ( ThemeWidget );
rofi_configuration->name = g_strdup ( "Root" );
}
}
| t_configuration_list T_CONFIGURATION T_BOPEN t_config_property_list_optional T_BCLOSE {};
@ -317,6 +344,12 @@ t_entry_list:
%empty {
$$ = g_slice_new0 ( ThemeWidget );
}
| t_entry_list T_RESET_THEME {
rofi_theme_reset();
rofi_theme_free($1);
$$ = g_slice_new0 ( ThemeWidget );
}
| t_entry_list t_name_prefix_optional t_entry_name_path_selectors T_BOPEN t_property_list_optional T_BCLOSE
{
for ( GList *liter = g_list_first ( $3); liter; liter = g_list_next ( liter ) ) {
@ -346,7 +379,7 @@ t_entry_list:
widget->media = g_slice_new0(ThemeMedia);
widget->media->type = rofi_theme_parse_media_type ( $4 );
widget->media->value = (double)$6;
for ( unsigned int i = 0; i < $9->num_widgets;i++) {
for ( unsigned int i = 0; i < $9->num_widgets; i++ ) {
ThemeWidget *d = $9->widgets[i];
rofi_theme_parse_merge_widgets(widget, d);
}
@ -359,7 +392,7 @@ t_entry_list:
widget->media = g_slice_new0(ThemeMedia);
widget->media->type = rofi_theme_parse_media_type ( $4 );
widget->media->value = $6;
for ( unsigned int i = 0; i < $9->num_widgets;i++) {
for ( unsigned int i = 0; i < $9->num_widgets; i++ ) {
ThemeWidget *d = $9->widgets[i];
rofi_theme_parse_merge_widgets(widget, d);
}
@ -372,7 +405,7 @@ t_entry_list:
widget->media = g_slice_new0(ThemeMedia);
widget->media->type = rofi_theme_parse_media_type ( $4 );
widget->media->value = (double)$6;
for ( unsigned int i = 0; i < $10->num_widgets;i++) {
for ( unsigned int i = 0; i < $10->num_widgets; i++ ) {
ThemeWidget *d = $10->widgets[i];
rofi_theme_parse_merge_widgets(widget, d);
}
@ -406,6 +439,18 @@ t_config_property
// We don't keep any reference to this after this point, so the property can be free'ed.
rofi_theme_property_free ( $1 );
}
| t_property_name T_BOPEN t_property_list_optional T_BCLOSE
{
ThemeWidget *widget = rofi_configuration;
widget = rofi_theme_find_or_create_name ( widget, $1 );
widget->set = TRUE;
rofi_theme_widget_add_properties ( widget, $3);
if ( $3 ) {
g_hash_table_destroy ( $3 );
}
g_free ( $1 );
}
;
/**
* properties
@ -512,8 +557,67 @@ t_property_element
$$ = rofi_theme_property_create ( P_ORIENTATION );
$$->value.i = $1;
}
| t_property_cursor {
$$ = rofi_theme_property_create ( P_CURSOR );
$$->value.i = $1;
}
| T_URL T_PARENT_LEFT T_STRING T_PARENT_RIGHT {
$$ = rofi_theme_property_create ( P_IMAGE );
$$->value.image.type = ROFI_IMAGE_URL;
$$->value.image.url = $3;
}
| T_URL T_PARENT_LEFT T_STRING T_COMMA t_property_scale_type T_PARENT_RIGHT {
$$ = rofi_theme_property_create ( P_IMAGE );
$$->value.image.type = ROFI_IMAGE_URL;
$$->value.image.url = $3;
$$->value.image.scaling = $5;
}
| T_LINEAR_GRADIENT T_PARENT_LEFT t_color_list T_PARENT_RIGHT {
$$ = rofi_theme_property_create ( P_IMAGE );
$$->value.image.type = ROFI_IMAGE_LINEAR_GRADIENT;
$$->value.image.dir = ROFI_DIRECTION_RIGHT;
$$->value.image.colors = $3;
}
| T_LINEAR_GRADIENT T_PARENT_LEFT T_TO t_property_direction T_COMMA t_color_list T_PARENT_RIGHT {
$$ = rofi_theme_property_create ( P_IMAGE );
$$->value.image.type = ROFI_IMAGE_LINEAR_GRADIENT;
$$->value.image.dir = $4;
$$->value.image.colors = $6;
}
| T_LINEAR_GRADIENT T_PARENT_LEFT t_property_color_value_angle T_COMMA t_color_list T_PARENT_RIGHT {
$$ = rofi_theme_property_create ( P_IMAGE );
$$->value.image.type = ROFI_IMAGE_LINEAR_GRADIENT;
$$->value.image.dir = ROFI_DIRECTION_ANGLE;
$$->value.image.angle = $3;
$$->value.image.colors = $5;
}
;
t_property_direction
: T_RIGHT { $$ = ROFI_DIRECTION_RIGHT; }
| T_LEFT { $$ = ROFI_DIRECTION_LEFT; }
| T_TOP { $$ = ROFI_DIRECTION_TOP; }
| T_BOTTOM { $$ = ROFI_DIRECTION_BOTTOM; }
;
t_property_scale_type
: T_BOTH { $$ = ROFI_SCALE_BOTH; }
| T_WIDTH { $$ = ROFI_SCALE_WIDTH; }
| T_HEIGHT { $$ = ROFI_SCALE_HEIGHT; }
| T_NONE { $$ = ROFI_SCALE_NONE; }
;
t_color_list
: t_property_color {
$$ = g_list_append ( NULL, g_memdup ( (gconstpointer)&($1), sizeof ( ThemeColor )));
}
| t_color_list T_COMMA t_property_color {
$$ = g_list_append ($1, g_memdup ( (gconstpointer)&($3), sizeof ( ThemeColor )));
}
;
/** List of elements */
t_property_element_list_optional
: %empty { $$ = NULL; }
@ -574,7 +678,7 @@ t_property_distance_zero
$$.base.left = NULL;
$$.base.right = NULL;
$$.base.modtype = ROFI_DISTANCE_MODIFIER_NONE;
$$.style = $2;
$$.style = $2;
}
| t_property_distance { $$ = $1;}
;
@ -587,7 +691,7 @@ t_property_distance_unit
$$->type = $2;
$$->left = NULL;
$$->right = NULL;
$$->modtype = ROFI_DISTANCE_MODIFIER_NONE;
$$->modtype = ROFI_DISTANCE_MODIFIER_NONE;
}
| T_INT {
$$ = g_slice_new0(RofiDistanceUnit);
@ -595,7 +699,7 @@ t_property_distance_unit
$$->type = ROFI_PU_PX;
$$->left = NULL;
$$->right = NULL;
$$->modtype = ROFI_DISTANCE_MODIFIER_NONE;
$$->modtype = ROFI_DISTANCE_MODIFIER_NONE;
}
| T_DOUBLE t_property_unit {
$$ = g_slice_new0(RofiDistanceUnit);
@ -603,7 +707,7 @@ t_property_distance_unit
$$->type = $2;
$$->left = NULL;
$$->right = NULL;
$$->modtype = ROFI_DISTANCE_MODIFIER_NONE;
$$->modtype = ROFI_DISTANCE_MODIFIER_NONE;
}
| T_PARENT_LEFT t_property_distance_unit_math3 T_PARENT_RIGHT {
$$ = g_slice_new0(RofiDistanceUnit);
@ -621,20 +725,20 @@ t_property_distance_unit
t_property_distance_unit_math
: t_property_distance_unit_math T_MODIFIER_MULTIPLY t_property_distance_unit {
$$ = g_slice_new0(RofiDistanceUnit);
$$->left = $1;
$$->right = $3;
$$->left = $1;
$$->right = $3;
$$->modtype = ROFI_DISTANCE_MODIFIER_MULTIPLY;
}
| t_property_distance_unit_math T_FORWARD_SLASH t_property_distance_unit {
$$ = g_slice_new0(RofiDistanceUnit);
$$->left = $1;
$$->right = $3;
$$->left = $1;
$$->right = $3;
$$->modtype = ROFI_DISTANCE_MODIFIER_DIVIDE;
}
| t_property_distance_unit_math T_PERCENT t_property_distance_unit {
$$ = g_slice_new0(RofiDistanceUnit);
$$->left = $1;
$$->right = $3;
$$->left = $1;
$$->right = $3;
$$->modtype = ROFI_DISTANCE_MODIFIER_MODULO;
}
| t_property_distance_unit {
@ -646,14 +750,14 @@ t_property_distance_unit_math
t_property_distance_unit_math2
: t_property_distance_unit_math2 T_MODIFIER_ADD t_property_distance_unit_math {
$$ = g_slice_new0(RofiDistanceUnit);
$$->left = $1;
$$->right = $3;
$$->left = $1;
$$->right = $3;
$$->modtype = ROFI_DISTANCE_MODIFIER_ADD;
}
| t_property_distance_unit_math2 T_MODIFIER_SUBTRACT t_property_distance_unit_math {
$$ = g_slice_new0(RofiDistanceUnit);
$$->left = $1;
$$->right = $3;
$$->left = $1;
$$->right = $3;
$$->modtype = ROFI_DISTANCE_MODIFIER_SUBTRACT;
}
| t_property_distance_unit_math {
@ -663,14 +767,14 @@ t_property_distance_unit_math2
t_property_distance_unit_math3
: t_property_distance_unit_math3 T_MODIFIER_MIN t_property_distance_unit_math2 {
$$ = g_slice_new0(RofiDistanceUnit);
$$->left = $1;
$$->right = $3;
$$->left = $1;
$$->right = $3;
$$->modtype = ROFI_DISTANCE_MODIFIER_MIN;
}
| t_property_distance_unit_math3 T_MODIFIER_MAX t_property_distance_unit_math2 {
$$ = g_slice_new0(RofiDistanceUnit);
$$->left = $1;
$$->right = $3;
$$->left = $1;
$$->right = $3;
$$->modtype = ROFI_DISTANCE_MODIFIER_MAX;
}
| t_property_distance_unit_math2 {
@ -683,27 +787,27 @@ t_property_distance
: T_INT t_property_unit t_property_line_style {
$$.base.distance = (double)$1;
$$.base.type = $2;
$$.base.left = NULL;
$$.base.right = NULL;
$$.base.modtype = ROFI_DISTANCE_MODIFIER_NONE;
$$.style = $3;
$$.base.left = NULL;
$$.base.right = NULL;
$$.base.modtype = ROFI_DISTANCE_MODIFIER_NONE;
$$.style = $3;
}
/** Double unit and line style */
| T_DOUBLE t_property_unit t_property_line_style {
$$.base.distance = (double)$1;
$$.base.type = $2;
$$.base.modtype = ROFI_DISTANCE_MODIFIER_NONE;
$$.base.left = NULL;
$$.base.right = NULL;
$$.style = $3;
$$.base.left = NULL;
$$.base.right = NULL;
$$.style = $3;
}
| T_CALC T_PARENT_LEFT t_property_distance_unit_math3 T_PARENT_RIGHT t_property_line_style {
$$.base.distance = 0;
$$.base.type = ROFI_PU_PX;
$$.base.left = $3;
$$.base.right = NULL;
$$.base.left = $3;
$$.base.right = NULL;
$$.base.modtype = ROFI_DISTANCE_MODIFIER_GROUP;
$$.style = $5;
$$.style = $5;
};
/** distance unit. px, em, % */
@ -753,14 +857,20 @@ t_property_color
if ( ! check_in_range($3,0,100, &(@$)) ) { YYABORT; }
if ( ! check_in_range($6,0,100, &(@$)) ) { YYABORT; }
if ( ! check_in_range($9,0,100, &(@$)) ) { YYABORT; }
$$.alpha = $11; $$.red = $3/100.0; $$.green = $6/100.0; $$.blue = $9/100.0;
$$.alpha = $11;
$$.red = $3/100.0;
$$.green = $6/100.0;
$$.blue = $9/100.0;
}
/** rgba ( 0-100% 0-100% 0-100% / 0-1.0 ) */
| T_COL_RGBA T_PARENT_LEFT t_property_color_value T_PERCENT t_property_color_value T_PERCENT t_property_color_value T_PERCENT t_property_color_opt_alpha_ws T_PARENT_RIGHT {
if ( ! check_in_range($3,0,100, &(@$)) ) { YYABORT; }
if ( ! check_in_range($5,0,100, &(@$)) ) { YYABORT; }
if ( ! check_in_range($7,0,100, &(@$)) ) { YYABORT; }
$$.alpha = $9; $$.red = $3/100.0; $$.green = $5/100.0; $$.blue = $7/100.0;
$$.alpha = $9;
$$.red = $3/100.0;
$$.green = $5/100.0;
$$.blue = $7/100.0;
}
/** hwb with comma */
| T_COL_HWB T_PARENT_LEFT t_property_color_value_angle T_COMMA t_property_color_value_unit T_COMMA t_property_color_value_unit t_property_color_opt_alpha_c T_PARENT_RIGHT {
@ -777,7 +887,7 @@ t_property_color
/** cmyk with comma */
| T_COL_CMYK T_PARENT_LEFT t_property_color_value_unit T_COMMA t_property_color_value_unit T_COMMA t_property_color_value_unit T_COMMA t_property_color_value_unit t_property_color_opt_alpha_c T_PARENT_RIGHT {
$$.alpha = $10;
double c= $3, m= $5, y= $7, k= $9;
double c = $3, m = $5, y = $7, k = $9;
$$.red = (1.0-c)*(1.0-k);
$$.green = (1.0-m)*(1.0-k);
$$.blue = (1.0-y)*(1.0-k);
@ -785,7 +895,7 @@ t_property_color
/** cmyk whitespace edition. */
| T_COL_CMYK T_PARENT_LEFT t_property_color_value_unit t_property_color_value_unit t_property_color_value_unit t_property_color_value_unit t_property_color_opt_alpha_ws T_PARENT_RIGHT {
$$.alpha = $7;
double c= $3, m= $4, y= $5, k= $6;
double c = $3, m = $4, y = $5, k = $6;
$$.red = (1.0-c)*(1.0-k);
$$.green = (1.0-m)*(1.0-k);
$$.blue = (1.0-y)*(1.0-k);
@ -842,8 +952,14 @@ t_property_color_value
;
t_property_orientation
: ORIENTATION_HORI { $$ = ROFI_ORIENTATION_HORIZONTAL; }
| ORIENTATION_VERT { $$ = ROFI_ORIENTATION_VERTICAL; }
: ORIENTATION_HORI { $$ = ROFI_ORIENTATION_HORIZONTAL; }
| ORIENTATION_VERT { $$ = ROFI_ORIENTATION_VERTICAL; }
;
t_property_cursor
: CURSOR_DEF { $$ = ROFI_CURSOR_DEFAULT; }
| CURSOR_PTR { $$ = ROFI_CURSOR_POINTER; }
| CURSOR_TXT { $$ = ROFI_CURSOR_TEXT; }
;
/** Property name */

View file

@ -9,7 +9,6 @@ libgwater_xcb_a_CFLAGS = \
$(AM_CFLAGS) \
$(GW_XCB_INTERNAL_CFLAGS)
GW_XCB_CFLAGS = \
-I$(srcdir)/subprojects/libgwater/xcb \
$(GW_XCB_INTERNAL_CFLAGS)
@ -17,4 +16,3 @@ GW_XCB_CFLAGS = \
GW_XCB_LIBS = \
libgwater-xcb.a \
$(GW_XCB_INTERNAL_LIBS)

View file

@ -1,5 +1,5 @@
project('rofi', 'c',
version: '1.6.1-wayland',
version: '1.6.1-wayland-dev',
meson_version: '>=0.47.0',
license: [ 'MIT' ],
default_options: [
@ -41,6 +41,8 @@ plugins_deps = [
dependency('cairo'),
]
dep_lm = c_compiler.find_library('m', required : false)
deps = [
plugins_deps,
dependency('gio-unix-2.0'),
@ -48,28 +50,27 @@ deps = [
dependency('pangocairo'),
dependency('xkbcommon'),
dependency('gdk-pixbuf-2.0'),
dep_lm,
]
gwxcb = subproject('xcb')
libgwater = subproject('libgwater')
# XCB stuff
deps += [
gwxcb.get_variable('libgwater_xcb'),
libgwater.get_variable('libgwater_xcb'),
dependency('xcb'),
dependency('xcb-aux'),
dependency('xcb-xkb'),
dependency('xkbcommon-x11'),
dependency('xcb-ewmh'),
dependency('xcb-icccm'),
dependency('xcb-xrm'),
dependency('xcb-randr'),
dependency('xcb-cursor'),
dependency('xcb-xinerama'),
dependency('cairo-xcb'),
dependency('libstartup-notification-1.0'),
]
libgif = c_compiler.find_library('libgif', required: false)
deps += [ libgif ]
wayland_client = dependency('wayland-client', required: get_option('wayland'))
wayland_protocols = dependency('wayland-protocols', required: get_option('wayland'))
wayland_cursor = dependency('wayland-cursor', required: get_option('wayland'))
@ -77,7 +78,7 @@ if wayland_client.found()
deps += wayland_client
deps += wayland_protocols
deps += wayland_cursor
deps += subproject('libgwater-wayland').get_variable('libgwater_wayland')
deps += libgwater.get_variable('libgwater_wayland')
endif
check = dependency('check', version: '>= 0.11.0', required: get_option('check'))
@ -90,7 +91,6 @@ header_conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
header_conf.set_quoted('PACKAGE_BUGREPORT', 'https://github.com/davatorium/rofi/')
header_conf.set_quoted('PACKAGE_URL', 'https://reddit.com/r/qtools/')
header_conf.set('THEME_CONVERTER', true)
header_conf.set('_GNU_SOURCE', true)
header_conf.set('USE_NK_GIT_VERSION', true)
@ -99,7 +99,6 @@ header_conf.set('GLIB_VERSION_MIN_REQUIRED', '(G_ENCODE_VERSION(@0@,@1@))'.forma
header_conf.set('GLIB_VERSION_MAX_ALLOWED', '(G_ENCODE_VERSION(@0@,@1@))'.format(glib_min_major, glib_min_minor))
header_conf.set('ENABLE_DRUN', get_option('drun'))
header_conf.set('HAVE_LIBGIF', libgif.found())
header_conf.set('WINDOW_MODE', get_option('window'))
header_conf.set('ENABLE_WAYLAND', wayland_client.found())
@ -297,6 +296,7 @@ install_data(
'themes/blue.rasi',
'themes/c64.rasi',
'themes/dmenu.rasi',
'themes/docu.rasi',
'themes/glue_pro_blue.rasi',
'themes/gruvbox-common.rasi',
'themes/gruvbox-dark-hard.rasi',
@ -312,6 +312,8 @@ install_data(
'themes/solarized.rasi',
'themes/solarized_alternate.rasi',
'themes/fancy.rasi',
'themes/iggy.rasi',
'themes/iggy.jpg',
install_dir: themedir
)
@ -344,6 +346,7 @@ test('helper_pidfile test', executable('helper_pidfile.test', [
],
objects: rofi.extract_objects([
'config/config.c',
'source/theme.c',
'source/helper.c',
'source/xrmoptions.c',
'source/rofi-types.c',
@ -423,6 +426,7 @@ test('helper test', executable('helper.test', [
],
objects: rofi.extract_objects([
'config/config.c',
'source/theme.c',
'source/helper.c',
'source/xrmoptions.c',
'source/rofi-types.c',
@ -435,6 +439,7 @@ test('helper_expand test', executable('helper_expand.test', [
],
objects: rofi.extract_objects([
'config/config.c',
'source/theme.c',
'source/helper.c',
'source/xrmoptions.c',
'source/rofi-types.c',
@ -447,6 +452,7 @@ test('helper_config_cmdline_parser test', executable('helper_config_cmdline_pars
],
objects: rofi.extract_objects([
'config/config.c',
'source/theme.c',
'source/helper.c',
'source/xrmoptions.c',
'source/rofi-types.c',
@ -480,6 +486,7 @@ if check.found()
'config/config.c',
'source/dialogs/help-keys.c',
'source/helper.c',
'source/theme.c',
'source/mode.c',
'source/xrmoptions.c',
'source/rofi-types.c',
@ -494,6 +501,7 @@ if check.found()
objects: rofi.extract_objects([
'config/config.c',
'source/helper.c',
'source/theme.c',
'source/xrmoptions.c',
'source/rofi-types.c',
]),

View file

@ -11,7 +11,7 @@ This means, that next rofi version will either be
* 0.15.13 (bugfix release)
* 0.16.0 (minor release) or (if no major bugs are discovered)
* 1.0.0 (major release)
* 1.0.0 (major release)
## Keyboard Layouts
@ -30,7 +30,7 @@ they are available they can be used for keybindings, if not, the user gets a war
### DMenu reading from stdin
**Rofi** used to have a custom `fgets` implementation that supported custom separators. The has been repaced by the
**Rofi** used to have a custom `fgets` implementation that supported custom separators. The has been replaced by the
`getdelim` feature of POSIX '08, this gave a speedup of 6x (from 648 ms for 202000 lines down to 108ms).
### Multi-Core power
@ -52,7 +52,7 @@ themes (with live preview) and a themes repository.
To make things even easier, you can now take screenshots of **rofi** from within **rofi** with a simple keybinding.
![Rofi Internal Screenshot](rofi-screenshot.png)
### Theme repository
This has been requested several times and rofi's website actually has a theming page. This however got outdated quickly
@ -71,7 +71,7 @@ The repository can be found [here](https://github.com/DaveDavenport/rofi-themes/
The second tool is a website allowing you to easily create themes and preview all changes life, the
[themenator](https://davedavenport.github.io/rofi/generator.html) Big thanks to
[SardemFF7](https://github.com/sardemff7) who got tired of me complaining, took the very rough prototype and turned it
into something beautiful.
into something beautiful.
Hopefully people will make beautiful themes and submit them to the [theme repository](https://github.com/DaveDavenport/rofi-themes/).

View file

@ -79,7 +79,7 @@ Below is a more complete changelog between the 0.15.12 and the 1.0.0 release.
## Bug fixes
* Fix subpixel rendering. (#303)
* Fix basic tests on OpenBSD (#272)
* Fix basic tests on OpenBSD (#272)
* Fix wrong use of memcpy (thx to Jasperia).
* Work around for sigwaitinfo on OpenBSD.
* Ignore invalid entries (non-utf8) in dmenu mode.
@ -94,4 +94,3 @@ Below is a more complete changelog between the 0.15.12 and the 1.0.0 release.
* Removal of old themeing method. Given it was incomplete.
* Removal of daemon mode, given this duplicates Window Manager functionality.

View file

@ -1,22 +1,21 @@
# V1.1.0 - A trump card
## New Features
## New Features
- Keys mode, showing keybindings.
- Stop cycling option (#407) (Thx to Yaroslav)
- Kill window on delete entry (#316)
- Keys mode, showing keybindings.
- Stop cycling option (#407) (Thx to Yaroslav)
- Kill window on delete entry (#316)
## Improvements
## Improvements
- Add Control+Backspace as remove word back keybinding.
- Allow user to use X11 background for fake transparency (#390)
- Allow user to specify background image.
- Add Control+Backspace as remove word back keybinding.
- Allow user to use X11 background for fake transparency (#390)
- Allow user to specify background image.
- Improved keybinding handling, allowing on-release and modifier only (#384).
- Use display name for prompt (#409)
- Use display name for prompt (#409)
- Parse subdirectories in drun parser (#416)
- Switch to stop cycling (#407)
##Bug fixes
- Grab mouse pointer with keyboard
## Bug fixes
- Grab mouse pointer with keyboard

View file

@ -1,14 +1,14 @@
# V1.2.0 - 8397
# V1.2.0 - 8397
## New Features
Despite me saying after every release that it is mostly feature complete; new **Rofi**, new features.
Despite me saying after every release that it is mostly feature complete; new **Rofi**, new features.
However these new features are mostly to improve current functionality and debugging.
Below the 4 most important ones.
### Underline Match
A new, hopefully welcome, addition is that **Rofi** now highlights the match in each row:
A new, hopefully welcome, addition is that **Rofi** now highlights the match in each row:
![Rofi Underline](./rofi-underline-match.png)
@ -40,7 +40,7 @@ rofi.window-format: {t:-16} ({c:10})
## Track configuration option origin
**Rofi** now keeps track of how configuration options are set. It will now display if it is the default value, set in
Xresources, configuration file or commnadline.
Xresources, configuration file or commandline.
![Rofi configuration tracking](./rofi-options.png)

View file

@ -53,7 +53,7 @@ Async mode is not always possible, and will be disabled if not possible.
In this release rofi is more efficient in drawing its content to the X11 window. The basic redraw on expose has been
speedup by a factor 1000. This was obtained by using a server side copy of the internal surface, instead of painting it
with cairo each time. Especially for large (4k and higher) screens, in fullscreen mode, this reduces redrawing from +-
180ms to 0.1 ms. A second improvement was made by configuring X11 not repaint the window background when resized, this
180ms to 0.1 ms. A second improvement was made by configuring X11 not repaint the window background when resized, this
caused some flickering (it was painted black before being drawn). It now keeps the old content and tells rofi to
repaint. This causes trailing, but overall looks nicer.

View file

@ -13,7 +13,7 @@ possible.
Because of The great work done by [SardemFF7](https://github.com/SardemFF7/) the
code base is simplified and the key and mouse handling improved. The libraries
provided by SardemFF7 also made it possible to add a often requested feature of
provided by SardemFF7 also made it possible to add a often requested feature of
icons (correctly using the icon-theme). A feature I never expected to be added.
To top this off, SardemFF7 added support to build rofi using
[meson](http://mesonbuild.com/).
@ -77,7 +77,7 @@ widgets.
> Note that opening a fonts is one of the slowest operations during rofi
> startup; having multiple fonts could have a significant impact on startup
> times.
> times.
### Flexible layout
@ -104,7 +104,7 @@ The new theme parser also support importing and overriding. This allow you to
make make modifications to an existing theme, without having to completely copy
it. For example, I want to use the `arthur` theme (shipped with rofi) but use
fake transparency, change the font off the result list and import a set of
overriding colors from `mycolors`.
overriding colors from `mycolors`.
```css
// Import the default arthur theme
@ -118,9 +118,9 @@ overriding colors from `mycolors`.
transparency: "screenshot";
}
/* Override the font on the listview elements */
#element {
#element {
font: "Ubuntu Mono 18";
}
}
```
## Icons
@ -182,7 +182,7 @@ See [here](https://gitcrate.org/qtools/rofi-top).
## Configuration File
> This feature is in alpha stage.
> This feature is in alpha stage.
The new theme format can now (as an alpha) feature be used to set rofi's
configuration. In the future, when we add wayland support, we want to get rid of
@ -236,4 +236,3 @@ would look using: `rofi -dump-config`.
* Allow rofi to be placed above window based on window id.
* Support different font per textbox.
* Keep cache of previous used fonts.

View file

@ -4,7 +4,7 @@ After the last release turned out to be fairly large we are hopefully back to mo
This release focuses on squashing some bugs and hopefully improving the user experience.
Nevertheless this release also includes some new features.
Big thanks to [SardemFF7](https://www.sardemff7.net/), without whose help and contributions this release would not have been possible.
Big thanks to [SardemFF7](https://www.sardemff7.net/), without whose help and contributions this release would not have been possible.
## New features
@ -21,7 +21,7 @@ The different fields are:
* **name**: the application's name
* **generic**: the application's generic name
* **exec**: the application's executable
* **exec**: the application's executable
* **categories**: the application's categories
* **comment**: the application comment
* **all**: all of the above

View file

@ -1,6 +1,6 @@
# 1.5.2: Procrastination in progress
Rofi 1.5.2 is another bug-fix release in the 1.5 series.
Rofi 1.5.2 is another bug-fix release in the 1.5 series.
## Fix border drawing
@ -74,14 +74,14 @@ An often requested feature is the ability to change the display string for the d
The `-drun-display-format` option is added that allows just this.
> -drun-display-format
>
>
> The format string for the drun dialog:
> * name: the application's name
> * generic: the application's generic name
> * exec: the application's executable
> * categories: the application's categories
> * comment: the application comment
>
>
> Default: {name} [({generic})]
Items between `[]` are only displayed when the field within is set. So in the above example, the `()` are omitted when

View file

@ -1,6 +1,6 @@
# 1.5.3: Time delayed progress
Rofi 1.5.3 is another bug-fix release in the 1.5 series.
Rofi 1.5.3 is another bug-fix release in the 1.5 series.
There is one breaking change in the theme naming and there are a few small new features (tweaks) in this release.
@ -32,7 +32,7 @@ separator character.
If you have very long entries in your view that get ellipsized (cut off at the end indicated by ...) you can now select,
at runtime, where they are cut off (start, middle or end).
You cycle through the options with the the `alt+.` keybinding.
You cycle through the options with the `alt+.` keybinding.
Start:
@ -53,7 +53,7 @@ End:
The full list of fixes and updates:
* Update manpage with missing entry. (#937)
* Update manpage with missing entry. (#937)
* Rename sidebar widget to mode-switcher and allow configuration from theme.
* Timing: Moving timing output to glib debug system.
* SSH: Fix unitialized variable issue.
@ -70,4 +70,3 @@ The full list of fixes and updates:
* Update libnkutils, libgwater.
* DMENU: Add format option to strip pango markup from return value.
* ListView: allow user to change ellipsizing displayed value at run-time.

View file

@ -115,7 +115,7 @@ This is a very initial implementation of CSS like `@media` support. This allows
based on screen size or ratio.
We currently support: minimum width, minimum height, maximum width, maximum
height, monitor id, minimum acpect ratio or maximum acpect ratio.
height, monitor id, minimum aspect ratio or maximum aspect ratio.
For example, go to fullscreen mode on screens smaller then full HD:

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
releasenotes/1.7.0/iggy.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

View file

@ -0,0 +1,356 @@
# 1.7.0: Iggy 2024
![Iggy](./iggy.jpg)
Rofi 1.7.0 is another bug-fix release that also removes a lot of deprecated features. One of the biggest changes is
the removal of the (deprecated) xresources based configuration setup. With this removal, also a lot of hack-ish code has
been removed that tried to patch old config setups. While the deprecation might be frustrating for people who have not
yet converted to the new format, I hope for some understanding. Even though this move might not be popular, the
deprecation in previous releases and consequential removal of these options is needed for two reasons.
The most important one is to keep rofi maintainable and secondary to open possibility to overhaul the config system in
the future and with that fixing some long standing bugs and add new options that
where hindered by the almost 10 year old system.
Beside mostly bug-fixes and removal of deprecated options, we also improved the theming and added features to help in
some of the more 'off-script' use of rofi.
This release was made possible by many contributors, see below for a full list. Big thanks again to SardemF77 and
TonCherAmi.
## File Browser
TonCherAmi made several very nice usability improvements to the file-browser. His changes allow you to define sorting
and ordering of the entries and changing the default start directory.
These options can be set using the new 'nested' configuration format that we are testing in rofi:
```css
configuration {
filebrowser {
/** Directory the file browser starts in. */
directory: "/some/directory";
/**
* Sorting method. Can be set to:
* - "name"
* - "mtime" (modification time)
* - "atime" (access time)
* - "ctime" (change time)
*/
sorting-method: "name";
/** Group directories before files. */
directories-first: true;
}
}
```
## File Completion
In rofi 1.7.0 a long awaited patch I wrote many years ago landed into the rofi.
This patch adds some basic completion support by changing modi. Currently it
only supports chaining the FileBrowser mode. This allows you to launch an
application with a file as argument. This is currently supported in the Run
and the DRun modi by pressing the `Control-l` keybinding. For the Run mode it
will add it as first argument, in DRun it only works if the Desktop file
indicates support for this.
![completer](./complete.gif)
This is not the final implementation, but a first investigation in how to
add/extend this feature. Ideally you can have multiple completers (including
custom ones) you can choose from.
## Timeout actions
You can now configure an action to be taken when rofi has not been interacted
with for a certain amount of seconds. You can specify a keybinding to trigger
after X seconds.
This option can be set using the new 'nested' configuration format that we are
testing in rofi:
```css
configuration {
timeout {
delay: 15;
action: "kb-cancel";
}
}
```
This setting will close rofi after 15 seconds of no interaction.
```css
configuration {
timeout {
delay: 5;
action: "kb-accept";
}
}
```
This setting will accept the current selection after 5 seconds of no
interaction.
## Background image and gradients
To improve theming the `background-image` property was added with support for
setting images `url()` or a gradient `linear-gradient()`.
```css
window {
background-image: url("/tmp/i3.png", both);
}
element {
children: [element-icon, element-text];
background-image: linear-gradient(to bottom, black/20%, white/20%, black/10%);
}
```
The below screenshot shows both background image and gradients.
![background image](./background-image.png)
Or a more subtle change is the gradient on the tabs here:
![iggy-theme](./iggy-theme.png)
## Clickable button and icons
```css
icon-paste {
expand: false;
filename: "gtk-paste";
size: 24;
vertical-align: 0.5;
action: "kb-primary-paste";
}
```
```css
button-paste {
expand: false;
content: "My Clickable Message";
vertical-align: 0.5;
action: "kb-primary-paste";
}
```
The screenshot below shows a non-squared image and clickable buttons (the close icon in the top right)
![rofi icons](./rofi-icons.png)
# Changelog
* ADD: -steal-focus option.
Explicitly steal focus from from the current window and restore it on closing.
Enabling this might break the window switching mode.
* ADD: [Config] Add nested configuration option support.
Allow for nested configuration options, this allows for options to be grouped.
```css
configuration {
timeout {
delay: 15;
action: "kb-cancel";
}
combi {
display-name: "Combi";
}
}
```
* ADD: [Config] Support for handling dynamic config options.
A quick work-around for handling old-style dynamic options. This should be resolved when all options are
converted to the new (internal) config system.
* ADD: [DRun] Add fallback icon option.
This option allows you to set a fallback icon from applications.
```css
configuration {
application_fallback_icon: "my-icon";
}
```
* ADD: [IconFetcher] Find images shipped with the theme.
If you have an icon widget you can specify an image that exists in the theme directory.
```css
window {
background-image: url("iggy.jpg", width);
}
```
* ADD: [DRun] Add support for passing file (using file-browser) completer for desktop files that support his.
See above.
* ADD: [DRun] Support for service files.
Support KDE service desktop files.
* ADD: [FileBrowser] Allow setting startup directory (#1325)
* ADD: [FileBrowser]: Add sorting-method. (#1340)
* ADD: [FileBrowser] Add option to group directories ahead of files. (#1352)
See above.
* ADD: [Filtering] Add prefix matching method. (#1237)
This matching method matches each entered word to start of words in the target
entry.
* ADD: [Icon] Add option to square the widget.
By default all icons are squared, this can now be disabled. The icon will
occupy the actual space the image occupies.
* ADD: [Icon|Button] Make action available on icon, button and keybinding name.
See above.
* ADD: [KeyBinding] Add Ctrl-Shift-Enter option. (#874)
This combines the custom and alt keybinding. Allowing a custom command to be
launched in terminal.
* ADD: [ListView]-hover-select option. (#1234)
Automatically select the entry under the mouse cursor.
* ADD: [Run] Add support for passing file (using file-browser) completer.
See above.
* ADD: [Textbox] Allow theme to force markup on text widget.
Force markup on text widgets.
* ADD: [Theme] theme validation option. (`-rasi-validate`)
* ADD: [View] Add support for user timeout and keybinding action.
* ADD: [Widget] Add cursor property (#1313)
Add support for setting the mouse cursor on widgets.
For example the entry cursor on the textbox, or click hand cursor on the entry.
```css
element,element-text,element-icon, button {
cursor: pointer;
}
```
* ADD: [Widget] Add scaling option to background-image.
Allows you to scale the `background-image` on width, height and both.
See above example.
* ADD: [Widget] Add support background-image and lineair gradient option.
See above.
* ADD: [Window] Add pango markup for window format (#1288)
Allows you to use pango-markup in the window format option.
* ADD: [Window] Allow rofi to stay open after closing window.
```css
configuration {
window {
close-on-delete: false;
}
}
```
* FIX: [DSL] Move theme reset into grammar parser from lexer.
Given how the lexer and the grammar parser interact, the reset did not happen at
the right point in the parsing process, causing unexpected behaviour.
* FIX: [Drun]: fix sorting on broken desktop files. (thanks to nick87720z)
Broken desktop files could cause a rofi crash.
* FIX: [File Browser]: Fix escaping of paths.
Fix opening files with special characters that needs to be escaped.
* FIX: [ListView] Fix wrong subwidget name.
Fixes theming of `element-index`.
* FIX: [Script] Don't enable custom keybindings by default.
The quick switch between modi was broken when on a script mode. This now by default works,
unless the mode overrides this.
* FIX: [TextBox] Fix height estimation.
This should fix themes that mix differently sized fonts.
* FIX: [Theme] widget state and inherited properties. This should help fixing some old themes with changes from 1.6.1.
An old pre-1.6.1 rasi theme should work with the following section added:
```css
element-text {
background-color: inherit;
text-color: inherit;
}
```
* FIX: [Widget] Fix rendering of border and dashes. (Thanks to nick87720z)
This fixes the long broken feature of dashed borders.
```css
message {
padding: 1px ;
border-color: var(separatorcolor);
border: 2px dash 0px 0px ;
}
```
* REMOVE: -dump-xresources
* REMOVE: -fullscreen
* REMOVE: -show-match
* REMOVE: Old xresources based configuration file.
* REMOVE: fake transparency/background option, part of theme now.
* REMOVE: xresources parsing via Xserver
* Remove: [Theme] Remove backwards compatiblity hack.
* DOC: Update changes to manpages
# Thanks
Big thanks to:
* Quentin Glidic
* a1346054
* Ian C
* TonCherAmi
* nick87720z
* Markus Grab
* Zachary Freed
* nickofolas
* unisgn
* Jas
* rahulaggarwal965
* Awal Garg
* Eduard Lucena
* Lars Wendler
Apologies if I mistyped or missed anybody.

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

View file

@ -2,5 +2,6 @@
<gresources>
<gresource prefix="/org/qtools/rofi">
<file alias="default_theme.rasi">doc/default_theme.rasi</file>
<file alias="default_configuration.rasi">doc/default_configuration.rasi</file>
</gresource>
</gresources>

View file

@ -6,18 +6,18 @@ GIT=$(which git)
if [ -d "${DIR}/.git/" ] && [ -n "${GIT}" ]
then
echo -n "#define GIT_VERSION \"" > ${FILE}.tmp
echo -n "#define GIT_VERSION \"" > "${FILE}.tmp"
BRTG="$(${GIT} describe --tags --always --all | sed -e 's:heads/::')"
REV="$(${GIT} describe --tags --always --dirty| sed -e 's:-g\([a-f0-9]\{7\}\):-git-\1:g')"
echo -n "${REV} (${BRTG})" >> ${FILE}.tmp
echo "\"" >> ${FILE}.tmp
echo -n "${REV} (${BRTG})" >> "${FILE}.tmp"
echo "\"" >> "${FILE}.tmp"
else
echo "#undef GIT_VERSION" > ${FILE}.tmp
echo "#undef GIT_VERSION" > "${FILE}.tmp"
fi
if [ ! -f ${FILE} ] || ! diff ${FILE}.tmp ${FILE} > /dev/null
if [ ! -f "${FILE}" ] || ! diff "${FILE}.tmp" "${FILE}" >/dev/null
then
mv ${FILE}.tmp ${FILE}
mv "${FILE}.tmp" "${FILE}"
else
rm ${FILE}.tmp
rm "${FILE}.tmp"
fi

View file

@ -1,9 +1,9 @@
#!/usr/bin/env bash
#
# This code is released in public domain by Dave Davenport <qball@gmpclient.org>
# This code is released in public domain by Dave Davenport <qball@gmpclient.org>
# This converts from old style theme (< 1.4) to new style theme (>= 1.4)
#
function update_color ()
update_color()
{
var=${1}
var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters
@ -12,11 +12,11 @@ function update_color ()
then
echo "#${var:5}"
else
echo ${var}
echo "${var}"
fi
}
function parse_window_color ()
parse_window_color()
{
OLDIFS=${IFS}
IFS=","
@ -37,7 +37,7 @@ function parse_window_color ()
IFS=${OLDIFS}
}
function parse_color ()
parse_color()
{
state=$1
OLDIFS=${IFS}
@ -62,13 +62,13 @@ while read LINE
do
if [[ ${LINE} =~ ^rofi\.color-normal: ]]
then
parse_color "normal" "${LINE:18}"
parse_color "normal" "${LINE:18}"
elif [[ ${LINE} =~ ^rofi\.color-urgent: ]]
then
parse_color "urgent" "${LINE:18}"
parse_color "urgent" "${LINE:18}"
elif [[ ${LINE} =~ ^rofi\.color-active: ]]
then
parse_color "active" "${LINE:18}"
parse_color "active" "${LINE:18}"
elif [[ ${LINE} =~ ^rofi\.color-window: ]]
then
parse_window_color "${LINE:18}"

View file

@ -13,14 +13,14 @@ shift
OUTPUT_PNG=$1
shift
XVFB=$(which Xvfb 2> /dev/null)
XDOTOOL=$(which xdotool 2> /dev/null)
ROFI=$(which rofi 2> /dev/null)
SCROT=$(which scrot 2> /dev/null)
FEH=$(which feh 2> /dev/null)
COMPTON=$(which compton 2> /dev/null)
XVFB=$(which Xvfb 2>/dev/null)
XDOTOOL=$(which xdotool 2>/dev/null)
ROFI=$(which rofi 2>/dev/null)
SCROT=$(which scrot 2>/dev/null)
FEH=$(which feh 2>/dev/null)
COMPTON=$(which compton 2>/dev/null)
function check_tool()
check_tool()
{
if [ -z "${1}" ]
then
@ -30,26 +30,26 @@ function check_tool()
}
XPID=
function create_fake_x ( )
create_fake_x()
{
export DISPLAY=":$1"
echo "Starting fake X: ${DISPLAY}"
${XVFB} ${DISPLAY} -screen 0 1024x600x24&
${XVFB} "${DISPLAY}" -screen 0 1024x600x24 &
XPID=$!
sleep 1
}
function destroy_fake_x ( )
destroy_fake_x()
{
if [ -n "${XPID}" ]
then
echo "Stopping fake X: ${XPID}"
kill ${XPID}
wait ${XPID}
kill "${XPID}"
wait "${XPID}"
fi
}
function generate()
generate()
{
echo "Normal"
echo "Alternative"
@ -81,16 +81,16 @@ ROFI_OPTIONS="-selected-row 6 -u 2,3 -a 4,5 -location 0 -width 100 -lines 7 -col
export DISPLAY=${VDISPLAY}
# Create fake X11
create_fake_x ${VDISPLAY}
create_fake_x "${VDISPLAY}"
sleep 1
fluxbox &
sleep 1;
compton -b
sleep 1
compton -b
feh --bg-center background.jpg
(generate | ${ROFI} -no-config -theme "${THEME_FILE}" -dmenu ${ROFI_OPTIONS} > /dev/null )&
(generate | ${ROFI} -no-config -theme "${THEME_FILE}" -dmenu ${ROFI_OPTIONS} >/dev/null )&
sleep 1
#${XDOTOOL} key Alt+S
scrot ${OUTPUT_PNG}
scrot "${OUTPUT_PNG}"
${XDOTOOL} key Return
sleep 2
destroy_fake_x

View file

@ -14,12 +14,12 @@ shift
OUTPUT_PNG=$1
shift
XVFB=$(which Xvfb 2> /dev/null)
XDOTOOL=$(which xdotool 2> /dev/null)
XRDB=$(which xrdb 2> /dev/null)
ROFI=$(which rofi 2> /dev/null)
XVFB=$(which Xvfb 2>/dev/null)
XDOTOOL=$(which xdotool 2>/dev/null)
XRDB=$(which xrdb 2>/dev/null)
ROFI=$(which rofi 2>/dev/null)
function check_tool()
check_tool()
{
if [ -z "${1}" ]
then
@ -29,26 +29,26 @@ function check_tool()
}
XPID=
function create_fake_x ( )
create_fake_x()
{
export DISPLAY=":$1"
echo "Starting fake X: ${DISPLAY}"
${XVFB} ${DISPLAY} -screen 0 800x600x24 &
${XVFB} "${DISPLAY}" -screen 0 800x600x24 &
XPID=$!
sleep 1
}
function destroy_fake_x ( )
destroy_fake_x()
{
if [ -n "${XPID}" ]
then
echo "Stopping fake X: ${XPID}"
kill ${XPID}
wait ${XPID}
kill "${XPID}"
wait "${XPID}"
fi
}
function generate()
generate()
{
echo "Normal"
echo "Alternative"
@ -84,13 +84,13 @@ then
fi
# Create fake X11
create_fake_x ${VDISPLAY}
create_fake_x "${VDISPLAY}"
# Load Xresources if specified.
if [ -n "${XRDB_FILE}" ]
then
echo -e "${COLOR_YELLOW}Loading Xresources:${RESET} ${XRDB_FILE}"
${XRDB} -retain -load ${XRDB_FILE}
${XRDB} -retain -load "${XRDB_FILE}"
fi
(generate | ${ROFI} -config "${XRDB_FILE}" -dmenu ${ROFI_OPTIONS} > /dev/null )&

View file

@ -10,7 +10,7 @@
# preferred terminal emulator. On Debian, there is the x-terminal-emulator
# symlink for example.
for terminal in $TERMINAL x-terminal-emulator urxvt rxvt st terminology qterminal Eterm aterm uxterm xterm roxterm xfce4-terminal.wrapper mate-terminal lxterminal konsole alacritty kitty; do
if command -v $terminal > /dev/null 2>&1; then
if command -v $terminal >/dev/null 2>&1; then
exec $terminal "$@"
fi
done

View file

@ -1,9 +1,8 @@
#!/usr/bin/env bash
#
# This code is released in public domain by Dave Davenport <qball@gmpclient.org>
# This code is released in public domain by Dave Davenport <qball@gmpclient.org>
#
ROFI=$(which rofi)
SED=$(which sed)
MKTEMP=$(which mktemp)
@ -37,7 +36,7 @@ declare -a theme_names
# Function that tries to find all installed rofi themes.
# This fills in #themes array and formats a displayable string #theme_names
##
function find_themes()
find_themes()
{
DIRS=${XDG_DATA_DIRS}
OLDIFS=${IFS}
@ -70,8 +69,8 @@ function find_themes()
# Add user dir.
DIRS+=":${XDG_DATA_HOME:-${HOME}/.local/share}"
DIRS+=":${XDG_CONFIG_HOME:-${HOME}/.config}"
for p in ${DIRS}; do
p=${p%/}
for p in ${DIRS}; do
p=${p%/}
TD=${p}/rofi/themes
if [ -n "${p}" ] && [ -d "${TD}" ]
then
@ -80,10 +79,10 @@ function find_themes()
do
if [ -f "${file}" ]
then
themes+=(${file})
FN=$(basename ${file})
themes+=("${file}")
FN=$(basename "${file}")
NAME=${FN%.*}
USER=$(${SED} -n 's/^.*User: \(.*\)/\1/p' ${file} | head -n 1 )
USER=$(${SED} -n 's/^.*User: \(.*\)/\1/p' "${file}" | head -n 1 )
if [ -z "${USER}" ]
then
theme_names+=(${NAME})
@ -95,29 +94,28 @@ function find_themes()
fi
done
IFS=${OLDIFS}
}
##
# Create a copy of rofi
##
function create_config_copy()
create_config_copy()
{
${ROFI} -dump-config > ${TMP_CONFIG_FILE}
${ROFI} -dump-config > "${TMP_CONFIG_FILE}"
# remove theme entry.
sed -i 's/^\s*theme:\s\+".*"\s*;//g' ${TMP_CONFIG_FILE}
sed -i 's/^\s*theme:\s\+".*"\s*;//g' "${TMP_CONFIG_FILE}"
}
###
# Print the list out so it can be displayed by rofi.
##
function create_theme_list()
create_theme_list()
{
OLDIFS=${IFS}
IFS='|'
for themen in ${theme_names[@]}
for themen in ${theme_names[@]}
do
echo ${themen}
echo "${themen}"
done
IFS=${OLDIFS}
}
@ -127,9 +125,9 @@ function create_theme_list()
##
declare -i SELECTED
function select_theme ()
select_theme()
{
local MORE_FLAGS=(-dmenu -format i -no-custom -p "Theme" -markup -config ${TMP_CONFIG_FILE} -i)
local MORE_FLAGS=(-dmenu -format i -no-custom -p "Theme" -markup -config "${TMP_CONFIG_FILE}" -i)
MORE_FLAGS+=(-kb-custom-1 "Alt-a")
MORE_FLAGS+=(-u 2,3 -a 4,5 )
local CUR="default"
@ -143,23 +141,23 @@ function select_theme ()
Current theme: <b>${CUR}</b>"""
THEME_FLAG=
if [ -n "${SELECTED}" ]
then
THEME_FLAG="-theme ${themes[${SELECTED}]}"
then
THEME_FLAG="-theme ${themes[${SELECTED}]}"
fi
RES=$( create_theme_list | ${ROFI} ${THEME_FLAG} ${MORE_FLAGS[@]} -cycle -selected-row "${SELECTED}" -mesg "${MESG}")
RES=$( create_theme_list | ${ROFI} ${THEME_FLAG} ${MORE_FLAGS[@]} -cycle -selected-row "${SELECTED}" -mesg "${MESG}")
RTR=$?
if [ ${RTR} = 10 ]
if [ "${RTR}" = 10 ]
then
return 0;
elif [ ${RTR} = 1 ]
elif [ "${RTR}" = 1 ]
then
return 1;
elif [ ${RTR} = 65 ]
elif [ "${RTR}" = 65 ]
then
return 1;
fi
CUR=${theme_names[${RES}]}
SELECTED=${RES}
SELECTED=${RES}
done
}
@ -167,31 +165,16 @@ Current theme: <b>${CUR}</b>"""
# Create if not exists, then removes #include of .theme file (if present) and add the selected theme to the end.
# Repeated calls should leave the config clean-ish
###
function set_theme()
set_theme()
{
CDIR="${XDG_CONFIG_HOME:-${HOME}/.config}/rofi"
if [ ! -d "${CDIR}" ]
then
mkdir -p ${CDIR}
mkdir -p "${CDIR}"
fi
if [ -f "${CDIR}/config.rasi" ]
then
get_link=$(readlink -f "${CDIR}/config.rasi")
${SED} -i "/@import.*/d" "${get_link}"
echo "@import \"${1}\"" >> "${get_link}"
else
if [ ! -e "${CDIR}/config" ]
then
# No file.
echo "rofi.theme: ${1}" >> "${CDIR}/config"
elif [ -f "${CDIR}/config" ]
then
# Regular file
get_link=$(readlink -f "${CDIR}/config")
${SED} -i "/rofi\.theme: .*\.rasi$/d" "${get_link}"
echo "rofi.theme: ${1}" >> "${get_link}"
fi
fi
get_link=$(readlink -f "${CDIR}/config.rasi")
${SED} -i "/@import.*/d" "${get_link}"
echo "@import \"${1}\"" >> "${get_link}"
}
############################################################################################################
@ -228,4 +211,4 @@ fi
##
# Remove temp. config.
##
rm ${TMP_CONFIG_FILE}
rm -- "${TMP_CONFIG_FILE}"

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -76,7 +76,7 @@ static void combi_mode_parse_switchers ( Mode *sw )
sizeof ( CombiMode ) * ( pd->num_switchers + 1 ) );
Mode *mode = rofi_collect_modi_search ( token );
if ( mode != NULL ) {
if ( mode != NULL ) {
pd->switchers[pd->num_switchers].disable = FALSE;
pd->switchers[pd->num_switchers++].mode = mode;
continue;
@ -172,6 +172,8 @@ static ModeMode combi_mode_result ( Mode *sw, int mretv, char **input, unsigned
}
return MODE_EXIT;
}
} else if ( ( mretv& MENU_COMPLETE) ) {
return RELOAD_DIALOG;
}
for ( unsigned i = 0; i < pd->num_switchers; i++ ) {
@ -180,7 +182,7 @@ static ModeMode combi_mode_result ( Mode *sw, int mretv, char **input, unsigned
return mode_result ( pd->switchers[i].mode, mretv, input, selected_line - pd->starts[i] );
}
}
if ( ( mretv & MENU_CUSTOM_INPUT ) ) {
if ( ( mretv & MENU_CUSTOM_INPUT ) ) {
return mode_result ( pd->switchers[0].mode, mretv, input, selected_line );
}
return MODE_EXIT;
@ -216,22 +218,22 @@ static char * combi_mgrv ( const Mode *sw, unsigned int selected_line, int *stat
char * str = retv = mode_get_display_value ( pd->switchers[i].mode, selected_line - pd->starts[i], state, attr_list, TRUE );
const char *dname = mode_get_display_name ( pd->switchers[i].mode );
if ( !config.combi_hide_mode_prefix ) {
retv = g_strdup_printf ( "%s %s", dname, str );
g_free ( str );
}
retv = g_strdup_printf ( "%s %s", dname, str );
g_free ( str );
if ( attr_list != NULL ) {
ThemeWidget *wid = rofi_theme_find_widget ( sw->name, NULL, TRUE );
if ( attr_list != NULL ) {
ThemeWidget *wid = rofi_config_find_widget ( sw->name, NULL, TRUE );
Property *p = rofi_theme_find_property ( wid, P_COLOR, pd->switchers[i].mode->name, TRUE );
if ( p != NULL ) {
PangoAttribute *pa = pango_attr_foreground_new (
p->value.color.red * 65535,
p->value.color.green * 65535,
p->value.color.blue * 65535 );
pa->start_index = PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING;
pa->end_index = strlen ( dname );
*attr_list = g_list_append ( *attr_list, pa );
PangoAttribute *pa = pango_attr_foreground_new (
p->value.color.red * 65535,
p->value.color.green * 65535,
p->value.color.blue * 65535 );
pa->start_index = PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING;
pa->end_index = strlen ( dname );
*attr_list = g_list_append ( *attr_list, pa );
}
}
}
return retv;
}

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -159,7 +159,7 @@ static void async_read_callback ( GObject *source_object, GAsyncResult *res, gpo
// Absorb separator, already in buffer so should not block.
// If error == NULL end of stream..
g_data_input_stream_read_byte ( stream, NULL, &error );
if ( error == NULL ) {
if ( error == NULL ) {
// Add empty line.
read_add ( pd, "", 0 );
rofi_view_reload ();
@ -204,7 +204,7 @@ static int get_dmenu_async ( DmenuModePrivateData *pd, int sync_pre_read )
}
static void get_dmenu_sync ( DmenuModePrivateData *pd )
{
while ( TRUE ) {
while ( TRUE ) {
gsize len = 0;
char *data = g_data_input_stream_read_upto ( pd->data_input_stream, &( pd->separator ), 1, &len, NULL, NULL );
if ( data == NULL ) {
@ -298,7 +298,7 @@ static void dmenu_mode_free ( Mode *sw )
}
DmenuModePrivateData *pd = (DmenuModePrivateData *) mode_get_private_data ( sw );
if ( pd != NULL ) {
if ( pd->cancel ) {
if ( pd->cancel ) {
// If open, cancel reads.
if ( pd->input_stream && !g_input_stream_is_closed ( pd->input_stream ) ) {
g_cancellable_cancel ( pd->cancel );
@ -368,7 +368,7 @@ static int dmenu_mode_init ( Mode *sw )
// Input data separator.
find_arg_char ( "-sep", &( pd->separator ) );
find_arg_uint ( "-selected-row", &( pd->selected_line ) );
find_arg_uint ( "-selected-row", &( pd->selected_line ) );
// By default we print the unescaped line back.
pd->format = "s";
@ -376,19 +376,31 @@ static int dmenu_mode_init ( Mode *sw )
find_arg_str ( "-format", &( pd->format ) );
// Urgent.
char *str = NULL;
find_arg_str ( "-u", &str );
find_arg_str ( "-u", &str );
if ( str != NULL ) {
parse_ranges ( str, &( pd->urgent_list ), &( pd->num_urgent_list ) );
}
// Active
str = NULL;
find_arg_str ( "-a", &str );
find_arg_str ( "-a", &str );
if ( str != NULL ) {
parse_ranges ( str, &( pd->active_list ), &( pd->num_active_list ) );
}
// DMENU COMPATIBILITY
find_arg_uint ( "-l", &( config.menu_lines ) );
unsigned int lines = DEFAULT_MENU_LINES;
find_arg_uint ( "-l", &( lines ) );
if ( lines != DEFAULT_MENU_LINES ) {
Property *p = rofi_theme_property_create ( P_INTEGER );
p->name = g_strdup("lines");
p->value.i = lines;
ThemeWidget *widget = rofi_theme_find_or_create_name ( rofi_theme, "listview" );
GHashTable *table = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, (GDestroyNotify) rofi_theme_property_free );
g_hash_table_replace ( table, p->name, p );
rofi_theme_widget_add_properties ( widget, table );
g_hash_table_destroy ( table );
}
str = NULL;
find_arg_str ( "-window-title", &str );
@ -422,7 +434,7 @@ static int dmenu_mode_init ( Mode *sw )
}
g_free ( estr );
}
// If input is stdin, and a tty, do not read as rofi grabs input and therefor blocks.
// If input is stdin, and a tty, do not read as rofi grabs input and therefore blocks.
if ( !( fd == STDIN_FILENO && isatty ( fd ) == 1 ) ) {
pd->cancel = g_cancellable_new ();
pd->cancel_source = g_cancellable_connect ( pd->cancel, G_CALLBACK ( async_read_cancel ), pd, NULL );
@ -504,7 +516,7 @@ static void dmenu_finish ( RofiViewState *state, int retv )
else if ( retv >= 10 ) {
rofi_set_return_code ( retv );
}
else{
else {
rofi_set_return_code ( EXIT_SUCCESS );
}
rofi_view_set_active ( NULL );
@ -604,7 +616,7 @@ static void dmenu_finalize ( RofiViewState *state )
// We normally do not want to restart the loop.
restart = FALSE;
// Normal mode
if ( ( mretv & MENU_OK ) && pd->selected_line != UINT32_MAX && cmd_list[pd->selected_line].entry != NULL ) {
if ( ( mretv & MENU_OK ) && pd->selected_line != UINT32_MAX && cmd_list[pd->selected_line].entry != NULL ) {
// Check if entry is non-selectable.
if ( cmd_list[pd->selected_line].nonselectable == TRUE ) {
g_free ( input );
@ -736,7 +748,7 @@ int dmenu_switcher_dialog ( void )
g_free ( input );
return TRUE;
}
find_arg_str ( "-p", &( dmenu_mode.display_name ) );
find_arg_str ( "-p", &( dmenu_mode.display_name ) );
RofiViewState *state = rofi_view_create ( &dmenu_mode, input, menu_flags, dmenu_finalize );
if ( find_arg ( "-keep-right" ) >= 0 ) {

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -51,6 +51,8 @@
#include "widgets/textbox.h"
#include "history.h"
#include "dialogs/drun.h"
#include "dialogs/filebrowser.h"
#include "mode-private.h"
#include "xcb.h"
#include "rofi-icon-fetcher.h"
@ -67,6 +69,7 @@ typedef enum
DRUN_DESKTOP_ENTRY_TYPE_UNDETERMINED = 0,
DRUN_DESKTOP_ENTRY_TYPE_APPLICATION,
DRUN_DESKTOP_ENTRY_TYPE_LINK,
DRUN_DESKTOP_ENTRY_TYPE_SERVICE,
DRUN_DESKTOP_ENTRY_TYPE_DIRECTORY,
} DRunDesktopEntryType;
@ -120,7 +123,8 @@ typedef struct
typedef struct
{
const char *entry_field_name;
gboolean enabled;
gboolean enabled_match;
gboolean enabled_display;
} DRunEntryField;
typedef enum
@ -135,12 +139,12 @@ typedef enum
} DRunMatchingFields;
static DRunEntryField matching_entry_fields[DRUN_MATCH_NUM_FIELDS] = {
{ .entry_field_name = "name", .enabled = TRUE, },
{ .entry_field_name = "generic", .enabled = TRUE, },
{ .entry_field_name = "exec", .enabled = TRUE, },
{ .entry_field_name = "categories", .enabled = TRUE, },
{ .entry_field_name = "keywords", .enabled = TRUE, },
{ .entry_field_name = "comment", .enabled = FALSE, }
{ .entry_field_name = "name", .enabled_match = TRUE, .enabled_display = TRUE, },
{ .entry_field_name = "generic", .enabled_match = TRUE, .enabled_display = TRUE, },
{ .entry_field_name = "exec", .enabled_match = TRUE, .enabled_display = TRUE, },
{ .entry_field_name = "categories", .enabled_match = TRUE, .enabled_display = TRUE, },
{ .entry_field_name = "keywords", .enabled_match = TRUE, .enabled_display = TRUE, },
{ .entry_field_name = "comment", .enabled_match = FALSE,.enabled_display = FALSE,}
};
struct _DRunModePrivateData
@ -159,11 +163,23 @@ struct _DRunModePrivateData
const gchar *icon_theme;
// DE
gchar **current_desktop_list;
gboolean file_complete;
Mode *completer;
char *old_completer_input;
uint32_t selected_line;
char *old_input;
/** fallback icon */
uint32_t fallback_icon_fetch_uid;
cairo_surface_t *fallback_icon;
};
struct RegexEvalArg
{
DRunModeEntry *e;
const char *path;
gboolean success;
};
@ -178,12 +194,19 @@ static gboolean drun_helper_eval_cb ( const GMatchInfo *info, GString *res, gpoi
if ( match != NULL ) {
switch ( match[1] )
{
// Unsupported
case 'f':
case 'F':
case 'u':
case 'U':
g_string_append(res, e->path);
break;
// Unsupported
case 'i':
// TODO
if ( e->e && e->e->icon ) {
g_string_append_printf(res, "--icon %s", e->e->icon_name );
}
break;
// Deprecated
case 'd':
case 'D':
@ -257,7 +280,7 @@ static void launch_link_entry ( DRunModeEntry *e )
g_free ( path );
}
}
static void exec_cmd_entry ( DRunModeEntry *e )
static void exec_cmd_entry ( DRunModeEntry *e, const char *path )
{
GError *error = NULL;
GRegex *reg = g_regex_new ( "%[a-zA-Z%]", 0, 0, &error );
@ -266,7 +289,7 @@ static void exec_cmd_entry ( DRunModeEntry *e )
g_error_free ( error );
return;
}
struct RegexEvalArg earg = { .e = e, .success = TRUE };
struct RegexEvalArg earg = { .e = e, .path = path, .success = TRUE };
char *str = g_regex_replace_eval ( reg, e->exec, -1, 0, 0, drun_helper_eval_cb, &earg, &error );
if ( error != NULL ) {
g_warning ( "Internal error, failed replace field codes: %s.", error->message );
@ -397,6 +420,10 @@ static void read_desktop_file ( DRunModePrivateData *pd, const char *root, const
else if ( !g_strcmp0 ( key, "Link" ) ) {
desktop_entry_type = DRUN_DESKTOP_ENTRY_TYPE_LINK;
}
else if ( !g_strcmp0 ( key, "Service" ) ) {
desktop_entry_type = DRUN_DESKTOP_ENTRY_TYPE_SERVICE;
g_debug ( "Service file detected." );
}
else {
g_debug ( "[%s] [%s] Skipping desktop file: Not of type Application or Link (%s)", id, path, key );
g_free ( key );
@ -441,7 +468,7 @@ static void read_desktop_file ( DRunModePrivateData *pd, const char *root, const
if ( list ) {
for ( gsize lcd = 0; show && pd->current_desktop_list[lcd]; lcd++ ) {
for ( gsize lle = 0; show && lle < llength; lle++ ) {
show = !( g_strcmp0 ( pd->current_desktop_list[lcd], list[lle] ) == 0 );
show = !( g_strcmp0 ( pd->current_desktop_list[lcd], list[lle] ) == 0 );
}
}
g_strfreev ( list );
@ -470,6 +497,12 @@ static void read_desktop_file ( DRunModePrivateData *pd, const char *root, const
g_key_file_free ( kf );
return;
}
if ( desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_SERVICE
&& !g_key_file_has_key ( kf, DRUN_GROUP_NAME, "Exec", NULL ) ) {
g_debug ( "[%s] [%s] Unsupported desktop file: no 'Exec' key present for type Service.", id, path );
g_key_file_free ( kf );
return;
}
if ( desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_LINK
&& !g_key_file_has_key ( kf, DRUN_GROUP_NAME, "URL", NULL ) ) {
g_debug ( "[%s] [%s] Unsupported desktop file: no 'URL' key present for type Link.", id, path );
@ -501,7 +534,7 @@ static void read_desktop_file ( DRunModePrivateData *pd, const char *root, const
char **categories = NULL;
if ( pd->show_categories ) {
categories = g_key_file_get_locale_string_list ( kf, DRUN_GROUP_NAME, "Categories", NULL, NULL, NULL );
if ( !rofi_strv_contains ( (const char * const *) categories, (const char * const *) pd->show_categories ) ) {
if ( !rofi_strv_contains ( (const char * const *) categories, (const char * const *) pd->show_categories ) ) {
g_strfreev ( categories );
g_key_file_free ( kf );
return;
@ -540,15 +573,16 @@ static void read_desktop_file ( DRunModePrivateData *pd, const char *root, const
pd->entry_list[pd->cmd_list_length].action = DRUN_GROUP_NAME;
gchar *gn = g_key_file_get_locale_string ( kf, DRUN_GROUP_NAME, "GenericName", NULL, NULL );
pd->entry_list[pd->cmd_list_length].generic_name = gn;
if ( matching_entry_fields[DRUN_MATCH_FIELD_KEYWORDS].enabled ) {
if ( matching_entry_fields[DRUN_MATCH_FIELD_KEYWORDS].enabled_match
|| matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled_display) {
pd->entry_list[pd->cmd_list_length].keywords = g_key_file_get_locale_string_list ( kf, DRUN_GROUP_NAME, "Keywords", NULL, NULL, NULL );
}
else {
pd->entry_list[pd->cmd_list_length].keywords = NULL;
}
if ( matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled ) {
if ( matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled_match
|| matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled_display ) {
if ( categories ) {
pd->entry_list[pd->cmd_list_length].categories = categories;
categories = NULL;
@ -563,26 +597,23 @@ static void read_desktop_file ( DRunModePrivateData *pd, const char *root, const
g_strfreev ( categories );
pd->entry_list[pd->cmd_list_length].type = desktop_entry_type;
if ( desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_APPLICATION ) {
if ( desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_APPLICATION ||
desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_SERVICE ) {
pd->entry_list[pd->cmd_list_length].exec = g_key_file_get_string ( kf, action, "Exec", NULL );
}
else {
pd->entry_list[pd->cmd_list_length].exec = NULL;
}
if ( matching_entry_fields[DRUN_MATCH_FIELD_COMMENT].enabled ) {
if ( matching_entry_fields[DRUN_MATCH_FIELD_COMMENT].enabled_match
|| matching_entry_fields[DRUN_MATCH_FIELD_COMMENT].enabled_display ) {
pd->entry_list[pd->cmd_list_length].comment = g_key_file_get_locale_string ( kf,
DRUN_GROUP_NAME, "Comment", NULL, NULL );
}
else {
pd->entry_list[pd->cmd_list_length].comment = NULL;
}
if ( config.show_icons ) {
pd->entry_list[pd->cmd_list_length].icon_name = g_key_file_get_locale_string ( kf, DRUN_GROUP_NAME, "Icon", NULL, NULL );
}
else{
pd->entry_list[pd->cmd_list_length].icon_name = NULL;
}
pd->entry_list[pd->cmd_list_length].icon_name = g_key_file_get_locale_string ( kf, DRUN_GROUP_NAME, "Icon", NULL, NULL );
pd->entry_list[pd->cmd_list_length].icon = NULL;
// Keep keyfile around.
@ -712,6 +743,15 @@ static gint drun_int_sort_list ( gconstpointer a, gconstpointer b, G_GNUC_UNUSED
DRunModeEntry *db = (DRunModeEntry *) b;
if ( da->sort_index < 0 && db->sort_index < 0 ) {
if ( da->name == NULL && db->name == NULL ) {
return 0;
}
else if ( da->name == NULL ) {
return -1;
}
else if ( db->name == NULL ) {
return 1;
}
return g_utf8_collate ( da->name, db->name );
}
else {
@ -907,30 +947,41 @@ static void get_apps ( DRunModePrivateData *pd )
char *cache_file = g_build_filename ( cache_dir, DRUN_DESKTOP_CACHE_FILE, NULL );
TICK_N ( "Get Desktop apps (start)" );
if ( drun_read_cache ( pd, cache_file ) ) {
gchar *dir;
// First read the user directory.
dir = g_build_filename ( g_get_user_data_dir (), "applications", NULL );
walk_dir ( pd, dir, dir );
g_free ( dir );
TICK_N ( "Get Desktop apps (user dir)" );
// Then read thee system data dirs.
const gchar * const * sys = g_get_system_data_dirs ();
for ( const gchar * const *iter = sys; *iter != NULL; ++iter ) {
ThemeWidget *wid = rofi_config_find_widget ( drun_mode.name, NULL, TRUE );
/** Load user entires */
Property *p = rofi_theme_find_property ( wid, P_BOOLEAN, "parse-user", TRUE );
if ( p == NULL || ( p->type == P_BOOLEAN && p->value.b )) {
gchar *dir;
// First read the user directory.
dir = g_build_filename ( g_get_user_data_dir (), "applications", NULL );
walk_dir ( pd, dir, dir );
g_free ( dir );
TICK_N ( "Get Desktop apps (user dir)" );
}
/** Load application entires */
p = rofi_theme_find_property ( wid, P_BOOLEAN, "parse-system", TRUE );
if ( p == NULL || ( p->type == P_BOOLEAN && p->value.b )) {
// Then read thee system data dirs.
const gchar * const * sys = g_get_system_data_dirs ();
for ( const gchar * const *iter = sys; *iter != NULL; ++iter ) {
gboolean unique = TRUE;
// Stupid duplicate detection, better then walking dir.
for ( const gchar *const *iterd = sys; iterd != iter; ++iterd ) {
if ( g_strcmp0 ( *iter, *iterd ) == 0 ) {
unique = FALSE;
}
if ( g_strcmp0 ( *iter, *iterd ) == 0 ) {
unique = FALSE;
}
}
// Check, we seem to be getting empty string...
if ( unique && ( **iter ) != '\0' ) {
dir = g_build_filename ( *iter, "applications", NULL );
walk_dir ( pd, dir, dir );
g_free ( dir );
char *dir = g_build_filename ( *iter, "applications", NULL );
walk_dir ( pd, dir, dir );
g_free ( dir );
}
}
TICK_N ( "Get Desktop apps (system dirs)" );
}
TICK_N ( "Get Desktop apps (system dirs)" );
get_apps_history ( pd );
g_qsort_with_data ( pd->entry_list, pd->cmd_list_length, sizeof ( DRunModeEntry ), drun_int_sort_list, NULL );
@ -950,13 +1001,15 @@ static void drun_mode_parse_entry_fields ()
const char * const sep = ",#";
// Split token on ','. This modifies switcher_str.
for ( unsigned int i = 0; i < DRUN_MATCH_NUM_FIELDS; i++ ) {
matching_entry_fields[i].enabled = FALSE;
matching_entry_fields[i].enabled_match = FALSE;
matching_entry_fields[i].enabled_display = FALSE;
}
for ( char *token = strtok_r ( switcher_str, sep, &savept ); token != NULL;
token = strtok_r ( NULL, sep, &savept ) ) {
if ( strcmp ( token, "all" ) == 0 ) {
for ( unsigned int i = 0; i < DRUN_MATCH_NUM_FIELDS; i++ ) {
matching_entry_fields[i].enabled = TRUE;
matching_entry_fields[i].enabled_match = TRUE;
matching_entry_fields[i].enabled_display = TRUE;
}
break;
}
@ -965,7 +1018,8 @@ static void drun_mode_parse_entry_fields ()
for ( unsigned int i = 0; i < DRUN_MATCH_NUM_FIELDS; i++ ) {
const char * entry_name = matching_entry_fields[i].entry_field_name;
if ( g_ascii_strcasecmp ( token, entry_name ) == 0 ) {
matching_entry_fields[i].enabled = TRUE;
matching_entry_fields[i].enabled_match = TRUE;
matching_entry_fields[i].enabled_display = TRUE;
matched = TRUE;
}
}
@ -978,6 +1032,18 @@ static void drun_mode_parse_entry_fields ()
g_free ( switcher_str );
}
static void drun_mode_parse_display_format() {
for ( int i = 0; i < DRUN_MATCH_NUM_FIELDS; i++ ) {
if ( matching_entry_fields[i].enabled_display ) continue;
gchar* search_term = g_strdup_printf("{%s}",matching_entry_fields[i].entry_field_name);
if ( strstr( config.drun_display_format, search_term) ) {
matching_entry_fields[i].enabled_match = TRUE;
}
g_free( search_term );
}
}
static int drun_mode_init ( Mode *sw )
{
if ( mode_get_private_data ( sw ) != NULL ) {
@ -986,7 +1052,7 @@ static int drun_mode_init ( Mode *sw )
DRunModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) );
pd->disabled_entries = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, NULL );
mode_set_private_data ( sw, (void *) pd );
// current destkop
// current desktop
const char *current_desktop = g_getenv ( "XDG_CURRENT_DESKTOP" );
pd->current_desktop_list = current_desktop ? g_strsplit ( current_desktop, ":", 0 ) : NULL;
@ -995,7 +1061,11 @@ static int drun_mode_init ( Mode *sw )
}
drun_mode_parse_entry_fields ();
drun_mode_parse_display_format();
get_apps ( pd );
pd->completer = create_new_file_browser ();
mode_init ( pd->completer );
return TRUE;
}
static void drun_entry_clear ( DRunModeEntry *e )
@ -1027,11 +1097,39 @@ static ModeMode drun_mode_result ( Mode *sw, int mretv, char **input, unsigned i
DRunModePrivateData *rmpd = (DRunModePrivateData *) mode_get_private_data ( sw );
ModeMode retv = MODE_EXIT;
if ( ( mretv & MENU_OK ) ) {
if ( rmpd->file_complete == TRUE ) {
retv = RELOAD_DIALOG;
if ( ( mretv& (MENU_COMPLETE)) ) {
g_free ( rmpd->old_completer_input );
rmpd->old_completer_input = *input;
*input = NULL;
if ( rmpd->selected_line < rmpd->cmd_list_length ) {
(*input) = g_strdup ( rmpd->old_input );
}
rmpd->file_complete = FALSE;
}
else if ( (mretv&MENU_CANCEL) ) {
retv = MODE_EXIT;
}
else {
char *path = NULL;
retv = file_browser_mode_completer ( rmpd->completer, mretv, input, selected_line, &path );
if ( retv == MODE_EXIT ) {
exec_cmd_entry ( &( rmpd->entry_list[rmpd->selected_line] ), path );
}
g_free (path);
}
return retv;
}
if ( ( mretv & MENU_OK ) ) {
switch ( rmpd->entry_list[selected_line].type )
{
case DRUN_DESKTOP_ENTRY_TYPE_SERVICE:
case DRUN_DESKTOP_ENTRY_TYPE_APPLICATION:
exec_cmd_entry ( &( rmpd->entry_list[selected_line] ) );
exec_cmd_entry ( &( rmpd->entry_list[selected_line] ), NULL );
break;
case DRUN_DESKTOP_ENTRY_TYPE_LINK:
launch_link_entry ( &( rmpd->entry_list[selected_line] ) );
@ -1049,7 +1147,7 @@ static ModeMode drun_mode_result ( Mode *sw, int mretv, char **input, unsigned i
}
}
else if ( ( mretv & MENU_ENTRY_DELETE ) && selected_line < rmpd->cmd_list_length ) {
// Possitive sort index means it is in history.
// Positive sort index means it is in history.
if ( rmpd->entry_list[selected_line].sort_index >= 0 ) {
delete_entry_history ( &( rmpd->entry_list[selected_line] ) );
drun_entry_clear ( &( rmpd->entry_list[selected_line] ) );
@ -1059,6 +1157,38 @@ static ModeMode drun_mode_result ( Mode *sw, int mretv, char **input, unsigned i
}
retv = RELOAD_DIALOG;
}
else if ( mretv & MENU_CUSTOM_COMMAND ) {
retv = ( mretv & MENU_LOWER_MASK );
}
else if ( ( mretv& MENU_COMPLETE) ) {
retv = RELOAD_DIALOG;
if ( selected_line < rmpd->cmd_list_length ) {
switch ( rmpd->entry_list[selected_line].type )
{
case DRUN_DESKTOP_ENTRY_TYPE_SERVICE:
case DRUN_DESKTOP_ENTRY_TYPE_APPLICATION:
{
GRegex *regex = g_regex_new ("%[fFuU]", 0, 0, NULL);
if (g_regex_match (regex, rmpd->entry_list[selected_line].exec, 0, NULL) ) {
rmpd->selected_line = selected_line;
// TODO add check if it supports passing file.
g_free ( rmpd->old_input );
rmpd->old_input = g_strdup ( *input );
if ( *input ) g_free (*input);
*input = g_strdup ( rmpd->old_completer_input );
rmpd->file_complete = TRUE;
}
g_regex_unref ( regex );
}
default:
break;
}
}
}
return retv;
}
static void drun_mode_destroy ( Mode *sw )
@ -1071,6 +1201,10 @@ static void drun_mode_destroy ( Mode *sw )
g_hash_table_destroy ( rmpd->disabled_entries );
g_free ( rmpd->entry_list );
g_free ( rmpd->old_completer_input );
g_free ( rmpd->old_input );
mode_destroy ( rmpd->completer );
g_strfreev ( rmpd->current_desktop_list );
g_strfreev ( rmpd->show_categories );
g_free ( rmpd );
@ -1081,6 +1215,10 @@ static void drun_mode_destroy ( Mode *sw )
static char *_get_display_value ( const Mode *sw, unsigned int selected_line, int *state, G_GNUC_UNUSED GList **list, int get_entry )
{
DRunModePrivateData *pd = (DRunModePrivateData *) mode_get_private_data ( sw );
if ( pd->file_complete ) {
return pd->completer->_get_display_value (pd->completer, selected_line, state, list, get_entry );
}
*state |= MARKUP;
if ( !get_entry ) {
return NULL;
@ -1136,19 +1274,40 @@ static char *_get_display_value ( const Mode *sw, unsigned int selected_line, in
return retv;
}
static cairo_surface_t *fallback_icon ( DRunModePrivateData *pd, int height )
{
if ( config.application_fallback_icon ) {
// FALLBACK
if ( pd->fallback_icon_fetch_uid > 0 ) {
return rofi_icon_fetcher_get ( pd->fallback_icon_fetch_uid );
}
pd->fallback_icon_fetch_uid = rofi_icon_fetcher_query ( config.application_fallback_icon, height );
}
return NULL;
}
static cairo_surface_t *_get_icon ( const Mode *sw, unsigned int selected_line, int height )
{
DRunModePrivateData *pd = (DRunModePrivateData *) mode_get_private_data ( sw );
if ( pd->file_complete ) {
return pd->completer->_get_icon ( pd->completer, selected_line, height );
}
g_return_val_if_fail ( pd->entry_list != NULL, NULL );
DRunModeEntry *dr = &( pd->entry_list[selected_line] );
if ( dr->icon_name == NULL ) {
return NULL;
if ( dr->icon_name != NULL ) {
if ( dr->icon_fetch_uid > 0 ) {
cairo_surface_t *icon = rofi_icon_fetcher_get ( dr->icon_fetch_uid );
if ( icon ) {
return icon;
}
return fallback_icon ( pd, height );
}
dr->icon_fetch_uid = rofi_icon_fetcher_query ( dr->icon_name, height );
cairo_surface_t *icon = rofi_icon_fetcher_get ( dr->icon_fetch_uid );
if ( icon ) {
return icon;
}
}
if ( dr->icon_fetch_uid > 0 ) {
return rofi_icon_fetcher_get ( dr->icon_fetch_uid );
}
dr->icon_fetch_uid = rofi_icon_fetcher_query ( dr->icon_name, height );
return rofi_icon_fetcher_get ( dr->icon_fetch_uid );
return fallback_icon ( pd, height );
}
static char *drun_get_completion ( const Mode *sw, unsigned int index )
@ -1167,30 +1326,33 @@ static char *drun_get_completion ( const Mode *sw, unsigned int index )
static int drun_token_match ( const Mode *data, rofi_int_matcher **tokens, unsigned int index )
{
DRunModePrivateData *rmpd = (DRunModePrivateData *) mode_get_private_data ( data );
int match = 1;
if ( rmpd->file_complete ) {
return rmpd->completer->_token_match (rmpd->completer, tokens, index );
}
int match = 1;
if ( tokens ) {
for ( int j = 0; match && tokens != NULL && tokens[j] != NULL; j++ ) {
int test = 0;
rofi_int_matcher *ftokens[2] = { tokens[j], NULL };
// Match name
if ( matching_entry_fields[DRUN_MATCH_FIELD_NAME].enabled ) {
if ( matching_entry_fields[DRUN_MATCH_FIELD_NAME].enabled_match ) {
if ( rmpd->entry_list[index].name ) {
test = helper_token_match ( ftokens, rmpd->entry_list[index].name );
}
}
if ( matching_entry_fields[DRUN_MATCH_FIELD_GENERIC].enabled ) {
if ( matching_entry_fields[DRUN_MATCH_FIELD_GENERIC].enabled_match ) {
// Match generic name
if ( test == tokens[j]->invert && rmpd->entry_list[index].generic_name ) {
test = helper_token_match ( ftokens, rmpd->entry_list[index].generic_name );
}
}
if ( matching_entry_fields[DRUN_MATCH_FIELD_EXEC].enabled ) {
if ( matching_entry_fields[DRUN_MATCH_FIELD_EXEC].enabled_match ) {
// Match executable name.
if ( test == tokens[j]->invert && rmpd->entry_list[index].exec ) {
test = helper_token_match ( ftokens, rmpd->entry_list[index].exec );
}
}
if ( matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled ) {
if ( matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled_match ) {
// Match against category.
if ( test == tokens[j]->invert ) {
gchar **list = rmpd->entry_list[index].categories;
@ -1199,7 +1361,7 @@ static int drun_token_match ( const Mode *data, rofi_int_matcher **tokens, unsig
}
}
}
if ( matching_entry_fields[DRUN_MATCH_FIELD_KEYWORDS].enabled ) {
if ( matching_entry_fields[DRUN_MATCH_FIELD_KEYWORDS].enabled_match ) {
// Match against category.
if ( test == tokens[j]->invert ) {
gchar **list = rmpd->entry_list[index].keywords;
@ -1208,7 +1370,8 @@ static int drun_token_match ( const Mode *data, rofi_int_matcher **tokens, unsig
}
}
}
if ( matching_entry_fields[DRUN_MATCH_FIELD_COMMENT].enabled ) {
if ( matching_entry_fields[DRUN_MATCH_FIELD_COMMENT].enabled_match ) {
// Match executable name.
if ( test == tokens[j]->invert && rmpd->entry_list[index].comment ) {
test = helper_token_match ( ftokens, rmpd->entry_list[index].comment );
@ -1226,8 +1389,27 @@ static int drun_token_match ( const Mode *data, rofi_int_matcher **tokens, unsig
static unsigned int drun_mode_get_num_entries ( const Mode *sw )
{
const DRunModePrivateData *pd = (const DRunModePrivateData *) mode_get_private_data ( sw );
if ( pd->file_complete ) {
return pd->completer->_get_num_entries( pd->completer );
}
return pd->cmd_list_length;
}
static char *drun_get_message ( const Mode *sw )
{
DRunModePrivateData *pd = sw->private_data;
if ( pd->file_complete ) {
if ( pd->selected_line < pd->cmd_list_length ) {
char *msg = mode_get_message ( pd->completer);
if ( msg ) {
char *retv = g_strdup_printf("File complete for: %s\n%s", pd->entry_list[pd->selected_line].name, msg);
g_free (msg);
return retv;
}
return g_strdup_printf("File complete for: %s", pd->entry_list[pd->selected_line].name);
}
}
return NULL;
}
#include "mode-private.h"
Mode drun_mode =
{
@ -1238,6 +1420,7 @@ Mode drun_mode =
._result = drun_mode_result,
._destroy = drun_mode_destroy,
._token_match = drun_token_match,
._get_message = drun_get_message,
._get_completion = drun_get_completion,
._get_display_value = _get_display_value,
._get_icon = _get_icon,

View file

@ -36,6 +36,7 @@
#include <dirent.h>
#include "mode.h"
#include "theme.h"
#include "helper.h"
#include "mode-private.h"
#include "dialogs/filebrowser.h"
@ -58,6 +59,27 @@ enum FBFileType
RFILE,
NUM_FILE_TYPES,
};
/**
* Possible sorting methods
*/
enum FBSortingMethod
{
FB_SORT_NAME,
FB_SORT_TIME,
};
/**
* Type of time to sort by
*/
enum FBSortingTime
{
FB_MTIME,
FB_ATIME,
FB_CTIME,
};
/** Icons to use for the file type */
const char *icon_name[NUM_FILE_TYPES] =
{
"go-up",
@ -71,6 +93,7 @@ typedef struct
enum FBFileType type;
uint32_t icon_fetch_uid;
gboolean link;
time_t time;
} FBFile;
typedef struct
@ -80,6 +103,17 @@ typedef struct
unsigned int array_length;
} FileBrowserModePrivateData;
struct
{
enum FBSortingMethod sorting_method;
enum FBSortingTime sorting_time;
gboolean directories_first;
} file_browser_config = {
.sorting_method = FB_SORT_NAME,
.sorting_time = FB_MTIME,
.directories_first = TRUE,
};
static void free_list ( FileBrowserModePrivateData *pd )
{
for ( unsigned int i = 0; i < pd->array_length; i++ ) {
@ -94,18 +128,90 @@ static void free_list ( FileBrowserModePrivateData *pd )
#include <sys/types.h>
#include <dirent.h>
static gint compare ( gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer data )
static gint compare_name ( gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer data )
{
FBFile *fa = (FBFile*) a;
FBFile *fb = (FBFile*) b;
if ( fa->type != fb->type ) {
FBFile *fa = (FBFile *) a;
FBFile *fb = (FBFile *) b;
if ( file_browser_config.directories_first && fa->type != fb->type ) {
return fa->type - fb->type;
}
return g_strcmp0 ( fa->name, fb->name );
}
static void get_file_browser ( Mode *sw )
static gint compare_time ( gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer data )
{
FBFile *fa = (FBFile *) a;
FBFile *fb = (FBFile *) b;
if ( file_browser_config.directories_first && fa->type != fb->type ) {
return fa->type - fb->type;
}
if ( fa->time < 0 ) {
return -1;
}
if ( fb->time < 0 ) {
return 1;
}
return fb->time - fa->time;
}
static gint compare ( gconstpointer a, gconstpointer b, gpointer data )
{
GCompareDataFunc comparator = NULL;
switch ( file_browser_config.sorting_method )
{
case FB_SORT_NAME:
comparator = compare_name;
break;
case FB_SORT_TIME:
comparator = compare_time;
break;
default:
comparator = compare_name;
break;
}
return comparator ( a, b, data );
}
static time_t get_time ( const struct stat *statbuf )
{
switch ( file_browser_config.sorting_time )
{
case FB_MTIME:
return statbuf->st_mtim.tv_sec;
case FB_ATIME:
return statbuf->st_atim.tv_sec;
case FB_CTIME:
return statbuf->st_ctim.tv_sec;
default:
return 0;
}
}
static void set_time ( FBFile *file )
{
gchar* path = g_filename_from_utf8 ( file->path, -1, NULL, NULL, NULL );
struct stat statbuf;
if ( stat ( path, &statbuf ) == 0 ) {
file->time = get_time ( &statbuf );
}
else {
g_warning ( "Failed to stat file: %s, %s", path, strerror ( errno ) );
}
g_free ( path );
}
static void get_file_browser ( Mode *sw )
{
FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw );
/**
@ -125,6 +231,7 @@ static void get_file_browser ( Mode *sw )
pd->array[pd->array_length].type = UP;
pd->array[pd->array_length].icon_fetch_uid = 0;
pd->array[pd->array_length].link = FALSE;
pd->array[pd->array_length].time = -1;
pd->array_length++;
continue;
}
@ -150,6 +257,11 @@ static void get_file_browser ( Mode *sw )
pd->array[pd->array_length].type = ( rd->d_type == DT_DIR ) ? DIRECTORY : RFILE;
pd->array[pd->array_length].icon_fetch_uid = 0;
pd->array[pd->array_length].link = FALSE;
if ( file_browser_config.sorting_method == FB_SORT_TIME ) {
set_time ( &pd->array[pd->array_length] );
}
pd->array_length++;
break;
case DT_LNK:
@ -163,7 +275,7 @@ static void get_file_browser ( Mode *sw )
pd->array[pd->array_length].type = RFILE;
{
// If we have link, use a stat to fine out what it is, if we fail, we mark it as file.
// TODO have a 'broken link' mode?
// TODO have a 'broken link' mode?
// Convert full path to right encoding.
char *file = g_filename_from_utf8 ( pd->array[pd->array_length].path, -1, NULL, NULL, NULL );
if ( file ) {
@ -175,6 +287,10 @@ static void get_file_browser ( Mode *sw )
else if ( S_ISREG ( statbuf.st_mode ) ) {
pd->array[pd->array_length].type = RFILE;
}
if ( file_browser_config.sorting_method == FB_SORT_TIME ) {
pd->array[pd->array_length].time = get_time ( &statbuf );
}
}
else {
g_warning ( "Failed to stat file: %s, %s", file, strerror ( errno ) );
@ -192,6 +308,83 @@ static void get_file_browser ( Mode *sw )
g_qsort_with_data ( pd->array, pd->array_length, sizeof ( FBFile ), compare, NULL );
}
static void file_browser_mode_init_config ( Mode *sw )
{
char *msg = NULL;
gboolean found_error = FALSE;
ThemeWidget *wid = rofi_config_find_widget ( sw->name, NULL, TRUE );
Property *p = rofi_theme_find_property ( wid, P_STRING, "sorting-method", TRUE );
if ( p != NULL && p->type == P_STRING ) {
if ( g_strcmp0 ( p->value.s, "name" ) == 0 ) {
file_browser_config.sorting_method = FB_SORT_NAME;
}
else if ( g_strcmp0 ( p->value.s, "mtime" ) == 0 ) {
file_browser_config.sorting_method = FB_SORT_TIME;
file_browser_config.sorting_time = FB_MTIME;
}
else if ( g_strcmp0 ( p->value.s, "atime" ) == 0 ) {
file_browser_config.sorting_method = FB_SORT_TIME;
file_browser_config.sorting_time = FB_ATIME;
}
else if ( g_strcmp0 ( p->value.s, "ctime" ) == 0 ) {
file_browser_config.sorting_method = FB_SORT_TIME;
file_browser_config.sorting_time = FB_CTIME;
}
else {
found_error = TRUE;
msg = g_strdup_printf ( "\"%s\" is not a valid filebrowser sorting method", p->value.s );
}
}
p = rofi_theme_find_property ( wid, P_BOOLEAN, "directories-first", TRUE );
if ( p != NULL && p->type == P_BOOLEAN ) {
file_browser_config.directories_first = p->value.b;
}
if ( found_error ) {
rofi_view_error_dialog ( msg, FALSE );
g_free ( msg );
}
}
static void file_browser_mode_init_current_dir ( Mode *sw ) {
FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw );
ThemeWidget *wid = rofi_config_find_widget ( sw->name, NULL, TRUE );
Property *p = rofi_theme_find_property ( wid, P_STRING, "directory", TRUE );
gboolean config_has_valid_dir = p != NULL && p->type == P_STRING
&& g_file_test ( p->value.s, G_FILE_TEST_IS_DIR );
if ( config_has_valid_dir ) {
pd->current_dir = g_file_new_for_path ( p->value.s );
} else {
char *current_dir = NULL;
char *cache_file = g_build_filename ( cache_dir, FILEBROWSER_CACHE_FILE, NULL );
if ( g_file_get_contents ( cache_file, &current_dir, NULL, NULL ) ) {
if ( g_file_test ( current_dir, G_FILE_TEST_IS_DIR ) ) {
pd->current_dir = g_file_new_for_path ( current_dir );
}
g_free ( current_dir );
}
// Store it based on the unique identifiers (desktop_id).
g_free ( cache_file );
}
if ( pd->current_dir == NULL ) {
pd->current_dir = g_file_new_for_path ( g_get_home_dir () );
}
}
static int file_browser_mode_init ( Mode *sw )
{
/**
@ -200,21 +393,10 @@ static int file_browser_mode_init ( Mode *sw )
if ( mode_get_private_data ( sw ) == NULL ) {
FileBrowserModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) );
mode_set_private_data ( sw, (void *) pd );
{
char *path = g_build_filename ( cache_dir, FILEBROWSER_CACHE_FILE, NULL );
char *file = NULL;
if ( g_file_get_contents ( path, &file, NULL, NULL ) ) {
if ( g_file_test ( file, G_FILE_TEST_IS_DIR ) ) {
pd->current_dir = g_file_new_for_path ( file );
}
g_free ( file );
}
// Store it based on the unique identifiers (desktop_id).
g_free ( path );
if ( pd->current_dir == NULL ) {
pd->current_dir = g_file_new_for_path ( g_get_home_dir () );
}
}
file_browser_mode_init_config ( sw );
file_browser_mode_init_current_dir ( sw );
// Load content.
get_file_browser ( sw );
}
@ -239,6 +421,9 @@ static ModeMode file_browser_mode_result ( Mode *sw, int mretv, char **input, un
else if ( mretv & MENU_QUICK_SWITCH ) {
retv = ( mretv & MENU_LOWER_MASK );
}
else if ( mretv & MENU_CUSTOM_COMMAND ) {
retv = ( mretv & MENU_LOWER_MASK );
}
else if ( ( mretv & MENU_OK ) ) {
if ( selected_line < pd->array_length ) {
if ( pd->array[selected_line].type == UP ) {
@ -263,8 +448,10 @@ static ModeMode file_browser_mode_result ( Mode *sw, int mretv, char **input, un
return RESET_DIALOG;
}
else if ( pd->array[selected_line].type == RFILE ) {
char *d = g_filename_from_utf8 ( pd->array[selected_line].path, -1, NULL, NULL, NULL );
char *cmd = g_strdup_printf ( "xdg-open '%s'", d );
char *d = g_filename_from_utf8 ( pd->array[selected_line].path, -1, NULL, NULL, NULL );
char *d_esc = g_shell_quote ( d );
char *cmd = g_strdup_printf ( "xdg-open %s", d_esc );
g_free ( d_esc );
g_free ( d );
char *cdir = g_file_get_path ( pd->current_dir );
helper_execute_command ( cdir, cmd, FALSE, NULL );
@ -279,7 +466,7 @@ static ModeMode file_browser_mode_result ( Mode *sw, int mretv, char **input, un
char *p = rofi_expand_path ( *input );
char *dir = g_filename_from_utf8 ( p, -1, NULL, NULL, NULL );
g_free ( p );
if ( g_file_test ( dir, G_FILE_TEST_EXISTS ) ) {
if ( g_file_test ( dir, G_FILE_TEST_EXISTS ) ) {
if ( g_file_test ( dir, G_FILE_TEST_IS_DIR ) ) {
g_object_unref ( pd->current_dir );
pd->current_dir = g_file_new_for_path ( dir );
@ -395,7 +582,7 @@ Mode *create_new_file_browser ( void )
return sw;
}
#if 0
#if 1
ModeMode file_browser_mode_completer ( Mode *sw, int mretv, char **input, unsigned int selected_line, char **path )
{
ModeMode retv = MODE_EXIT;
@ -440,7 +627,7 @@ ModeMode file_browser_mode_completer ( Mode *sw, int mretv, char **input, unsign
char *p = rofi_expand_path ( *input );
char *dir = g_filename_from_utf8 ( p, -1, NULL, NULL, NULL );
g_free ( p );
if ( g_file_test ( dir, G_FILE_TEST_EXISTS ) ) {
if ( g_file_test ( dir, G_FILE_TEST_EXISTS ) ) {
if ( g_file_test ( dir, G_FILE_TEST_IS_DIR ) ) {
g_object_unref ( pd->current_dir );
pd->current_dir = g_file_new_for_path ( dir );
@ -464,8 +651,8 @@ Mode file_browser_mode =
{
.display_name = NULL,
.abi_version = ABI_VERSION,
.name = "file-browser",
.cfg_name_key = "display-file_browser",
.name = "filebrowser",
.cfg_name_key = "display-filebrowser",
._init = file_browser_mode_init,
._get_num_entries = file_browser_mode_get_num_entries,
._result = file_browser_mode_result,

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -71,6 +71,10 @@ static ModeMode help_keys_mode_result ( G_GNUC_UNUSED Mode *sw,
G_GNUC_UNUSED char **input,
G_GNUC_UNUSED unsigned int selected_line )
{
if ( mretv & MENU_CUSTOM_COMMAND ) {
int retv = ( mretv & MENU_LOWER_MASK );
return retv;
}
return MODE_EXIT;
}
static void help_keys_mode_destroy ( Mode *sw )

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -51,6 +51,7 @@
#include "helper.h"
#include "history.h"
#include "dialogs/run.h"
#include "dialogs/filebrowser.h"
#include "mode-private.h"
@ -61,15 +62,34 @@
*/
#define RUN_CACHE_FILE "rofi-3.runcache"
typedef struct
{
char *entry;
uint32_t icon_fetch_uid;
/* Surface holding the icon. */
cairo_surface_t *icon;
} RunEntry;
/**
* The internal data structure holding the private data of the Run Mode.
*/
typedef struct
{
/** list of available commands. */
char **cmd_list;
RunEntry *cmd_list;
/** Length of the #cmd_list. */
unsigned int cmd_list_length;
/** Current mode. */
gboolean file_complete;
uint32_t selected_line;
char *old_input;
Mode *completer;
char *old_completer_input;
/** fallback icon */
uint32_t fallback_icon_fetch_uid;
cairo_surface_t *fallback_icon;
} RunModePrivateData;
/**
@ -95,7 +115,7 @@ static gboolean exec_cmd ( const char *cmd, int run_in_term )
char *path = g_build_filename ( cache_dir, RUN_CACHE_FILE, NULL );
RofiHelperExecuteContext context = { .name = NULL };
// FIXME: assume startup notification support for terminals
if ( helper_execute_command ( NULL, lf_cmd, run_in_term, run_in_term ? &context : NULL ) ) {
if ( helper_execute_command ( NULL, lf_cmd, run_in_term, run_in_term ? &context : NULL ) ) {
/**
* This happens in non-critical time (After launching app)
* It is allowed to be a bit slower.
@ -119,11 +139,11 @@ static gboolean exec_cmd ( const char *cmd, int run_in_term )
*
* Remove command from history.
*/
static void delete_entry ( const char *cmd )
static void delete_entry ( const RunEntry *cmd )
{
char *path = g_build_filename ( cache_dir, RUN_CACHE_FILE, NULL );
history_remove ( path, cmd );
history_remove ( path, cmd->entry );
g_free ( path );
}
@ -139,25 +159,25 @@ static void delete_entry ( const char *cmd )
*/
static int sort_func ( const void *a, const void *b, G_GNUC_UNUSED void *data )
{
const char *astr = *( const char * const * ) a;
const char *bstr = *( const char * const * ) b;
const RunEntry *astr = ( const RunEntry * ) a;
const RunEntry *bstr = ( const RunEntry * ) b;
if ( astr == NULL && bstr == NULL ) {
if ( astr->entry == NULL && bstr->entry == NULL ) {
return 0;
}
else if ( astr == NULL ) {
else if ( astr->entry == NULL ) {
return 1;
}
else if ( bstr == NULL ) {
else if ( bstr->entry == NULL ) {
return -1;
}
return g_strcmp0 ( astr, bstr );
return g_strcmp0 ( astr->entry , bstr->entry );
}
/**
* External spider to get list of executables.
*/
static char ** get_apps_external ( char **retv, unsigned int *length, unsigned int num_favorites )
static RunEntry * get_apps_external ( RunEntry *retv, unsigned int *length, unsigned int num_favorites )
{
int fd = execute_generator ( config.run_list_command );
if ( fd >= 0 ) {
@ -176,7 +196,7 @@ static char ** get_apps_external ( char **retv, unsigned int *length, unsigned i
// This is a nice little penalty, but doable? time will tell.
// given num_favorites is max 25.
for ( unsigned int j = 0; found == 0 && j < num_favorites; j++ ) {
if ( strcasecmp ( buffer, retv[j] ) == 0 ) {
if ( strcasecmp ( buffer, retv[j].entry ) == 0 ) {
found = 1;
}
}
@ -186,8 +206,10 @@ static char ** get_apps_external ( char **retv, unsigned int *length, unsigned i
}
// No duplicate, add it.
retv = g_realloc ( retv, ( ( *length ) + 2 ) * sizeof ( char* ) );
retv[( *length )] = g_strdup ( buffer );
retv = g_realloc ( retv, ( ( *length ) + 2 ) * sizeof ( RunEntry ) );
retv[( *length )].entry = g_strdup ( buffer );
retv[( *length )].icon = NULL;
retv[( *length )].icon_fetch_uid = 0;
( *length )++;
}
@ -200,17 +222,19 @@ static char ** get_apps_external ( char **retv, unsigned int *length, unsigned i
}
}
}
retv[( *length ) ] = NULL;
retv[( *length ) ].entry = NULL;
retv[( *length ) ].icon = NULL;
retv[( *length ) ].icon_fetch_uid = 0;
return retv;
}
/**
* Internal spider used to get list of executables.
*/
static char ** get_apps ( unsigned int *length )
static RunEntry * get_apps ( unsigned int *length )
{
GError *error = NULL;
char **retv = NULL;
RunEntry *retv = NULL;
unsigned int num_favorites = 0;
char *path;
@ -219,7 +243,12 @@ static char ** get_apps ( unsigned int *length )
}
TICK_N ( "start" );
path = g_build_filename ( cache_dir, RUN_CACHE_FILE, NULL );
retv = history_get_list ( path, length );
char **hretv = history_get_list ( path, length );
retv = (RunEntry*)g_malloc0((*length+1)*sizeof(RunEntry));
for ( unsigned int i = 0; i < *length; i++ ) {
retv[i].entry = hretv[i];
}
g_free(hretv);
g_free ( path );
// Keep track of how many where loaded as favorite.
num_favorites = ( *length );
@ -227,9 +256,13 @@ static char ** get_apps ( unsigned int *length )
path = g_strdup ( g_getenv ( "PATH" ) );
gsize l = 0;
gchar *homedir = g_locale_to_utf8 ( g_get_home_dir (), -1, NULL, &l, &error );
gchar *homedir = g_locale_to_utf8 ( g_get_home_dir (), -1, NULL, &l, &error );
if ( error != NULL ) {
g_debug ( "Failed to convert homedir to UTF-8: %s", error->message );
for ( unsigned int i = 0; retv[i].entry != NULL ; i++ ) {
g_free ( retv[i].entry );
}
g_free(retv);
g_clear_error ( &error );
g_free ( homedir );
return NULL;
@ -285,7 +318,7 @@ static char ** get_apps ( unsigned int *length )
// given num_favorites is max 25.
int found = 0;
for ( unsigned int j = 0; found == 0 && j < num_favorites; j++ ) {
if ( g_strcmp0 ( name, retv[j] ) == 0 ) {
if ( g_strcmp0 ( name, retv[j].entry ) == 0 ) {
found = 1;
}
}
@ -295,9 +328,13 @@ static char ** get_apps ( unsigned int *length )
continue;
}
retv = g_realloc ( retv, ( ( *length ) + 2 ) * sizeof ( char* ) );
retv[( *length )] = name;
retv[( *length ) + 1] = NULL;
retv = g_realloc ( retv, ( ( *length ) + 2 ) * sizeof ( RunEntry ) );
retv[( *length )].entry = name;
retv[( *length )].icon = NULL;
retv[( *length )].icon_fetch_uid = 0;
retv[( *length ) + 1].entry = NULL;
retv[( *length ) + 1].icon = NULL;
retv[( *length ) + 1].icon_fetch_uid = 0;
( *length )++;
}
@ -316,21 +353,21 @@ static char ** get_apps ( unsigned int *length )
}
// TODO: check this is still fast enough. (takes 1ms on laptop.)
if ( ( *length ) > num_favorites ) {
g_qsort_with_data ( &retv[num_favorites], ( *length ) - num_favorites, sizeof ( char* ), sort_func, NULL );
g_qsort_with_data ( &(retv[num_favorites]), ( *length ) - num_favorites, sizeof ( RunEntry ), sort_func, NULL );
}
g_free ( path );
unsigned int removed = 0;
for ( unsigned int index = num_favorites; index < ( ( *length ) - 1 ); index++ ) {
if ( g_strcmp0 ( retv[index], retv[index + 1] ) == 0 ) {
g_free ( retv[index] );
retv[index] = NULL;
if ( g_strcmp0 ( retv[index].entry , retv[index + 1].entry ) == 0 ) {
g_free ( retv[index].entry );
retv[index].entry = NULL;
removed++;
}
}
if ( ( *length ) > num_favorites ) {
g_qsort_with_data ( &retv[num_favorites], ( *length ) - num_favorites, sizeof ( char* ),
g_qsort_with_data ( &(retv[num_favorites]), ( *length ) - num_favorites, sizeof ( RunEntry ),
sort_func,
NULL );
}
@ -347,6 +384,8 @@ static int run_mode_init ( Mode *sw )
RunModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) );
sw->private_data = (void *) pd;
pd->cmd_list = get_apps ( &( pd->cmd_list_length ) );
pd->completer = create_new_file_browser ();
mode_init ( pd->completer );
}
return TRUE;
@ -355,7 +394,16 @@ static void run_mode_destroy ( Mode *sw )
{
RunModePrivateData *rmpd = (RunModePrivateData *) sw->private_data;
if ( rmpd != NULL ) {
g_strfreev ( rmpd->cmd_list );
for ( unsigned int i = 0; i < rmpd->cmd_list_length; i++ ) {
g_free ( rmpd->cmd_list[i].entry );
if ( rmpd->cmd_list[i].icon != NULL ) {
cairo_surface_destroy ( rmpd->cmd_list[i].icon );
}
}
g_free ( rmpd->cmd_list );
g_free ( rmpd->old_input );
g_free ( rmpd->old_completer_input );
mode_destroy ( rmpd->completer );
g_free ( rmpd );
sw->private_data = NULL;
}
@ -364,6 +412,9 @@ static void run_mode_destroy ( Mode *sw )
static unsigned int run_mode_get_num_entries ( const Mode *sw )
{
const RunModePrivateData *rmpd = (const RunModePrivateData *) sw->private_data;
if ( rmpd->file_complete ) {
return rmpd->completer->_get_num_entries( rmpd->completer );
}
return rmpd->cmd_list_length;
}
@ -373,9 +424,43 @@ static ModeMode run_mode_result ( Mode *sw, int mretv, char **input, unsigned in
ModeMode retv = MODE_EXIT;
gboolean run_in_term = ( ( mretv & MENU_CUSTOM_ACTION ) == MENU_CUSTOM_ACTION );
if ( rmpd->file_complete == TRUE ) {
if ( ( mretv & MENU_OK ) && rmpd->cmd_list[selected_line] != NULL ) {
if ( !exec_cmd ( rmpd->cmd_list[selected_line], run_in_term ) ) {
retv = RELOAD_DIALOG;
if ( ( mretv& (MENU_COMPLETE)) ) {
g_free ( rmpd->old_completer_input );
rmpd->old_completer_input = *input;
*input = NULL;
if ( rmpd->selected_line < rmpd->cmd_list_length ) {
(*input) = g_strdup ( rmpd->old_input );
}
rmpd->file_complete = FALSE;
}
else if ( (mretv&MENU_CANCEL) ) {
retv = MODE_EXIT;
}
else {
char *path = NULL;
retv = file_browser_mode_completer ( rmpd->completer, mretv, input, selected_line, &path );
if ( retv == MODE_EXIT ) {
if ( path == NULL ) {
exec_cmd ( rmpd->cmd_list[rmpd->selected_line].entry, run_in_term );
}
else {
char *arg= g_strdup_printf ( "%s '%s'", rmpd->cmd_list[rmpd->selected_line].entry, path);
exec_cmd ( arg, run_in_term );
g_free(arg);
}
}
g_free (path);
}
return retv;
}
if ( ( mretv & MENU_OK ) && rmpd->cmd_list[selected_line].entry != NULL ) {
if ( !exec_cmd ( rmpd->cmd_list[selected_line].entry, run_in_term ) ) {
retv = RELOAD_DIALOG;
}
}
@ -384,27 +469,106 @@ static ModeMode run_mode_result ( Mode *sw, int mretv, char **input, unsigned in
retv = RELOAD_DIALOG;
}
}
else if ( ( mretv & MENU_ENTRY_DELETE ) && rmpd->cmd_list[selected_line] ) {
delete_entry ( rmpd->cmd_list[selected_line] );
else if ( ( mretv & MENU_ENTRY_DELETE ) && rmpd->cmd_list[selected_line].entry ) {
delete_entry ( &(rmpd->cmd_list[selected_line]) );
// Clear the list.
retv = RELOAD_DIALOG;
run_mode_destroy ( sw );
run_mode_init ( sw );
}
else if ( mretv & MENU_CUSTOM_COMMAND ) {
retv = ( mretv & MENU_LOWER_MASK );
}
else if ( ( mretv& MENU_COMPLETE) ) {
retv = RELOAD_DIALOG;
if ( selected_line < rmpd->cmd_list_length ) {
rmpd->selected_line = selected_line;
g_free ( rmpd->old_input );
rmpd->old_input = g_strdup ( *input );
if ( *input ) g_free (*input);
*input = g_strdup ( rmpd->old_completer_input );
rmpd->file_complete = TRUE;
}
}
return retv;
}
static char *_get_display_value ( const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **list, int get_entry )
{
const RunModePrivateData *rmpd = (const RunModePrivateData *) sw->private_data;
return get_entry ? g_strdup ( rmpd->cmd_list[selected_line] ) : NULL;
if ( rmpd->file_complete ) {
return rmpd->completer->_get_display_value (rmpd->completer, selected_line, state, list, get_entry );
}
return get_entry ? g_strdup ( rmpd->cmd_list[selected_line].entry ) : NULL;
}
static int run_token_match ( const Mode *sw, rofi_int_matcher **tokens, unsigned int index )
{
const RunModePrivateData *rmpd = (const RunModePrivateData *) sw->private_data;
return helper_token_match ( tokens, rmpd->cmd_list[index] );
if ( rmpd->file_complete ) {
return rmpd->completer->_token_match (rmpd->completer, tokens, index );
}
return helper_token_match ( tokens, rmpd->cmd_list[index].entry );
}
static char *run_get_message ( const Mode *sw )
{
RunModePrivateData *pd = sw->private_data;
if ( pd->file_complete ) {
if ( pd->selected_line < pd->cmd_list_length ) {
char *msg = mode_get_message ( pd->completer);
if ( msg ) {
char *retv = g_strdup_printf("File complete for: %s\n%s", pd->cmd_list[pd->selected_line].entry, msg);
g_free (msg);
return retv;
}
return g_strdup_printf("File complete for: %s", pd->cmd_list[pd->selected_line].entry);
}
}
return NULL;
}
static cairo_surface_t *fallback_icon ( RunModePrivateData *pd, int height )
{
if ( config.application_fallback_icon ) {
// FALLBACK
if ( pd->fallback_icon_fetch_uid > 0 ) {
return rofi_icon_fetcher_get ( pd->fallback_icon_fetch_uid );
}
pd->fallback_icon_fetch_uid = rofi_icon_fetcher_query ( config.application_fallback_icon, height );
}
return NULL;
}
static cairo_surface_t *_get_icon ( const Mode *sw, unsigned int selected_line, int height )
{
RunModePrivateData *pd = (RunModePrivateData *) mode_get_private_data ( sw );
if ( pd->file_complete ) {
return pd->completer->_get_icon ( pd->completer, selected_line, height );
}
g_return_val_if_fail ( pd->cmd_list != NULL, NULL );
RunEntry *dr = &( pd->cmd_list[selected_line] );
if ( dr->icon_fetch_uid > 0 ) {
cairo_surface_t *icon = rofi_icon_fetcher_get ( dr->icon_fetch_uid );
if ( icon ) {
return icon;
}
return fallback_icon ( pd, height );
}
/** lookup icon */
char ** str = g_strsplit(dr->entry, " ", 2);
if ( str ) {
dr->icon_fetch_uid = rofi_icon_fetcher_query ( str[0], height );
g_strfreev ( str );
cairo_surface_t *icon = rofi_icon_fetcher_get ( dr->icon_fetch_uid );
if ( icon ) {
return icon;
}
}
return fallback_icon ( pd, height );
}
#include "mode-private.h"
@ -417,8 +581,9 @@ Mode run_mode =
._result = run_mode_result,
._destroy = run_mode_destroy,
._token_match = run_token_match,
._get_message = run_get_message,
._get_display_value = _get_display_value,
._get_icon = NULL,
._get_icon = _get_icon,
._get_completion = NULL,
._preprocess_input = NULL,
.private_data = NULL,

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -71,12 +71,14 @@ typedef struct
char delim;
/** no custom */
gboolean no_custom;
gboolean use_hot_keys;
} ScriptModePrivateData;
/**
* Shared function between DMENU and Script mode.
*/
void dmenuscript_parse_entry_extras ( G_GNUC_UNUSED Mode *sw, DmenuScriptEntry *entry, char *buffer, size_t length )
void dmenuscript_parse_entry_extras ( G_GNUC_UNUSED Mode *sw, DmenuScriptEntry *entry, char *buffer, G_GNUC_UNUSED size_t length )
{
gchar **extras = g_strsplit ( buffer, "\x1f", -1 );
gchar **extra;
@ -143,6 +145,9 @@ static void parse_header_entry ( Mode *sw, char *line, ssize_t length )
else if ( strcasecmp ( line, "no-custom" ) == 0 ) {
pd->no_custom = ( strcasecmp ( value, "true" ) == 0 );
}
else if ( strcasecmp ( line, "use-hot-keys" ) == 0 ) {
pd->use_hot_keys = ( strcasecmp ( value, "true" ) == 0 );
}
}
}
@ -213,7 +218,7 @@ static DmenuScriptEntry *execute_executor ( Mode *sw, char *arg, unsigned int *l
retv[( *length )].info = NULL;
retv[( *length )].icon_fetch_uid = 0;
retv[( *length )].nonselectable = FALSE;
if ( buf_length > 0 && ( read_length > (ssize_t) buf_length ) ) {
if ( buf_length > 0 && ( read_length > (ssize_t) buf_length ) ) {
dmenuscript_parse_entry_extras ( sw, &( retv[( *length )] ), buffer + buf_length, read_length - buf_length );
}
retv[( *length ) + 1].entry = NULL;
@ -279,19 +284,24 @@ static ModeMode script_mode_result ( Mode *sw, int mretv, char **input, unsigned
unsigned int new_length = 0;
if ( ( mretv & MENU_CUSTOM_COMMAND ) ) {
//retv = 1+( mretv & MENU_LOWER_MASK );
script_mode_reset_highlight ( sw );
if ( selected_line != UINT32_MAX ) {
new_list = execute_executor ( sw, rmpd->cmd_list[selected_line].entry, &new_length, 10 + ( mretv & MENU_LOWER_MASK ), &( rmpd->cmd_list[selected_line] ) );
}
else {
if ( rmpd->no_custom == FALSE ) {
new_list = execute_executor ( sw, *input, &new_length, 10 + ( mretv & MENU_LOWER_MASK ), NULL );
if ( rmpd->use_hot_keys ) {
script_mode_reset_highlight ( sw );
if ( selected_line != UINT32_MAX ) {
new_list = execute_executor ( sw, rmpd->cmd_list[selected_line].entry, &new_length, 10 + ( mretv & MENU_LOWER_MASK ), &( rmpd->cmd_list[selected_line] ) );
}
else {
return RELOAD_DIALOG;
if ( rmpd->no_custom == FALSE ) {
new_list = execute_executor ( sw, *input, &new_length, 10 + ( mretv & MENU_LOWER_MASK ), NULL );
}
else {
return RELOAD_DIALOG;
}
}
}
else {
retv = ( mretv & MENU_LOWER_MASK );
return retv;
}
}
else if ( ( mretv & MENU_OK ) && rmpd->cmd_list[selected_line].entry != NULL ) {
if ( rmpd->cmd_list[selected_line].nonselectable ) {

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -173,7 +173,7 @@ static void delete_ssh ( const char *host )
* @param retv list of hosts
* @param length pointer to length of list [in][out]
*
* Read 'known_hosts' file when entries are not hashsed.
* Read 'known_hosts' file when entries are not hashed.
*
* @returns updated list of hosts.
*/
@ -198,14 +198,14 @@ static SshEntry *read_known_hosts_file ( const char *path, SshEntry * retv, unsi
}
// Find end of hostname set.
char *end = strstr ( start, " " );
if ( end == NULL ) {
if ( end == NULL ) {
// Something is wrong.
continue;
}
*end = '\0';
char *sep = start;
start = strsep ( &sep, ", " );
while ( start ) {
while ( start ) {
int port = 0;
if ( start[0] == '[' ) {
start++;
@ -215,7 +215,7 @@ static SshEntry *read_known_hosts_file ( const char *path, SshEntry * retv, unsi
errno = 0;
gchar *endptr = NULL;
gint64 number = g_ascii_strtoll ( &( end[2] ), &endptr, 10 );
if ( errno != 0 ) {
if ( errno != 0 ) {
g_warning ( "Failed to parse port number: %s.", &( end[2] ) );
}
else if ( endptr == &( end[2] ) ) {
@ -466,7 +466,7 @@ static void parse_ssh_config_file ( SSHModePrivateData *pd, const char *filename
*
* @returns an array of strings containing all the hosts.
*/
static SshEntry * get_ssh ( SSHModePrivateData *pd, unsigned int *length )
static SshEntry * get_ssh ( SSHModePrivateData *pd, unsigned int *length )
{
SshEntry *retv = NULL;
unsigned int num_favorites = 0;
@ -488,7 +488,7 @@ static SshEntry * get_ssh ( SSHModePrivateData *pd, unsigned int *length )
errno = 0;
gchar *endptr = NULL;
gint64 number = g_ascii_strtoll ( &( portstr[1] ), &endptr, 10 );
if ( errno != 0 ) {
if ( errno != 0 ) {
g_warning ( "Failed to parse port number: %s.", &( portstr[1] ) );
}
else if ( endptr == &( portstr[1] ) ) {
@ -607,6 +607,9 @@ static ModeMode ssh_mode_result ( Mode *sw, int mretv, char **input, unsigned in
ssh_mode_destroy ( sw );
ssh_mode_init ( sw );
}
else if ( mretv & MENU_CUSTOM_COMMAND ) {
retv = ( mretv & MENU_LOWER_MASK );
}
return retv;
}

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -58,6 +58,7 @@
#include "timings.h"
#include "rofi-icon-fetcher.h"
#include "mode-private.h"
#define WINLIST 32
@ -109,6 +110,7 @@ typedef struct
long hint_flags;
uint32_t wmdesktop;
char *wmdesktopstr;
unsigned int wmdesktopstr_len;
cairo_surface_t *icon;
gboolean icon_checked;
uint32_t icon_fetch_uid;
@ -180,20 +182,27 @@ static int winlist_append ( winlist *l, xcb_window_t w, client *d )
return l->len - 1;
}
static void client_free ( client *c )
{
if ( c == NULL ) {
return;
}
if ( c->icon ) {
cairo_surface_destroy ( c->icon );
}
g_free ( c->title );
g_free ( c->class );
g_free ( c->name );
g_free ( c->role );
g_free ( c->wmdesktopstr );
}
static void winlist_empty ( winlist *l )
{
while ( l->len > 0 ) {
client *c = l->data[--l->len];
if ( c != NULL ) {
if ( c->icon ) {
cairo_surface_destroy ( c->icon );
}
g_free ( c->title );
g_free ( c->class );
g_free ( c->name );
g_free ( c->role );
g_free ( c->wmdesktopstr );
g_free ( c );
client_free ( c );
g_free ( c );
}
}
}
@ -332,20 +341,24 @@ static client* window_client ( ModeModePrivateData *pd, xcb_window_t win )
xcb_ewmh_get_atoms_reply_wipe ( &states );
}
c->title = window_get_text_prop ( c->window, xcb->ewmh._NET_WM_NAME );
if ( c->title == NULL ) {
c->title = window_get_text_prop ( c->window, XCB_ATOM_WM_NAME );
char *tmp_title = window_get_text_prop ( c->window, xcb->ewmh._NET_WM_NAME );
if ( tmp_title == NULL ) {
tmp_title = window_get_text_prop ( c->window, XCB_ATOM_WM_NAME );
}
c->title = g_markup_escape_text ( tmp_title, -1 );
pd->title_len = MAX ( c->title ? g_utf8_strlen ( c->title, -1 ) : 0, pd->title_len );
g_free ( tmp_title );
c->role = window_get_text_prop ( c->window, netatoms[WM_WINDOW_ROLE] );
char *tmp_role = window_get_text_prop ( c->window, netatoms[WM_WINDOW_ROLE] );
c->role = g_markup_escape_text ( tmp_role ? tmp_role : "", -1 );
pd->role_len = MAX ( c->role ? g_utf8_strlen ( c->role, -1 ) : 0, pd->role_len );
g_free ( tmp_role );
cky = xcb_icccm_get_wm_class ( xcb->connection, c->window );
xcb_icccm_get_wm_class_reply_t wcr;
if ( xcb_icccm_get_wm_class_reply ( xcb->connection, cky, &wcr, NULL ) ) {
c->class = rofi_latin_to_utf8_strdup ( wcr.class_name, -1 );
c->name = rofi_latin_to_utf8_strdup ( wcr.instance_name, -1 );
c->class = g_markup_escape_text ( wcr.class_name, -1 );
c->name = g_markup_escape_text ( wcr.instance_name, -1 );
pd->name_len = MAX ( c->name ? g_utf8_strlen ( c->name, -1 ) : 0, pd->name_len );
xcb_icccm_get_wm_class_reply_wipe ( &wcr );
}
@ -454,7 +467,7 @@ static unsigned int window_mode_get_num_entries ( const Mode *sw )
* Is there a call for this?
*/
const char *invalid_desktop_name = "n/a";
static const char * _window_name_list_entry ( const char *str, uint32_t length, int entry )
static const char * _window_name_list_entry ( const char *str, uint32_t length, int entry )
{
uint32_t offset = 0;
int index = 0;
@ -491,14 +504,15 @@ static void _window_mode_load_data ( Mode *sw, unsigned int cd )
current_desktop = 0;
}
c = xcb_ewmh_get_client_list_stacking ( &xcb->ewmh, 0 );
g_debug ( "Get list from: %d", xcb->screen_nbr );
c = xcb_ewmh_get_client_list_stacking ( &xcb->ewmh, xcb->screen_nbr );
xcb_ewmh_get_windows_reply_t clients = { 0, };
if ( xcb_ewmh_get_client_list_stacking_reply ( &xcb->ewmh, c, &clients, NULL ) ) {
found = 1;
}
else {
c = xcb_ewmh_get_client_list ( &xcb->ewmh, xcb->screen_nbr );
if ( xcb_ewmh_get_client_list_reply ( &xcb->ewmh, c, &clients, NULL ) ) {
if ( xcb_ewmh_get_client_list_reply ( &xcb->ewmh, c, &clients, NULL ) ) {
found = 1;
}
}
@ -506,7 +520,7 @@ static void _window_mode_load_data ( Mode *sw, unsigned int cd )
return;
}
if ( clients.windows_len > 0 ) {
if ( clients.windows_len > 0 ) {
int i;
// windows we actually display. May be slightly different to _NET_CLIENT_LIST_STACKING
// if we happen to have a window destroyed while we're working...
@ -560,24 +574,30 @@ static void _window_mode_load_data ( Mode *sw, unsigned int cd )
char *output = NULL;
if ( pango_parse_markup ( _window_name_list_entry ( names.strings, names.strings_len,
c->wmdesktop ), -1, 0, NULL, &output, NULL, NULL ) ) {
c->wmdesktopstr = output;
c->wmdesktopstr = g_strdup ( _window_name_list_entry ( names.strings, names.strings_len, c->wmdesktop ) );
c->wmdesktopstr_len = g_utf8_strlen ( output, -1 );
pd->wmdn_len = MAX ( pd->wmdn_len, c->wmdesktopstr_len );
g_free ( output );
}
else {
c->wmdesktopstr = g_strdup ( "Invalid name" );
pd->wmdn_len = MAX ( pd->wmdn_len, g_utf8_strlen ( c->wmdesktopstr, -1 ) );
}
}
else {
c->wmdesktopstr = g_strdup ( _window_name_list_entry ( names.strings, names.strings_len, c->wmdesktop ) );
c->wmdesktopstr = g_markup_escape_text ( _window_name_list_entry ( names.strings, names.strings_len, c->wmdesktop ), -1 );
pd->wmdn_len = MAX ( pd->wmdn_len, g_utf8_strlen ( c->wmdesktopstr, -1 ) );
}
}
else {
c->wmdesktopstr = g_strdup_printf ( "%u", (uint32_t) c->wmdesktop );
pd->wmdn_len = MAX ( pd->wmdn_len, g_utf8_strlen ( c->wmdesktopstr, -1 ) );
}
}
else {
c->wmdesktopstr = g_strdup ( "" );
pd->wmdn_len = MAX ( pd->wmdn_len, g_utf8_strlen ( c->wmdesktopstr, -1 ) );
}
pd->wmdn_len = MAX ( pd->wmdn_len, g_utf8_strlen ( c->wmdesktopstr, -1 ) );
if ( cd && c->wmdesktop != current_desktop ) {
continue;
}
@ -633,7 +653,7 @@ static inline int act_on_window ( xcb_window_t window )
g_spawn_async ( NULL, args, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error );
if ( error != NULL ) {
char *msg = g_strdup_printf ( "Failed to execute action for window: '%s'\nError: '%s'", window_regex, error->message );
rofi_view_error_dialog ( msg, FALSE );
rofi_view_error_dialog ( msg, FALSE );
g_free ( msg );
// print error.
g_error_free ( error );
@ -655,6 +675,8 @@ static ModeMode window_mode_result ( Mode *sw, int mretv, G_GNUC_UNUSED char **i
act_on_window ( rmpd->ids->array[selected_line] );
}
else {
// Disable reverting input focus to previous window.
xcb->focus_revert = 0;
rofi_view_hide ();
if ( ( current_window_manager & WM_DO_NOT_CHANGE_CURRENT_DESKTOP ) == 0 ) {
// Get the desktop of the client to switch to
@ -696,6 +718,18 @@ static ModeMode window_mode_result ( Mode *sw, int mretv, G_GNUC_UNUSED char **i
else if ( ( mretv & ( MENU_ENTRY_DELETE ) ) == MENU_ENTRY_DELETE ) {
xcb_ewmh_request_close_window ( &( xcb->ewmh ), xcb->screen_nbr, rmpd->ids->array[selected_line], XCB_CURRENT_TIME, XCB_EWMH_CLIENT_SOURCE_TYPE_OTHER );
xcb_flush ( xcb->connection );
ThemeWidget *wid = rofi_config_find_widget ( sw->name, NULL, TRUE );
Property *p = rofi_theme_find_property ( wid, P_BOOLEAN, "close-on-delete", TRUE );
if ( p && p->type == P_BOOLEAN && p->value.b == FALSE ){
// Force a reload.
client_free ( rmpd->ids->data[selected_line] );
g_free ( rmpd->ids->data[selected_line] );
memmove(&(rmpd->ids->array[selected_line]), &(rmpd->ids->array[selected_line+1]), rmpd->ids->len-selected_line);
memmove(&(rmpd->ids->data[selected_line]), &(rmpd->ids->data[selected_line+1]), rmpd->ids->len-selected_line);
rmpd->ids->len--;
retv = RELOAD_DIALOG;
}
}
else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) {
GError *error = NULL;
@ -709,11 +743,14 @@ static ModeMode window_mode_result ( Mode *sw, int mretv, G_GNUC_UNUSED char **i
}
RofiHelperExecuteContext context = { .name = NULL };
if ( !helper_execute_command ( NULL, lf_cmd, run_in_term, run_in_term ? &context : NULL ) ) {
if ( !helper_execute_command ( NULL, lf_cmd, run_in_term, run_in_term ? &context : NULL ) ) {
retv = RELOAD_DIALOG;
}
g_free ( lf_cmd );
}
else if ( mretv & MENU_CUSTOM_COMMAND ) {
retv = ( mretv & MENU_LOWER_MASK );
}
return retv;
}
@ -735,12 +772,11 @@ struct arg
client *c;
};
static void helper_eval_add_str ( GString *str, const char *input, int l, int max_len )
static void helper_eval_add_str ( GString *str, const char *input, int l, int max_len, int nc )
{
// g_utf8 does not work with NULL string.
const char *input_nn = input ? input : "";
// Both l and max_len are in characters, not bytes.
int nc = g_utf8_strlen ( input_nn, -1 );
int spaces = 0;
if ( l == 0 ) {
spaces = MAX ( 0, max_len - nc );
@ -748,12 +784,16 @@ static void helper_eval_add_str ( GString *str, const char *input, int l, int ma
}
else {
if ( nc > l ) {
int bl = g_utf8_offset_to_pointer ( input_nn, l ) - input_nn;
g_string_append_len ( str, input_nn, bl );
int bl = g_utf8_offset_to_pointer ( input_nn, l ) - input_nn;
char *tmp = g_markup_escape_text ( input_nn, bl );
g_string_append ( str, tmp );
g_free ( tmp );
}
else {
spaces = l - nc;
g_string_append ( str, input_nn );
char *tmp = g_markup_escape_text ( input_nn, -1 );
g_string_append ( str, tmp );
g_free ( tmp );
}
}
while ( spaces-- ) {
@ -770,28 +810,26 @@ static gboolean helper_eval_cb ( const GMatchInfo *info, GString *str, gpointer
int l = 0;
if ( match[2] == ':' ) {
l = (int) g_ascii_strtoll ( &match[3], NULL, 10 );
if ( l < 0 && config.menu_width < 0 ) {
l = -config.menu_width + l;
}
if ( l < 0 ) {
l = 0;
}
}
if ( match[1] == 'w' ) {
helper_eval_add_str ( str, d->c->wmdesktopstr, l, d->pd->wmdn_len );
helper_eval_add_str ( str, d->c->wmdesktopstr, l, d->pd->wmdn_len, d->c->wmdesktopstr_len );
}
else if ( match[1] == 'c' ) {
helper_eval_add_str ( str, d->c->class, l, d->pd->clf_len );
helper_eval_add_str ( str, d->c->class, l, d->pd->clf_len, g_utf8_strlen ( d->c->class, -1 ) );
}
else if ( match[1] == 't' ) {
helper_eval_add_str ( str, d->c->title, l, d->pd->title_len );
helper_eval_add_str ( str, d->c->title, l, d->pd->title_len, g_utf8_strlen ( d->c->title, -1 ) );
}
else if ( match[1] == 'n' ) {
helper_eval_add_str ( str, d->c->name, l, d->pd->name_len );
helper_eval_add_str ( str, d->c->name, l, d->pd->name_len, g_utf8_strlen ( d->c->name, -1 ) );
}
else if ( match[1] == 'r' ) {
helper_eval_add_str ( str, d->c->role, l, d->pd->role_len );
helper_eval_add_str ( str, d->c->role, l, d->pd->role_len, g_utf8_strlen ( d->c->role, -1 ) );
}
g_free ( match );
}
return FALSE;
@ -817,6 +855,7 @@ static char *_get_display_value ( const Mode *sw, unsigned int selected_line, in
if ( c->active ) {
*state |= ACTIVE;
}
*state |= MARKUP;
return get_entry ? _generate_display_string ( rmpd, c ) : NULL;
}

View file

@ -22,6 +22,16 @@ monitor_active ( workarea *mon )
return proxy->monitor_active ( mon );
}
void display_set_input_focus ( guint w )
{
proxy->set_input_focus(w);
}
void display_revert_input_focus ()
{
proxy->revert_input_focus();
}
gboolean
display_setup ( GMainLoop *main_loop, NkBindings *bindings )
{

View file

@ -3,7 +3,7 @@
*
* MIT/X11 License
* Copyright © 2012 Sean Pringle <sean.pringle@gmail.com>
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -66,9 +66,9 @@ const char *const monitor_position_entries[] = {
"on monitor that has mouse pointer"
};
/** copy of the argc for use in commandline argument parser. */
static int stored_argc = 0;
int stored_argc = 0;
/** copy of the argv pointer for use in the commandline argument parser */
static char **stored_argv = NULL;
char **stored_argv = NULL;
char *helper_string_replace_if_exists_v ( char * string, GHashTable *h );
@ -179,6 +179,14 @@ static gchar *fuzzy_to_regex ( const char * input )
return retv;
}
static gchar *prefix_regex ( const char * input )
{
gchar *r = g_regex_escape_string ( input, -1 );
char *retv = g_strconcat ( "\\b", r, NULL );
g_free ( r );
return retv;
}
static char *utf8_helper_simplify_string ( const char *s )
{
gunichar buf2[G_UNICHAR_MAX_DECOMPOSITION_LENGTH] = { 0, };
@ -204,7 +212,7 @@ static char *utf8_helper_simplify_string ( const char *s )
}
// Macro for quickly generating regex for matching.
static inline GRegex * R ( const char *s, int case_sensitive )
static inline GRegex * R ( const char *s, int case_sensitive )
{
if ( config.normalize_match ) {
char *str = utf8_helper_simplify_string ( s );
@ -248,6 +256,11 @@ static rofi_int_matcher * create_regex ( const char *input, int case_sensitive )
retv = R ( r, case_sensitive );
g_free ( r );
break;
case MM_PREFIX:
r = prefix_regex ( input );
retv = R ( r, case_sensitive );
g_free ( r );
break;
default:
r = g_regex_escape_string ( input, -1 );
retv = R ( r, case_sensitive );
@ -322,7 +335,7 @@ const char ** find_arg_strv ( const char *const key )
const char **retv = NULL;
int length = 0;
for ( int i = 0; i < stored_argc; i++ ) {
if ( i < ( stored_argc - 1 ) && strcasecmp ( stored_argv[i], key ) == 0 ) {
if ( i < ( stored_argc - 1 ) && strcasecmp ( stored_argv[i], key ) == 0 ) {
length++;
}
}
@ -632,30 +645,22 @@ int config_sanity_check ( void )
else if ( g_strcmp0 ( config.matching, "normal" ) == 0 ) {
config.matching_method = MM_NORMAL;;
}
else if ( g_strcmp0 ( config.matching, "prefix" ) == 0 ) {
config.matching_method = MM_PREFIX;
}
else {
g_string_append_printf ( msg, "\t<b>config.matching</b>=%s is not a valid matching strategy.\nValid options are: glob, regex, fuzzy or normal.\n",
g_string_append_printf ( msg, "\t<b>config.matching</b>=%s is not a valid matching strategy.\nValid options are: glob, regex, fuzzy, prefix or normal.\n",
config.matching );
found_error = 1;
}
}
if ( config.element_height < 1 ) {
g_string_append_printf ( msg, "\t<b>config.element_height</b>=%d is invalid. An element needs to be atleast 1 line high.\n",
g_string_append_printf ( msg, "\t<b>config.element_height</b>=%d is invalid. An element needs to be at least 1 line high.\n",
config.element_height );
config.element_height = 1;
found_error = TRUE;
}
if ( config.menu_columns == 0 ) {
g_string_append_printf ( msg, "\t<b>config.menu_columns</b>=%d is invalid. You need at least one visible column.\n",
config.menu_columns );
config.menu_columns = 1;
found_error = TRUE;
}
if ( config.menu_width == 0 ) {
g_string_append_printf ( msg, "<b>config.menu_width</b>=0 is invalid. You cannot have a window with no width." );
config.menu_columns = 50;
found_error = TRUE;
}
if ( !( config.location >= 0 && config.location <= 8 ) ) {
g_string_append_printf ( msg, "\t<b>config.location</b>=%d is invalid. Value should be between %d and %d.\n",
config.location, 0, 8 );
@ -694,8 +699,7 @@ int config_sanity_check ( void )
if ( g_strcmp0 ( config.monitor, "-3" ) == 0 ) {
// On -3, set to location 1.
config.location = 1;
config.fullscreen = 0;
config.location = 1;
}
if ( found_error ) {
@ -903,33 +907,6 @@ static int rofi_scorer_get_score_for ( enum CharClass prev, enum CharClass curr
return 0;
}
/**
* @param pattern The user input to match against.
* @param plen Pattern length.
* @param str The input to match against pattern.
* @param slen Length of str.
*
* rofi_scorer_fuzzy_evaluate implements a global sequence alignment algorithm to find the maximum accumulated score by
* aligning `pattern` to `str`. It applies when `pattern` is a subsequence of `str`.
*
* Scoring criteria
* - Prefer matches at the start of a word, or the start of subwords in CamelCase/camelCase/camel123 words. See WORD_START_SCORE/CAMEL_SCORE.
* - Non-word characters matter. See NON_WORD_SCORE.
* - The first characters of words of `pattern` receive bonus because they usually have more significance than the rest.
* See PATTERN_START_MULTIPLIER/PATTERN_NON_START_MULTIPLIER.
* - Superfluous characters in `str` will reduce the score (gap penalty). See GAP_SCORE.
* - Prefer early occurrence of the first character. See LEADING_GAP_SCORE/GAP_SCORE.
*
* The recurrence of the dynamic programming:
* dp[i][j]: maximum accumulated score by aligning pattern[0..i] to str[0..j]
* dp[0][j] = leading_gap_penalty(0, j) + score[j]
* dp[i][j] = max(dp[i-1][j-1] + CONSECUTIVE_SCORE, max(dp[i-1][k] + gap_penalty(k+1, j) + score[j] : k < j))
*
* The first dimension can be suppressed since we do not need a matching scheme, which reduces the space complexity from
* O(N*M) to O(M)
*
* @returns the sorting weight.
*/
int rofi_scorer_fuzzy_evaluate ( const char *pattern, glong plen, const char *str, glong slen )
{
if ( slen > FUZZY_SCORER_MAX_LENGTH ) {
@ -1027,7 +1004,7 @@ gboolean helper_execute ( const char *wd, char **args, const char *error_precmd,
g_spawn_async ( wd, args, NULL, G_SPAWN_SEARCH_PATH, child_setup, user_data, NULL, &error );
if ( error != NULL ) {
char *msg = g_strdup_printf ( "Failed to execute: '%s%s'\nError: '%s'", error_precmd, error_cmd, error->message );
rofi_view_error_dialog ( msg, FALSE );
rofi_view_error_dialog ( msg, FALSE );
g_free ( msg );
// print error.
g_error_free ( error );
@ -1077,7 +1054,7 @@ gboolean helper_execute_command ( const char *wd, const char *cmd, gboolean run_
return helper_execute ( wd, args, "", cmd, context );
}
char *helper_get_theme_path ( const char *file )
char *helper_get_theme_path ( const char *file, const char *ext )
{
char *filename = rofi_expand_path ( file );
g_debug ( "Opening theme, testing: %s\n", filename );
@ -1086,11 +1063,11 @@ char *helper_get_theme_path ( const char *file )
}
g_free ( filename );
if ( g_str_has_suffix ( file, ".rasi" ) ) {
if ( g_str_has_suffix ( file, ext ) ) {
filename = g_strdup ( file );
}
else {
filename = g_strconcat ( file, ".rasi", NULL );
filename = g_strconcat ( file, ext, NULL );
}
// Check config's themes directory.
const char *cpath = g_get_user_config_dir ();
@ -1138,18 +1115,22 @@ char *helper_get_theme_path ( const char *file )
return filename;
}
static void parse_pair ( char *input, rofi_range_pair *item )
static gboolean parse_pair ( char *input, rofi_range_pair *item )
{
// Skip leading blanks.
while ( input != NULL && isblank ( *input ) ) {
++input;
}
if ( input == NULL ) {
return FALSE;
}
const char *sep[] = { "-", ":" };
int pythonic = ( strchr ( input, ':' ) || input[0] == '-' ) ? 1 : 0;
int index = 0;
for ( char *token = strsep ( &input, sep[pythonic] ); token != NULL; token = strsep ( &input, sep[pythonic] ) ) {
for ( char *token = strsep ( &input, sep[pythonic] ); token != NULL; token = strsep ( &input, sep[pythonic] ) ) {
if ( index == 0 ) {
item->start = item->stop = (int) strtol ( token, NULL, 10 );
index++;
@ -1166,6 +1147,7 @@ static void parse_pair ( char *input, rofi_range_pair *item )
--item->stop;
}
}
return TRUE;
}
void parse_ranges ( char *input, rofi_range_pair **list, unsigned int *length )
{
@ -1178,29 +1160,11 @@ void parse_ranges ( char *input, rofi_range_pair **list, unsigned int *length )
// Make space.
*list = g_realloc ( ( *list ), ( ( *length ) + 1 ) * sizeof ( struct rofi_range_pair ) );
// Parse a single pair.
parse_pair ( token, &( ( *list )[*length] ) );
( *length )++;
if ( parse_pair ( token, &( ( *list )[*length] ) ) ) {
( *length )++;
}
}
}
/**
* @param format The format string used. See below for possible syntax.
* @param string The selected entry.
* @param selected_line The selected line index.
* @param filter The entered filter.
*
* Function that outputs the selected line in the user-specified format.
* Currently the following formats are supported:
* * i: Print the index (0-(N-1))
* * d: Print the index (1-N)
* * s: Print input string.
* * q: Print quoted input string.
* * f: Print the entered filter.
* * F: Print the entered filter, quoted
*
* This functions outputs the formatted string to stdout, appends a newline (\n) character and
* calls flush on the file descriptor.
*/
void rofi_output_formatted_line ( const char *format, const char *string, int selected_line, const char *filter )
{
for ( int i = 0; format && format[i]; i++ ) {
@ -1335,7 +1299,7 @@ char *helper_string_replace_if_exists_v ( char * string, GHashTable *h )
char *res = NULL;
// Replace hits within {-\w+}.
GRegex *reg = g_regex_new ( "\\[(.*)({[-\\w]+})(.*)\\]|({[\\w-]+})", 0, 0, &error );
GRegex *reg = g_regex_new ( "\\[(.*)({[-\\w]+})(.*)\\]|({[\\w-]+})", G_REGEX_UNGREEDY, 0, &error );
if ( error == NULL ) {
res = g_regex_replace_eval ( reg, string, -1, 0, 0, helper_eval_cb2, h, &error );
}

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -168,7 +168,7 @@ static _element ** __history_get_element_list ( FILE *fd, unsigned int *length )
( *length )++;
}
if ( buffer != NULL ) {
if ( buffer != NULL ) {
free ( buffer );
buffer = NULL;
}

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -62,10 +62,12 @@ ActionBindingEntry rofi_bindings[] =
{ .id = REMOVE_TO_SOL, .name = "kb-remove-to-sol", .binding = "Control+u", .comment = "Delete till the start of line" },
{ .id = ACCEPT_ENTRY, .name = "kb-accept-entry", .binding = "Control+j,Control+m,Return,KP_Enter", .comment = "Accept entry" },
{ .id = ACCEPT_CUSTOM, .name = "kb-accept-custom", .binding = "Control+Return", .comment = "Use entered text as command (in ssh/run modi)" },
{ .id = ACCEPT_CUSTOM_ALT, .name = "kb-accept-custom-alt", .binding = "Control+Shift+Return", .comment = "Use entered text as command (in ssh/run modi)" },
{ .id = ACCEPT_ALT, .name = "kb-accept-alt", .binding = "Shift+Return", .comment = "Use alternate accept command." },
{ .id = DELETE_ENTRY, .name = "kb-delete-entry", .binding = "Shift+Delete", .comment = "Delete entry from history" },
{ .id = MODE_NEXT, .name = "kb-mode-next", .binding = "Shift+Right,Control+Tab", .comment = "Switch to the next mode." },
{ .id = MODE_PREVIOUS, .name = "kb-mode-previous", .binding = "Shift+Left,Control+ISO_Left_Tab", .comment = "Switch to the previous mode." },
{ .id = MODE_COMPLETE, .name = "kb-mode-complete", .binding = "Control+l", .comment = "Start completion for mode." },
{ .id = ROW_LEFT, .name = "kb-row-left", .binding = "Control+Page_Up", .comment = "Go to the previous column" },
{ .id = ROW_RIGHT, .name = "kb-row-right", .binding = "Control+Page_Down", .comment = "Go to the next column" },
{ .id = ROW_UP, .name = "kb-row-up", .binding = "Up,Control+p,ISO_Left_Tab", .comment = "Select previous entry" },
@ -145,6 +147,18 @@ static gboolean binding_trigger_action ( guint64 scope, G_GNUC_UNUSED gpointer t
return rofi_view_trigger_action ( rofi_view_get_active (), scope, GPOINTER_TO_UINT ( user_data ) );
}
guint key_binding_get_action_from_name ( const char *name )
{
for ( gsize i = 0; i < G_N_ELEMENTS ( rofi_bindings ); ++i ) {
ActionBindingEntry *b = &rofi_bindings[i];
if ( g_strcmp0(b->name, name) == 0 ) {
return b->id;
}
}
return UINT32_MAX;
}
gboolean parse_keys_abe ( NkBindings *bindings )
{
GError *error = NULL;

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -153,8 +153,17 @@ void mode_set_private_data ( Mode *mode, void *pd )
const char *mode_get_display_name ( const Mode *mode )
{
if ( mode->display_name != NULL ) {
return mode->display_name;
/** Find the widget */
ThemeWidget *wid = rofi_config_find_widget ( mode->name, NULL, TRUE );
if ( wid ) {
/** Check string property */
Property *p = rofi_theme_find_property ( wid, P_STRING, "display-name", TRUE );
if ( p != NULL && p->type == P_STRING ) {
return p->value.s;
}
}
if ( mode->display_name != NULL ) {
return mode->display_name;
}
return mode->name;
}

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -46,6 +46,7 @@
#include <stdint.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "helper.h"
typedef struct
{
@ -77,7 +78,8 @@ typedef struct
unsigned int *acount;
uint32_t uid;
int size;
int wsize;
int hsize;
cairo_surface_t *surface;
IconFetcherNameEntry *entry;
@ -140,6 +142,11 @@ void rofi_icon_fetcher_init ( void )
g_slist_free ( l );
}
static void free_wrapper ( gpointer data, G_GNUC_UNUSED gpointer user_data )
{
g_free ( data ) ;
}
void rofi_icon_fetcher_destroy ( void )
{
if ( rofi_icon_fetcher_data == NULL ) {
@ -151,7 +158,7 @@ void rofi_icon_fetcher_destroy ( void )
g_hash_table_unref ( rofi_icon_fetcher_data->icon_cache_uid );
g_hash_table_unref ( rofi_icon_fetcher_data->icon_cache );
g_list_foreach ( rofi_icon_fetcher_data->supported_extensions, (GFunc) g_free, NULL );
g_list_foreach ( rofi_icon_fetcher_data->supported_extensions, free_wrapper, NULL );
g_list_free ( rofi_icon_fetcher_data->supported_extensions );
g_free ( rofi_icon_fetcher_data );
}
@ -163,14 +170,22 @@ void rofi_icon_fetcher_destroy ( void )
* Copyright (C) 2011-2018 Red Hat, Inc.
*/
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
/** Location of red byte */
#define RED_BYTE 2
/** Location of green byte */
#define GREEN_BYTE 1
/** Location of blue byte */
#define BLUE_BYTE 0
/** Location of alpha byte */
#define ALPHA_BYTE 3
#else
/** Location of red byte */
#define RED_BYTE 1
/** Location of green byte */
#define GREEN_BYTE 2
/** Location of blue byte */
#define BLUE_BYTE 3
/** Location of alpha byte */
#define ALPHA_BYTE 0
#endif
@ -212,8 +227,8 @@ static cairo_surface_t * rofi_icon_fetcher_get_surface_from_pixbuf ( GdkPixbuf
gint cstride;
guint lo, o;
guchar a = 0xff;
const guchar *pixels_end, *line, *line_end;
guchar *cpixels, *cline;
const guchar *pixels_end, *line;
guchar *cpixels;
pixels_end = pixels + height * stride;
o = alpha ? 4 : 3;
@ -225,9 +240,9 @@ static cairo_surface_t * rofi_icon_fetcher_get_surface_from_pixbuf ( GdkPixbuf
cairo_surface_flush ( surface );
while ( pixels < pixels_end ) {
line = pixels;
line_end = line + lo;
cline = cpixels;
line = pixels;
const guchar *line_end = line + lo;
guchar *cline = cpixels;
while ( line < line_end ) {
if ( alpha ) {
@ -257,7 +272,7 @@ gboolean rofi_icon_fetcher_file_is_image ( const char * const path )
return FALSE;
}
const char *suf = strrchr ( path, '.' );
if ( suf == NULL ) {
if ( suf == NULL ) {
return FALSE;
}
suf++;
@ -288,24 +303,32 @@ static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpoint
icon_path = sentry->entry->name;
}
else {
icon_path = icon_path_ = nk_xdg_theme_get_icon ( rofi_icon_fetcher_data->xdg_context, themes, NULL, sentry->entry->name, sentry->size, 1, TRUE );
icon_path = icon_path_ = nk_xdg_theme_get_icon ( rofi_icon_fetcher_data->xdg_context, themes, NULL, sentry->entry->name, MIN(sentry->wsize,sentry->hsize), 1, TRUE );
if ( icon_path_ == NULL ) {
g_debug ( "failed to get icon %s(%d): n/a", sentry->entry->name, sentry->size );
return;
g_debug ( "failed to get icon %s(%dx%d): n/a", sentry->entry->name, sentry->wsize, sentry->hsize );
const char *ext = g_strrstr(sentry->entry->name, ".");
if ( ext ) {
printf("%s %s\r\n", sentry->entry->name, ext);
icon_path = helper_get_theme_path ( sentry->entry->name, ext );
}
if ( icon_path == NULL ) {
return;
}
}
else{
g_debug ( "found icon %s(%d): %s", sentry->entry->name, sentry->size, icon_path );
g_debug ( "found icon %s(%dx%d): %s", sentry->entry->name, sentry->wsize, sentry->hsize, icon_path );
}
}
cairo_surface_t *icon_surf = NULL;
const char *suf = strrchr ( icon_path, '.' );
if ( suf == NULL ) {
if ( suf == NULL ) {
return;
}
GError *error = NULL;
GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_scale ( icon_path, sentry->size, sentry->size, TRUE, &error );
GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_scale ( icon_path, sentry->wsize, sentry->hsize, TRUE, &error );
if ( error != NULL ) {
g_warning ( "Failed to load image: %s", error->message );
g_error_free ( error );
@ -323,6 +346,40 @@ static void rofi_icon_fetcher_worker ( thread_state *sdata, G_GNUC_UNUSED gpoint
rofi_view_reload ();
}
uint32_t rofi_icon_fetcher_query_advanced ( const char *name, const int wsize, const int hsize )
{
g_debug ( "Query: %s(%dx%d)", name, wsize, hsize );
IconFetcherNameEntry *entry = g_hash_table_lookup ( rofi_icon_fetcher_data->icon_cache, name );
if ( entry == NULL ) {
entry = g_new0 ( IconFetcherNameEntry, 1 );
entry->name = g_strdup ( name );
g_hash_table_insert ( rofi_icon_fetcher_data->icon_cache, entry->name, entry );
}
IconFetcherEntry *sentry;
for ( GList *iter = g_list_first ( entry->sizes ); iter; iter = g_list_next ( iter ) ) {
sentry = iter->data;
if ( sentry->wsize == wsize && sentry->hsize == hsize ) {
return sentry->uid;
}
}
// Not found.
sentry = g_new0 ( IconFetcherEntry, 1 );
sentry->uid = ++( rofi_icon_fetcher_data->last_uid );
sentry->wsize = wsize;
sentry->hsize = hsize;
sentry->entry = entry;
sentry->surface = NULL;
entry->sizes = g_list_prepend ( entry->sizes, sentry );
g_hash_table_insert ( rofi_icon_fetcher_data->icon_cache_uid, GINT_TO_POINTER ( sentry->uid ), sentry );
// Push into fetching queue.
sentry->state.callback = rofi_icon_fetcher_worker;
g_thread_pool_push ( tpool, sentry, NULL );
return sentry->uid;
}
uint32_t rofi_icon_fetcher_query ( const char *name, const int size )
{
g_debug ( "Query: %s(%d)", name, size );
@ -335,7 +392,7 @@ uint32_t rofi_icon_fetcher_query ( const char *name, const int size )
IconFetcherEntry *sentry;
for ( GList *iter = g_list_first ( entry->sizes ); iter; iter = g_list_next ( iter ) ) {
sentry = iter->data;
if ( sentry->size == size ) {
if ( sentry->wsize == size && sentry->hsize == size ) {
return sentry->uid;
}
}
@ -343,7 +400,8 @@ uint32_t rofi_icon_fetcher_query ( const char *name, const int size )
// Not found.
sentry = g_new0 ( IconFetcherEntry, 1 );
sentry->uid = ++( rofi_icon_fetcher_data->last_uid );
sentry->size = size;
sentry->wsize = size;
sentry->hsize = size;
sentry->entry = entry;
sentry->surface = NULL;

View file

@ -16,6 +16,8 @@ const char * const PropertyTypeName[P_NUM_TYPES] = {
"Boolean",
/** Color */
"Color",
/** Image */
"Image",
/** Padding */
"Padding",
/** Link to global setting */
@ -28,6 +30,8 @@ const char * const PropertyTypeName[P_NUM_TYPES] = {
"List",
/** Orientation */
"Orientation",
/** Cursor */
"Cursor",
/** Inherit */
"Inherit",
};

View file

@ -3,7 +3,7 @@
*
* MIT/X11 License
* Copyright © 2012 Sean Pringle <sean.pringle@gmail.com>
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -91,13 +91,23 @@ void rofi_add_error_message ( GString *str )
{
list_of_error_msgs = g_list_append ( list_of_error_msgs, str );
}
void rofi_clear_error_messages ( void )
{
if ( list_of_error_msgs ) {
for ( GList *iter = g_list_first ( list_of_error_msgs );
iter != NULL; iter = g_list_next ( iter ) ) {
g_string_free ( (GString *) iter->data, TRUE );
}
g_list_free ( list_of_error_msgs );
list_of_error_msgs = NULL;
}
}
/** Path to the configuration file */
G_MODULE_EXPORT char *config_path = NULL;
/** Path to the configuration file in the new format */
G_MODULE_EXPORT char *config_path_new = NULL;
/** Array holding all activated modi. */
Mode **modi = NULL;
Mode **modi = NULL;
/** List of (possibly uninitialized) modi's */
Mode ** available_modi = NULL;
@ -115,11 +125,9 @@ NkBindings *bindings = NULL;
GMainLoop *main_loop = NULL;
/** Flag indicating we are in dmenu mode. */
static int dmenu_mode = FALSE;
static int dmenu_mode = FALSE;
/** Rofi's return code */
int return_code = EXIT_SUCCESS;
static gboolean old_config_format = FALSE;
int return_code = EXIT_SUCCESS;
void process_result ( RofiViewState *state );
@ -195,14 +203,14 @@ static void run_switcher ( ModeMode mode )
// User can pre-select a row.
if ( find_arg ( "-selected-row" ) >= 0 ) {
unsigned int sr = 0;
find_arg_uint ( "-selected-row", &( sr ) );
find_arg_uint ( "-selected-row", &( sr ) );
rofi_view_set_selected_line ( state, sr );
}
if ( state ) {
rofi_view_set_active ( state );
}
if ( rofi_view_get_active () == NULL ) {
g_main_loop_quit ( main_loop );
g_main_loop_quit ( main_loop );
}
}
void process_result ( RofiViewState *state )
@ -214,6 +222,16 @@ void process_result ( RofiViewState *state )
MenuReturn mretv = rofi_view_get_return_value ( state );
char *input = g_strdup ( rofi_view_get_user_input ( state ) );
ModeMode retv = mode_result ( sw, mretv, &input, selected_line );
{
if ( state->text ) {
if ( input == NULL ) {
textbox_text ( state->text, "" );
} else if ( strcmp ( rofi_view_get_user_input ( state ), input ) != 0 ) {
textbox_text ( state->text, input );
textbox_cursor_end ( state->text );
}
}
}
g_free ( input );
ModeMode mode = curr_switcher;
@ -285,11 +303,10 @@ static void print_list_of_modi ( int is_term )
static void print_main_application_options ( int is_term )
{
print_help_msg ( "-no-config", "", "Do not load configuration, use default values.", NULL, is_term );
print_help_msg ( "-v,-version", "", "Print the version number and exit.", NULL, is_term );
print_help_msg ( "-v,-version", "", "Print the version number and exit.", NULL, is_term );
print_help_msg ( "-dmenu", "", "Start in dmenu mode.", NULL, is_term );
print_help_msg ( "-display", "[string]", "X server to contact.", "${DISPLAY}", is_term );
print_help_msg ( "-h,-help", "", "This help message.", NULL, is_term );
print_help_msg ( "-dump-xresources", "", "Dump the current configuration in Xresources format and exit.", NULL, is_term );
print_help_msg ( "-e", "[string]", "Show a dialog displaying the passed message and exit.", NULL, is_term );
print_help_msg ( "-markup", "", "Enable pango markup where possible.", NULL, is_term );
print_help_msg ( "-normal-window", "", "Behave as a normal window. (experimental)", NULL, is_term );
@ -298,7 +315,6 @@ static void print_main_application_options ( int is_term )
print_help_msg ( "-no-plugins", "", "Disable loading of external plugins.", NULL, is_term );
print_help_msg ( "-plugin-path", "", "Directory used to search for rofi plugins. *DEPRECATED*", NULL, is_term );
print_help_msg ( "-dump-config", "", "Dump the current configuration in rasi format and exit.", NULL, is_term );
print_help_msg ( "-upgrade-config", "", "Upgrade the old-style configuration file in the new rasi format and exit.", NULL, is_term );
print_help_msg ( "-dump-theme", "", "Dump the current theme in rasi format and exit.", NULL, is_term );
}
static void help ( G_GNUC_UNUSED int argc, char **argv )
@ -348,12 +364,9 @@ static void help ( G_GNUC_UNUSED int argc, char **argv )
#endif
printf ( " Bugreports: %s"PACKAGE_BUGREPORT "%s\n", is_term ? color_bold : "", is_term ? color_reset : "" );
printf ( " Support: %s"PACKAGE_URL "%s\n", is_term ? color_bold : "", is_term ? color_reset : "" );
printf ( " %s#rofi @ freenode.net%s\n", is_term ? color_bold : "", is_term ? color_reset : "" );
printf ( " %s#rofi @ libera.chat%s\n", is_term ? color_bold : "", is_term ? color_reset : "" );
if ( find_arg ( "-no-config" ) < 0 ) {
if ( config_path_new ) {
printf ( " Configuration file: %s%s%s\n", is_term ? color_bold : "", config_path_new, is_term ? color_reset : "" );
}
else {
if ( config_path ) {
printf ( " Configuration file: %s%s%s\n", is_term ? color_bold : "", config_path, is_term ? color_reset : "" );
}
}
@ -440,7 +453,7 @@ static void cleanup ()
mode_destroy ( modi[i] );
}
rofi_view_workers_finalize ();
if ( main_loop != NULL ) {
if ( main_loop != NULL ) {
g_main_loop_unref ( main_loop );
main_loop = NULL;
}
@ -454,15 +467,8 @@ static void cleanup ()
g_free ( modi );
g_free ( config_path );
g_free ( config_path_new );
if ( list_of_error_msgs ) {
for ( GList *iter = g_list_first ( list_of_error_msgs );
iter != NULL; iter = g_list_next ( iter ) ) {
g_string_free ( (GString *) iter->data, TRUE );
}
g_list_free ( list_of_error_msgs );
}
rofi_clear_error_messages();
if ( rofi_theme ) {
rofi_theme_free ( rofi_theme );
@ -471,17 +477,17 @@ static void cleanup ()
TIMINGS_STOP ();
rofi_collect_modi_destroy ( );
rofi_icon_fetcher_destroy ( );
if ( rofi_configuration ) {
rofi_theme_free ( rofi_configuration );
rofi_configuration = NULL;
}
}
/**
* Collected modi
*/
/**
* @param name Search for mode with this name.
*
* @return returns Mode * when found, NULL if not.
*/
Mode * rofi_collect_modi_search ( const char *name )
{
for ( unsigned int i = 0; i < num_available_modi; i++ ) {
@ -636,6 +642,7 @@ static int add_mode ( const char * token )
if ( sw != NULL ) {
// Add to available list, so combi can find it.
rofi_collect_modi_add ( sw );
mode_set_config ( sw );
modi[num_modi] = sw;
num_modi++;
}
@ -728,12 +735,12 @@ static gboolean startup ( G_GNUC_UNUSED gpointer data )
g_main_loop_quit ( main_loop );
}
}
else if ( find_arg_str ( "-e", &( msg ) ) ) {
else if ( find_arg_str ( "-e", &( msg ) ) ) {
int markup = FALSE;
if ( find_arg ( "-markup" ) >= 0 ) {
markup = TRUE;
}
if ( !rofi_view_error_dialog ( msg, markup ) ) {
if ( !rofi_view_error_dialog ( msg, markup ) ) {
g_main_loop_quit ( main_loop );
}
}
@ -789,7 +796,7 @@ int main ( int argc, char *argv[] )
cmd_set_arguments ( argc, argv );
// Version
if ( find_arg ( "-v" ) >= 0 || find_arg ( "-version" ) >= 0 ) {
if ( find_arg ( "-v" ) >= 0 || find_arg ( "-version" ) >= 0 ) {
#ifdef GIT_VERSION
g_print ( "Version: "GIT_VERSION "\n" );
#else
@ -798,6 +805,18 @@ int main ( int argc, char *argv[] )
return EXIT_SUCCESS;
}
if ( find_arg ( "-rasi-validate" ) >= 0 ) {
char *str = NULL;
find_arg_str ( "-rasi-validate", &str );
if ( str != NULL ) {
int retv = rofi_theme_rasi_validate ( str );
cleanup ();
return retv;
}
fprintf ( stderr, "Usage: %s -rasi-validate my-theme.rasi", argv[0] );
return EXIT_FAILURE;
}
{
const char *ro_pid = g_getenv ( "ROFI_OUTSIDE" );
if ( ro_pid != NULL ) {
@ -812,7 +831,7 @@ int main ( int argc, char *argv[] )
// Detect if we are in dmenu mode.
// This has two possible causes.
// 1 the user specifies it on the command-line.
if ( find_arg ( "-dmenu" ) >= 0 ) {
if ( find_arg ( "-dmenu" ) >= 0 ) {
dmenu_mode = TRUE;
}
// 2 the binary that executed is called dmenu (e.g. symlink to rofi)
@ -839,22 +858,43 @@ int main ( int argc, char *argv[] )
}
config_parser_add_option ( xrm_String, "pid", (void * *) &pidfile, "Pidfile location" );
/** default configuration */
{
GBytes *theme_data = g_resource_lookup_data (
resources_get_resource (),
"/org/qtools/rofi/default_configuration.rasi",
G_RESOURCE_LOOKUP_FLAGS_NONE,
NULL );
if ( theme_data ) {
const char *theme = g_bytes_get_data ( theme_data, NULL );
if ( rofi_theme_parse_string ( (const char *) theme ) ) {
g_warning ( "Failed to parse default configuration. Giving up.." );
if ( list_of_error_msgs ) {
for ( GList *iter = g_list_first ( list_of_error_msgs );
iter != NULL; iter = g_list_next ( iter ) ) {
g_warning ( "Error: %s%s%s",
color_bold, ( (GString *) iter->data )->str, color_reset );
}
}
rofi_configuration = NULL;
cleanup ();
return EXIT_FAILURE;
}
g_bytes_unref ( theme_data );
}
}
if ( find_arg ( "-config" ) < 0 ) {
const char *cpath = g_get_user_config_dir ();
if ( cpath ) {
config_path = g_build_filename ( cpath, "rofi", "config", NULL );
config_path_new = g_strconcat ( config_path, ".rasi", NULL );
config_path = g_build_filename ( cpath, "rofi", "config.rasi", NULL );
}
}
else {
char *c = NULL;
find_arg_str ( "-config", &c );
if ( g_str_has_suffix ( c, ".rasi" ) ) {
config_path_new = rofi_expand_path ( c );
}
else {
config_path = rofi_expand_path ( c );
}
config_path = rofi_expand_path ( c );
}
TICK ();
@ -917,21 +957,10 @@ int main ( int argc, char *argv[] )
rofi_theme_parse_file ( etc );
found_system = TRUE;
}
else {
/** Old format. */
gchar *xetc = g_build_filename ( dirs[i], "rofi.conf", NULL );
g_debug ( "Look for default config file: %s", xetc );
if ( g_file_test ( xetc, G_FILE_TEST_IS_REGULAR ) ) {
config_parse_xresource_options_file ( xetc );
old_config_format = TRUE;
found_system = TRUE;
}
g_free ( xetc );
}
g_free ( etc );
}
}
if ( !found_system ) {
if ( !found_system ) {
/** New format. */
gchar *etc = g_build_filename ( SYSCONFDIR, "rofi.rasi", NULL );
g_debug ( "Look for default config file: %s", etc );
@ -939,41 +968,20 @@ int main ( int argc, char *argv[] )
g_debug ( "Look for default config file: %s", etc );
rofi_theme_parse_file ( etc );
}
else {
/** Old format. */
gchar *xetc = g_build_filename ( SYSCONFDIR, "rofi.conf", NULL );
g_debug ( "Look for default config file: %s", xetc );
if ( g_file_test ( xetc, G_FILE_TEST_IS_REGULAR ) ) {
config_parse_xresource_options_file ( xetc );
old_config_format = TRUE;
}
g_free ( xetc );
}
g_free ( etc );
}
// Load in config from X resources.
if ( config.backend == DISPLAY_XCB ) {
config_parse_xresource_options ( xcb );
}
if ( config_path_new && g_file_test ( config_path_new, G_FILE_TEST_IS_REGULAR ) ) {
if ( rofi_theme_parse_file ( config_path_new ) ) {
if ( config_path && g_file_test ( config_path, G_FILE_TEST_IS_REGULAR ) ) {
if ( rofi_theme_parse_file ( config_path ) ) {
rofi_theme_free ( rofi_theme );
rofi_theme = NULL;
}
}
else {
g_free ( config_path_new );
config_path_new = NULL;
if ( g_file_test ( config_path, G_FILE_TEST_IS_REGULAR ) ) {
config_parse_xresource_options_file ( config_path );
old_config_format = TRUE;
}
}
}
find_arg_str ( "-theme", &( config.theme ) );
if ( config.theme ) {
TICK_N ( "Parse theme" );
rofi_theme_reset ( );
if ( rofi_theme_parse_file ( config.theme ) ) {
// TODO: instantiate fallback theme.?
rofi_theme_free ( rofi_theme );
@ -985,10 +993,6 @@ int main ( int argc, char *argv[] )
config_parse_cmd_options ( );
TICK_N ( "Load cmd config " );
if ( old_config_format ) {
g_warning ( "The old Xresources based configuration format is deprecated." );
g_warning ( "Please upgrade: rofi -upgrade-config." );
}
parse_keys_abe ( bindings );
// Get the path to the cache dir.
@ -1043,7 +1047,6 @@ int main ( int argc, char *argv[] )
}
g_bytes_unref ( theme_data );
}
rofi_theme_convert_old ();
}
/**
@ -1065,52 +1068,6 @@ int main ( int argc, char *argv[] )
cleanup ();
return EXIT_SUCCESS;
}
if ( find_arg ( "-upgrade-config" ) >= 0 ) {
setup_modi ();
for ( unsigned int i = 0; i < num_modi; i++ ) {
mode_init ( modi[i] );
}
const char *cpath = g_get_user_config_dir ();
if ( cpath ) {
char *fcpath = g_build_filename ( cpath, "rofi", NULL );
if ( !g_file_test ( fcpath, G_FILE_TEST_IS_DIR ) && g_mkdir_with_parents ( fcpath, 0700 ) < 0 ) {
g_warning ( "Failed to create rofi configuration directory: %s", fcpath );
cleanup ();
g_free ( fcpath );
return EXIT_FAILURE;
}
g_free ( fcpath );
fcpath = g_build_filename ( cpath, "rofi", "config.rasi", NULL );
if ( g_file_test ( fcpath, G_FILE_TEST_IS_REGULAR ) ) {
g_warning ( "New configuration file already exists: %s", fcpath );
cleanup ();
g_free ( fcpath );
return EXIT_FAILURE;
}
FILE *fd = fopen ( fcpath, "w" );
if ( fd == NULL ) {
g_warning ( "Failed to open new rofi configuration file: %s: %s", fcpath, strerror ( errno ) );
cleanup ();
g_free ( fcpath );
return EXIT_FAILURE;
}
config_parse_dump_config_rasi_format ( fd, TRUE );
fprintf ( stdout, "\n***** Generated configuration file in: %s *****\n", fcpath );
fflush ( fd );
fclose ( fd );
g_free ( fcpath );
}
else {
g_warning ( "Failed to get user configuration directory." );
cleanup ();
return EXIT_FAILURE;
}
cleanup ();
return EXIT_SUCCESS;
}
if ( find_arg ( "-dump-config" ) >= 0 ) {
config_parse_dump_config_rasi_format ( stdout, FALSE );
cleanup ();
@ -1118,16 +1075,11 @@ int main ( int argc, char *argv[] )
}
// Dump.
// catch help request
if ( find_arg ( "-h" ) >= 0 || find_arg ( "-help" ) >= 0 || find_arg ( "--help" ) >= 0 ) {
if ( find_arg ( "-h" ) >= 0 || find_arg ( "-help" ) >= 0 || find_arg ( "--help" ) >= 0 ) {
help ( argc, argv );
cleanup ();
return EXIT_SUCCESS;
}
if ( find_arg ( "-dump-xresources" ) >= 0 ) {
config_parse_xresource_dump ();
cleanup ();
return EXIT_SUCCESS;
}
unsigned int interval = 1;
if ( find_arg_uint ( "-record-screenshots", &interval ) ) {
@ -1177,3 +1129,20 @@ int main ( int argc, char *argv[] )
g_free ( windowid );
return return_code;
}
/** List of error messages.*/
extern GList *list_of_error_msgs;
int rofi_theme_rasi_validate ( const char *filename )
{
rofi_theme_parse_file ( filename );
if ( list_of_error_msgs == NULL ) {
return EXIT_SUCCESS;
}
for ( GList *iter = g_list_first ( list_of_error_msgs );
iter != NULL; iter = g_list_next ( iter ) ) {
fputs ( ( (GString *) iter->data )->str, stderr );
}
return EXIT_FAILURE;
}

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -33,6 +33,7 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <math.h>
// GFile stuff.
#include <gio/gio.h>
#include "theme.h"
@ -44,6 +45,7 @@
#include "rofi.h"
#include "rofi-types.h"
#include "display.h"
#include "rofi-icon-fetcher.h"
void yyerror ( YYLTYPE *yylloc, const char *, const char * );
static gboolean distance_compare ( RofiDistance d, RofiDistance e )
@ -107,7 +109,7 @@ RofiDistance rofi_theme_property_copy_distance ( RofiDistance const distance )
return retv;
}
Property* rofi_theme_property_copy ( Property *p )
Property* rofi_theme_property_copy ( const Property *p )
{
Property *retv = rofi_theme_property_create ( p->type );
retv->name = g_strdup ( p->name );
@ -136,6 +138,18 @@ Property* rofi_theme_property_copy ( Property *p )
retv->value.padding.right = rofi_theme_property_copy_distance ( p->value.padding.right );
break;
}
case P_IMAGE:
{
retv->value = p->value;
retv->value.image.url = g_strdup ( p->value.image.url );
retv->value.image.colors = NULL;
for ( GList *l = g_list_first ( p->value.image.colors );
l ; l = g_list_next(l)) {
retv->value.image.colors = g_list_append ( retv->value.image.colors,
g_memdup ( l->data, sizeof(ThemeColor)));
}
break;
}
default:
retv->value = p->value;
}
@ -181,67 +195,28 @@ void rofi_theme_property_free ( Property *p )
rofi_theme_property_free ( p->value.link.def_value );
}
}
if ( p->type == P_PADDING ) {
else if ( p->type == P_PADDING ) {
rofi_theme_distance_property_free ( &( p->value.padding.top ) );
rofi_theme_distance_property_free ( &( p->value.padding.right ) );
rofi_theme_distance_property_free ( &( p->value.padding.bottom ) );
rofi_theme_distance_property_free ( &( p->value.padding.left ) );
}
else if ( p->type == P_IMAGE ) {
if ( p->value.image.url ) {
g_free( p->value.image.url );
}
if ( p->value.image.colors ) {
g_list_free_full ( p->value.image.colors, g_free );
}
}
g_slice_free ( Property, p );
}
/**
* This function is a hack to insert backward support for older theme with the updated listvie structure.
*/
static void rofi_theme_insert_listview_backwards_fix ( void )
{
GHashTable *table = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, (GDestroyNotify) rofi_theme_property_free );
ThemeWidget *t = rofi_theme_find_or_create_name ( rofi_theme, "element" );
ThemeWidget *tt = rofi_theme_find_or_create_name ( rofi_theme, "element-text" );
ThemeWidget *ti = rofi_theme_find_or_create_name ( rofi_theme, "element-icon" );
// Inherit text color
Property *ptc = rofi_theme_property_create ( P_INHERIT );
ptc->name = g_strdup ( "text-color" );
g_hash_table_replace ( table, ptc->name, ptc );
// Transparent background
Property *ptb = rofi_theme_property_create ( P_COLOR );
ptb->name = g_strdup ( "background-color" );
ptb->value.color.red = 0.0;
ptb->value.color.green = 0.0;
ptb->value.color.blue = 0.0;
ptb->value.color.alpha = 0.0;
g_hash_table_replace ( table, ptb->name, ptb );
rofi_theme_widget_add_properties ( tt, table );
RofiDistance dsize = (RofiDistance){ .base = { 1.2, ROFI_PU_CH, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL }, .style = ROFI_HL_SOLID };
Property *pts = rofi_theme_property_create ( P_PADDING );
pts->value.padding.top = pts->value.padding.right = pts->value.padding.bottom = pts->value.padding.left = dsize;
pts->name = g_strdup ( "size" );
g_hash_table_replace ( table, pts->name, pts );
rofi_theme_widget_add_properties ( ti, table );
/** Add spacing between icon and text. */
g_hash_table_destroy ( table );
table = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, (GDestroyNotify) rofi_theme_property_free );
Property *psp = rofi_theme_property_create ( P_PADDING );
psp->name = g_strdup ( "spacing" );
RofiDistance d = (RofiDistance){ .base = { 5, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL }, .style = ROFI_HL_SOLID };
psp->value.padding = (RofiPadding){ d, d, d, d };
g_hash_table_replace ( table, psp->name, psp );
rofi_theme_widget_add_properties ( t, table );
g_hash_table_destroy ( table );
}
void rofi_theme_reset ( void )
{
rofi_theme_free ( rofi_theme );
rofi_theme = g_slice_new0 ( ThemeWidget );
rofi_theme->name = g_strdup ( "Root" );
// Hack to fix backwards compatibility.
rofi_theme_insert_listview_backwards_fix ( );
}
void rofi_theme_free ( ThemeWidget *widget )
@ -347,17 +322,11 @@ static void rofi_theme_print_distance ( RofiDistance d )
printf ( "dash " );
}
}
/** Textual representation of Window Location */
const char * const WindowLocationStr[9] = {
"center",
"northwest",
"north",
"northeast",
"east",
"southeast",
"south",
"southwest",
"west"
/** Textual representation of RofiCursorType */
const char *const RofiCursorTypeStr[3] = {
"default",
"pointer",
"text",
};
static void int_rofi_theme_print_property ( Property *p )
@ -377,6 +346,9 @@ static void int_rofi_theme_print_property ( Property *p )
case P_ORIENTATION:
printf ( "%s", ( p->value.i == ROFI_ORIENTATION_HORIZONTAL ) ? "horizontal" : "vertical" );
break;
case P_CURSOR:
printf ( "%s", RofiCursorTypeStr[p->value.i] );
break;
case P_HIGHLIGHT:
if ( p->value.highlight.style & ROFI_HL_BOLD ) {
printf ( "bold " );
@ -399,8 +371,39 @@ static void int_rofi_theme_print_property ( Property *p )
}
break;
case P_POSITION:
printf ( "%s", WindowLocationStr[p->value.i] );
break;
{
switch ( p->value.i)
{
case WL_CENTER:
fputs("center",stdout);
break;
case WL_NORTH:
fputs("north",stdout);
break;
case WL_SOUTH:
fputs("south",stdout);
break;
case WL_WEST:
fputs("west",stdout);
break;
case WL_EAST:
fputs("east",stdout);
break;
case WL_NORTH|WL_EAST:
fputs("northeast",stdout);
break;
case WL_SOUTH|WL_EAST:
fputs("southeast",stdout);
break;
case WL_NORTH|WL_WEST:
fputs("northwest",stdout);
break;
case WL_SOUTH|WL_WEST:
fputs("southwest",stdout);
break;
}
break;
}
case P_STRING:
printf ( "\"%s\"", p->value.s );
break;
@ -408,8 +411,13 @@ static void int_rofi_theme_print_property ( Property *p )
printf ( "%d", p->value.i );
break;
case P_DOUBLE:
printf ( "%.2f", p->value.f );
break;
{
char sign = (p->value.f < 0);
int top = (int)fabs(p->value.f);
int bottom = (fabs(fmod(p->value.f,1.0)))*100;
printf ( "%s%d.%02d",sign?"-":"", top,bottom);
break;
}
case P_BOOLEAN:
printf ( "%s", p->value.b ? "true" : "false" );
break;
@ -420,6 +428,31 @@ static void int_rofi_theme_print_property ( Property *p )
( p->value.color.blue * 255.0 ),
( p->value.color.alpha * 100.0 ) );
break;
case P_IMAGE:
{
if ( p->value.image.type == ROFI_IMAGE_URL ) {
printf("url (\"%s\")", p->value.s );
} else if ( p->value.image.type == ROFI_IMAGE_LINEAR_GRADIENT ) {
printf("linear-gradient ( ");
guint length = g_list_length ( p->value.image.colors);
guint index = 0;
for ( GList *l = g_list_first ( p->value.image.colors); l != NULL; l = g_list_next(l)) {
ThemeColor *color = (ThemeColor*)l->data;
printf ( "rgba ( %.0f, %.0f, %.0f, %.0f %% )",
( color->red * 255.0 ),
( color->green * 255.0 ),
( color->blue * 255.0 ),
( color->alpha * 100.0 ) );
index++;
if ( index < length ) {
printf(", ");
}
}
printf(")");
}
break;
}
case P_PADDING:
if ( distance_compare ( p->value.padding.top, p->value.padding.bottom ) &&
distance_compare ( p->value.padding.left, p->value.padding.right ) &&
@ -471,7 +504,7 @@ static void rofi_theme_print_property_index ( size_t pnl, int depth, Property *p
putchar ( '\n' );
}
static void rofi_theme_print_index ( ThemeWidget *widget, int index )
void rofi_theme_print_index ( ThemeWidget *widget, int index )
{
GHashTableIter iter;
gpointer key, value;
@ -719,6 +752,14 @@ Property *rofi_theme_find_property ( ThemeWidget *widget, PropertyType type, con
}
return NULL;
}
ThemeWidget *rofi_config_find_widget ( const char *name, const char *state, gboolean exact )
{
// First find exact match based on name.
ThemeWidget *widget = rofi_theme_find_single ( rofi_configuration, name );
widget = rofi_theme_find ( widget, state, exact );
return widget;
}
ThemeWidget *rofi_theme_find_widget ( const char *name, const char *state, gboolean exact )
{
// First find exact match based on name.
@ -728,14 +769,36 @@ ThemeWidget *rofi_theme_find_widget ( const char *name, const char *state, gbool
return widget;
}
static int rofi_theme_get_position_inside ( Property *p, const widget *widget, const char *property, int def )
{
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_POSITION, property, FALSE );
return rofi_theme_get_position_inside ( p, widget, property, def );
}
return def;
}
return p->value.i;
}
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
return def;
}
int rofi_theme_get_position ( const widget *widget, const char *property, int def )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_POSITION, property, FALSE );
return rofi_theme_get_position_inside ( p, widget, property, def );
}
static int rofi_theme_get_integer_inside ( Property *p, const widget *widget, const char *property, int def )
{
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
return rofi_theme_get_position ( widget->parent, property, def );
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_INTEGER, property, FALSE );
return rofi_theme_get_integer_inside ( p, widget, property, def );
}
return def;
}
@ -744,31 +807,20 @@ int rofi_theme_get_position ( const widget *widget, const char *property, int de
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
return def;
}
int rofi_theme_get_integer ( const widget *widget, const char *property, int def )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_INTEGER, property, FALSE );
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
return rofi_theme_get_integer ( widget->parent, property, def );
}
return def;
}
return p->value.i;
}
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
return def;
return rofi_theme_get_integer_inside ( p, widget, property, def );
}
RofiDistance rofi_theme_get_distance ( const widget *widget, const char *property, int def )
static RofiDistance rofi_theme_get_distance_inside ( Property *p, const widget *widget, const char *property, int def )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_PADDING, property, FALSE );
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
return rofi_theme_get_distance ( widget->parent, property, def );
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_PADDING, property, FALSE );
return rofi_theme_get_distance_inside ( p, widget->parent, property, def );
}
return (RofiDistance){ .base = { def, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL }, .style = ROFI_HL_SOLID };
}
@ -782,15 +834,44 @@ RofiDistance rofi_theme_get_distance ( const widget *widget, const char *propert
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
return (RofiDistance){ .base = { def, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL }, .style = ROFI_HL_SOLID };
}
RofiDistance rofi_theme_get_distance ( const widget *widget, const char *property, int def )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_PADDING, property, FALSE );
return rofi_theme_get_distance_inside ( p, widget, property, def );
}
static int rofi_theme_get_boolean_inside ( Property *p, const widget *widget, const char *property, int def )
{
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_BOOLEAN, property, FALSE );
return rofi_theme_get_boolean_inside ( p, widget, property, def );
}
return def;
}
return p->value.b;
}
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
return def;
}
int rofi_theme_get_boolean ( const widget *widget, const char *property, int def )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_BOOLEAN, property, FALSE );
return rofi_theme_get_boolean_inside ( p, widget, property, def );
}
static RofiOrientation rofi_theme_get_orientation_inside ( Property *p, const widget *widget, const char *property, RofiOrientation def )
{
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
return rofi_theme_get_boolean ( widget->parent, property, def );
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_ORIENTATION, property, FALSE );
return rofi_theme_get_orientation_inside ( p, widget, property, def );
}
return def;
}
@ -803,27 +884,39 @@ RofiOrientation rofi_theme_get_orientation ( const widget *widget, const char *p
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_ORIENTATION, property, FALSE );
return rofi_theme_get_orientation_inside ( p, widget, property, def );
}
static RofiCursorType rofi_theme_get_cursor_type_inside ( Property *p, const widget *widget, const char *property, RofiCursorType def )
{
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
return rofi_theme_get_orientation ( widget->parent, property, def );
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_CURSOR, property, FALSE );
return rofi_theme_get_cursor_type_inside ( p, widget, property, def );
}
return def;
}
return p->value.b;
return p->value.i;
}
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
return def;
}
const char *rofi_theme_get_string ( const widget *widget, const char *property, const char *def )
RofiCursorType rofi_theme_get_cursor_type ( const widget *widget, const char *property, RofiCursorType def )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_STRING, property, FALSE );
Property *p = rofi_theme_find_property ( wid, P_CURSOR, property, FALSE );
return rofi_theme_get_cursor_type_inside ( p, widget, property, def );
}
static const char *rofi_theme_get_string_inside ( Property *p, const widget *widget, const char *property, const char *def )
{
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
return rofi_theme_get_string ( widget->parent, property, def );
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_STRING, property, FALSE );
return rofi_theme_get_string_inside ( p, widget, property, def );
}
return def;
}
@ -832,14 +925,20 @@ const char *rofi_theme_get_string ( const widget *widget, const char *property,
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
return def;
}
double rofi_theme_get_double ( const widget *widget, const char *property, double def )
const char *rofi_theme_get_string ( const widget *widget, const char *property, const char *def )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_DOUBLE, property, FALSE );
Property *p = rofi_theme_find_property ( wid, P_STRING, property, FALSE );
return rofi_theme_get_string_inside ( p, widget, property, def );
}
static double rofi_theme_get_double_inside ( ThemeWidget *wid, Property *p, const widget *widget, const char *property, double def )
{
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
return rofi_theme_get_double ( widget->parent, property, def );
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_DOUBLE, property, FALSE );
return rofi_theme_get_double_inside ( parent, p, widget, property, def );
}
return def;
}
@ -850,7 +949,9 @@ double rofi_theme_get_double ( const widget *widget, const char *property, doubl
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
return rofi_theme_get_double ( widget->parent, property, def );
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_INTEGER, property, FALSE );
return rofi_theme_get_double_inside ( parent, p, widget->parent, property, def );
}
return def;
}
@ -859,36 +960,157 @@ double rofi_theme_get_double ( const widget *widget, const char *property, doubl
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
return def;
}
void rofi_theme_get_color ( const widget *widget, const char *property, cairo_t *d )
double rofi_theme_get_double ( const widget *widget, const char *property, double def )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_COLOR, property, FALSE );
Property *p = rofi_theme_find_property ( wid, P_DOUBLE, property, FALSE );
return rofi_theme_get_double_inside ( wid, p, widget, property, def );
}
static void rofi_theme_get_color_inside ( const widget *widget, Property *p, const char *property, cairo_t *d )
{
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
rofi_theme_get_color ( widget->parent, property, d );
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_COLOR, property, FALSE );
rofi_theme_get_color_inside ( widget, p, property, d );
}
return;
}
cairo_set_source_rgba ( d,
p->value.color.red,
p->value.color.green,
p->value.color.blue,
p->value.color.alpha
);
p->value.color.red,
p->value.color.green,
p->value.color.blue,
p->value.color.alpha
);
}
else {
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
}
}
RofiPadding rofi_theme_get_padding ( const widget *widget, const char *property, RofiPadding pad )
void rofi_theme_get_color ( const widget *widget, const char *property, cairo_t *d )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_PADDING, property, FALSE );
Property *p = rofi_theme_find_property ( wid, P_COLOR, property, FALSE );
rofi_theme_get_color_inside ( widget, p, property, d );
}
static gboolean rofi_theme_get_image_inside ( Property *p, const widget *widget, const char *property, cairo_t *d )
{
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
return rofi_theme_get_padding ( widget->parent, property, pad );
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_IMAGE, property, FALSE );
return rofi_theme_get_image_inside ( p, widget, property, d );
}
return FALSE;
}
if ( p->value.image.type == ROFI_IMAGE_URL ) {
int wsize = -1;
int hsize = -1;
switch ( p->value.image.scaling ) {
case ROFI_SCALE_BOTH:
wsize = widget->w;
hsize = widget->h;
break;
case ROFI_SCALE_WIDTH:
wsize = widget->w;
break;
case ROFI_SCALE_HEIGHT:
hsize = widget->h;
break;
case ROFI_SCALE_NONE:
default:
break;
}
if ( p->value.image.surface_id == 0 || p->value.image.wsize != wsize || p->value.image.hsize != hsize) {
p->value.image.surface_id = rofi_icon_fetcher_query_advanced ( p->value.image.url, wsize, hsize );
p->value.image.wsize = wsize;
p->value.image.hsize = hsize;
}
cairo_surface_t *img = rofi_icon_fetcher_get ( p->value.image.surface_id );
if ( img != NULL ) {
cairo_pattern_t * pat = cairo_pattern_create_for_surface ( img );
cairo_pattern_set_extend ( pat, CAIRO_EXTEND_REPEAT );
cairo_set_source ( d, pat );
cairo_pattern_destroy ( pat );
return TRUE;
}
} else if ( p->value.image.type == ROFI_IMAGE_LINEAR_GRADIENT ) {
cairo_pattern_t * pat = NULL;
switch ( p->value.image.dir ) {
case ROFI_DIRECTION_RIGHT:
pat = cairo_pattern_create_linear (0.0,0.0, widget->w, 0.0);
break;
case ROFI_DIRECTION_LEFT:
pat = cairo_pattern_create_linear (widget->w,0.0, 0.0, 0.0);
break;
case ROFI_DIRECTION_BOTTOM:
pat = cairo_pattern_create_linear (0.0,0.0, 0.0, widget->h);
break;
case ROFI_DIRECTION_TOP:
pat = cairo_pattern_create_linear (0.0,widget->h, 0.0, 0.0);
break;
case ROFI_DIRECTION_ANGLE:
{
double offsety1 = sin(G_PI*2*p->value.image.angle)*(widget->h/2.0);
double offsetx1 = cos(G_PI*2*p->value.image.angle)*(widget->w/2.0);
pat = cairo_pattern_create_linear (
widget->w/2.0 - offsetx1, widget->h/2.0 - offsety1,
widget->w/2.0 + offsetx1, widget->h/2.0 + offsety1 );
break;
}
};
guint length = g_list_length ( p->value.image.colors );
if ( length > 1 ) {
length--;
guint color_index = 0;
for ( GList *l = g_list_first ( p->value.image.colors); l != NULL ; l = g_list_next ( l ) )
{
ThemeColor *c = (ThemeColor*) (l->data);
cairo_pattern_add_color_stop_rgba ( pat,(color_index)/(double)length,
c->red, c->green,
c->blue, c->alpha);
color_index++;
}
cairo_set_source ( d, pat );
cairo_pattern_destroy ( pat );
return TRUE;
} else if ( length == 1 ) {
ThemeColor *c = (ThemeColor*) (p->value.image.colors->data);
cairo_pattern_add_color_stop_rgba ( pat,0,
c->red, c->green,
c->blue, c->alpha);
cairo_set_source ( d, pat );
cairo_pattern_destroy ( pat );
return TRUE;
}
}
}
else {
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
}
return FALSE;
}
gboolean rofi_theme_get_image ( const widget *widget, const char *property, cairo_t *d )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_IMAGE , property, FALSE );
return rofi_theme_get_image_inside (p, widget, property, d);
}
static RofiPadding rofi_theme_get_padding_inside ( Property *p, const widget *widget, const char *property, RofiPadding pad )
{
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_PADDING, property, FALSE );
return rofi_theme_get_padding_inside ( p, widget, property, pad );
}
return pad;
}
@ -903,15 +1125,21 @@ RofiPadding rofi_theme_get_padding ( const widget *widget, const char *property,
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
return pad;
}
GList *rofi_theme_get_list ( const widget *widget, const char * property, const char *defaults )
RofiPadding rofi_theme_get_padding ( const widget *widget, const char *property, RofiPadding pad )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_PADDING, property, FALSE );
return rofi_theme_get_padding_inside ( p, widget, property, pad );
}
static GList *rofi_theme_get_list_inside ( Property *p, const widget *widget, const char * property, const char *defaults )
{
ThemeWidget *wid2 = rofi_theme_find_widget ( widget->name, widget->state, TRUE );
Property *p = rofi_theme_find_property ( wid2, P_LIST, property, TRUE );
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
return rofi_theme_get_list ( widget->parent, property, defaults );
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_LIST, property, FALSE );
return rofi_theme_get_list_inside ( p, widget, property, defaults );
}
}
else if ( p->type == P_LIST ) {
@ -929,15 +1157,21 @@ GList *rofi_theme_get_list ( const widget *widget, const char * property, const
}
return NULL;
}
RofiHighlightColorStyle rofi_theme_get_highlight ( widget *widget, const char *property, RofiHighlightColorStyle th )
GList *rofi_theme_get_list ( const widget *widget, const char * property, const char *defaults )
{
ThemeWidget *wid2 = rofi_theme_find_widget ( widget->name, widget->state, TRUE );
Property *p = rofi_theme_find_property ( wid2, P_LIST, property, TRUE );
return rofi_theme_get_list_inside ( p, widget, property, defaults );
}
static RofiHighlightColorStyle rofi_theme_get_highlight_inside ( Property *p, widget *widget, const char *property, RofiHighlightColorStyle th )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_HIGHLIGHT, property, FALSE );
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
return rofi_theme_get_highlight ( widget->parent, property, th );
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_HIGHLIGHT, property, FALSE );
return rofi_theme_get_highlight_inside ( p, widget->parent, property, th );
}
return th;
}
@ -946,7 +1180,12 @@ RofiHighlightColorStyle rofi_theme_get_highlight ( widget *widget, const char *p
g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property );
return th;
}
RofiHighlightColorStyle rofi_theme_get_highlight ( widget *widget, const char *property, RofiHighlightColorStyle th )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_HIGHLIGHT, property, FALSE );
return rofi_theme_get_highlight_inside ( p, widget, property, th );
}
static int get_pixels ( RofiDistanceUnit *unit, RofiOrientation ori )
{
int val = unit->distance;
@ -1061,150 +1300,11 @@ gboolean rofi_theme_is_empty ( void )
return FALSE;
}
#ifdef THEME_CONVERTER
static char * rofi_theme_convert_color ( char *col )
{
char *r = g_strstrip ( col );
if ( *r == '#' && strlen ( r ) == 9 ) {
char a1 = r[1];
char a2 = r[2];
r[1] = r[3];
r[2] = r[4];
r[3] = r[5];
r[4] = r[6];
r[5] = r[7];
r[6] = r[8];
r[7] = a1;
r[8] = a2;
}
return r;
}
void rofi_theme_convert_old ( void )
{
{
char *str = g_strdup_printf ( "#window { border: %d; padding: %d;}", config.menu_bw, config.padding );
rofi_theme_parse_string ( str );
g_free ( str );
}
if ( config.color_window ) {
char **retv = g_strsplit ( config.color_window, ",", -1 );
const char * const conf[] = {
"* { background: %s; }",
"* { border-color: %s; }",
"* { separatorcolor: %s; }"
};
for ( int i = 0; retv && i < 3 && retv[i]; i++ ) {
char *str = g_strdup_printf ( conf[i], rofi_theme_convert_color ( retv[i] ) );
rofi_theme_parse_string ( str );
g_free ( str );
}
g_strfreev ( retv );
}
if ( config.color_normal ) {
char **retv = g_strsplit ( config.color_normal, ",", -1 );
const char * const conf[] = {
"* { normal-background: %s; }",
"* { foreground: %s; normal-foreground: @foreground; alternate-normal-foreground: @foreground; }",
"* { alternate-normal-background: %s; }",
"* { selected-normal-background: %s; }",
"* { selected-normal-foreground: %s; }"
};
for ( int i = 0; retv && retv[i] && i < 5; i++ ) {
char *str = g_strdup_printf ( conf[i], rofi_theme_convert_color ( retv[i] ) );
rofi_theme_parse_string ( str );
g_free ( str );
}
g_strfreev ( retv );
}
if ( config.color_urgent ) {
char **retv = g_strsplit ( config.color_urgent, ",", -1 );
const char * const conf[] = {
"* { urgent-background: %s; }",
"* { urgent-foreground: %s; alternate-urgent-foreground: @urgent-foreground;}",
"* { alternate-urgent-background: %s; }",
"* { selected-urgent-background: %s; }",
"* { selected-urgent-foreground: %s; }"
};
for ( int i = 0; retv && retv[i] && i < 5; i++ ) {
char *str = g_strdup_printf ( conf[i], rofi_theme_convert_color ( retv[i] ) );
rofi_theme_parse_string ( str );
g_free ( str );
}
g_strfreev ( retv );
}
if ( config.color_active ) {
char **retv = g_strsplit ( config.color_active, ",", -1 );
const char * const conf[] = {
"* { active-background: %s; }",
"* { active-foreground: %s; alternate-active-foreground: @active-foreground;}",
"* { alternate-active-background: %s; }",
"* { selected-active-background: %s; }",
"* { selected-active-foreground: %s; }"
};
for ( int i = 0; retv && retv[i] && i < 5; i++ ) {
char *str = g_strdup_printf ( conf[i], rofi_theme_convert_color ( retv[i] ) );
rofi_theme_parse_string ( str );
g_free ( str );
}
g_strfreev ( retv );
}
if ( config.separator_style != NULL ) {
if ( g_strcmp0 ( config.separator_style, "none" ) == 0 ) {
const char *const str = "#listview { border: 0px; }";
rofi_theme_parse_string ( str );
const char *const str2 = "#mode-switcher { border: 0px; }";
rofi_theme_parse_string ( str2 );
const char *const str3 = "#message { border: 0px; }";
rofi_theme_parse_string ( str3 );
}
else if ( g_strcmp0 ( config.separator_style, "solid" ) == 0 ) {
const char *const str = "#listview { border: 2px solid 0px 0px 0px; }";
rofi_theme_parse_string ( str );
const char *const str2 = "#mode-switcher { border: 2px solid 0px 0px 0px; }";
rofi_theme_parse_string ( str2 );
const char *const str3 = "#message { border: 2px solid 0px 0px 0px; }";
rofi_theme_parse_string ( str3 );
} /* dash is default */
}
/* Line Margin */
{
char *str = g_strdup_printf ( "#listview { spacing: %dpx;}", config.line_margin );
rofi_theme_parse_string ( str );
g_free ( str );
}
/* Line Padding */
{
char *str = g_strdup_printf ( "#element, inputbar, message { padding: %dpx;}", config.line_padding );
rofi_theme_parse_string ( str );
g_free ( str );
}
if ( config.hide_scrollbar ) {
const char *str = "#listview { scrollbar: false; }";
rofi_theme_parse_string ( str );
}
else {
const char *str = "#listview { scrollbar: true; }";
rofi_theme_parse_string ( str );
char *str2 = g_strdup_printf ( "#scrollbar { handle-width: %dpx; }", config.scrollbar_width );
rofi_theme_parse_string ( str2 );
g_free ( str2 );
}
if ( config.fake_transparency ) {
char *str = g_strdup_printf ( "#window { transparency: \"%s\"; }", config.fake_background );
rofi_theme_parse_string ( str );
g_free ( str );
}
}
#endif // THEME_CONVERTER
char * rofi_theme_parse_prepare_file ( const char *file, const char *parent_file )
{
char *filename = rofi_expand_path ( file );
// If no absolute path specified, expand it.
if ( parent_file != NULL && !g_path_is_absolute ( filename ) ) {
if ( parent_file != NULL && !g_path_is_absolute ( filename ) ) {
char *basedir = g_path_get_dirname ( parent_file );
char *path = g_build_filename ( basedir, filename, NULL );
g_free ( filename );
@ -1377,14 +1477,14 @@ ThemeMediaType rofi_theme_parse_media_type ( const char *type )
return THEME_MEDIA_TYPE_INVALID;
}
gboolean rofi_theme_has_property ( const widget *widget, const char *property )
static gboolean rofi_theme_has_property_inside ( Property *p, const widget *widget, const char *property )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_STRING, property, FALSE );
if ( p ) {
if ( p->type == P_INHERIT ) {
if ( widget->parent ) {
return rofi_theme_has_property ( widget->parent, property );
ThemeWidget *parent= rofi_theme_find_widget ( widget->parent->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( parent, P_STRING, property, FALSE );
return rofi_theme_has_property_inside ( p, widget, property );
}
return FALSE;
}
@ -1392,3 +1492,9 @@ gboolean rofi_theme_has_property ( const widget *widget, const char *property )
}
return FALSE;
}
gboolean rofi_theme_has_property ( const widget *widget, const char *property )
{
ThemeWidget *wid = rofi_theme_find_widget ( widget->name, widget->state, FALSE );
Property *p = rofi_theme_find_property ( wid, P_STRING, property, FALSE );
return rofi_theme_has_property_inside ( p, widget, property );
}

View file

@ -2,7 +2,7 @@
* rofi
*
* MIT/X11 License
* Copyright © 2013-2020 Qball Cow <qball@gmpclient.org>
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the

Some files were not shown because too many files have changed in this diff Show more