ifneq ($(PREFIX),/usr/)
sed -i -re 's#/usr/bin/autorandr#$(subst #,\#,${PREFIX})/bin/autorandr#g' ${DESTDIR}/${XDG_AUTOSTART_DIR}/autorandr.desktop
+ sed -i -re 's#/usr/bin/autorandr#$(subst #,\#,${PREFIX})/bin/autorandr#g' ${DESTDIR}/${XDG_AUTOSTART_DIR}/autorandr-kde.desktop
endif
uninstall_autostart_config:
install_udev:
$(if $(UDEV_RULES_DIR),,$(error UDEV_RULES_DIR is not defined))
mkdir -p ${DESTDIR}/${UDEV_RULES_DIR}/
- echo 'ACTION=="change", SUBSYSTEM=="drm", RUN+="$(if $(findstring systemd, $(MAKECMDGOALS)),/bin/systemctl start --no-block autorandr.service,${PREFIX}/bin/autorandr --batch --change --default default)"' > ${DESTDIR}/${UDEV_RULES_DIR}/40-monitor-hotplug.rules
+ echo 'ACTION=="change", SUBSYSTEM=="drm", RUN+="$(if $(findstring systemd, $(DEFAULT_TARGETS)),/bin/systemctl start --no-block autorandr.service,${PREFIX}/bin/autorandr --batch --change --default default)"' > ${DESTDIR}/${UDEV_RULES_DIR}/40-monitor-hotplug.rules
@echo
@echo "To activate the udev rules, run this command as root:"
@echo " udevadm control --reload-rules"
ifneq (,$(LAUNCHER_LDLIBS))
CLEANUP_FILES+=contrib/autorandr_launcher/autorandr-launcher
LAUNCHER_CFLAGS=$(shell pkg-config --cflags pkg-config xcb xcb-randr 2>/dev/null)
+DEF_AUTORANDR_PATH="-DAUTORANDR_PATH=\"${DESTDIR}${PREFIX}/bin/autorandr\""
contrib/autorandr_launcher/autorandr-launcher: contrib/autorandr_launcher/autorandr_launcher.c
- $(CC) $(CFLAGS) $(LAUNCHER_CFLAGS) -o $@ $+ $(LDFLAGS) $(LAUNCHER_LDLIBS) $(LDLIBS)
+ $(CC) $(CFLAGS) $(LAUNCHER_CFLAGS) $(DEF_AUTORANDR_PATH) -o $@ $+ $(LDFLAGS) $(LAUNCHER_LDLIBS) $(LDLIBS)
install_launcher: contrib/autorandr_launcher/autorandr-launcher
mkdir -p ${DESTDIR}${PREFIX}/bin
* Nazar Mokrynskyi
* Phillip Berndt
* Rasmus Wriedt Larsen
+* Sam Coulter
* Simon Wydooghe
* Stefan Tomanek
* stormc
options nvidia_drm modeset=1
```
+### Wayland
+
+Before running autorandr will check the environment for the `WAYLAND_DISPLAY`
+variable to check if the program is running in a Wayland session. This is to
+avoid issues between usage of xrandr in Wayland environments.
+
+If you need to run autorandr in a Wayland environment, one workaround is to
+unset the `WAYLAND_DISPLAY` variable before running the program, such as:
+
+```
+WAYLAND_DISPLAY= autorandr
+```
+
## Changelog
+**autorandr 1.14**
+* *2023-06-22* Direct --match-edid renaming of output messages to stderr
+* *2023-06-22* Add Wayland awareness
+* *2023-06-22* Various minor auxiliary tooling bug fixes, see git-log
+
**autorandr 1.13.3**
* *2023-01-24* Revert udev rule to rely on "change" event (see #324)
.SH HOOK SCRIPTS
-Three more scripts can be placed in the configuration directory:
+Four more scripts can be placed in the configuration directory:
.TP
\fIpostswitch\fR
Executed after a mode switch has taken place. This can be used to notify
else:
import configparser
-__version__ = "1.13.3"
+__version__ = "1.14"
try:
input = raw_input
--dry-run don't change anything, only print the xrandr commands
--fingerprint fingerprint your current hardware setup
--ignore-lid treat outputs as connected even if their lids are closed
---match-edid match diplays based on edid instead of name
+--match-edid match displays based on edid instead of name
--force force (re)loading of a profile / overwrite exiting files
--list list configurations
--skip-options <option> comma separated list of xrandr arguments (e.g. "gamma")
return x + 10000 * y
def __init__(self, output, edid, options):
- "Instanciate using output name, edid and a dictionary of XRandR command line parameters"
+ "Instantiate using output name, edid and a dictionary of XRandR command line parameters"
self.output = output
self.edid = edid
self.options = options
self.ignored_options = list(options)
def remove_default_option_values(self):
- "Remove values from the options dictionary that are superflous"
+ "Remove values from the options dictionary that are superfluous"
if "off" in self.options and len(self.options.keys()) > 1:
self.options = {"off": None}
return
@classmethod
def from_xrandr_output(cls, xrandr_output):
- """Instanciate an XrandrOutput from the output of `xrandr --verbose'
+ """Instantiate an XrandrOutput from the output of `xrandr --verbose'
This method also returns a list of modes supported by the output.
"""
@classmethod
def from_config_file(cls, profile, edid_map, configuration):
- "Instanciate an XrandrOutput from the contents of a configuration file"
+ "Instantiate an XrandrOutput from the contents of a configuration file"
options = {}
for line in configuration.split("\n"):
if line:
# We are not interested in screens
xrandr_output = re.sub("(?m)^Screen [0-9].+", "", xrandr_output).strip()
- # Split at output boundaries and instanciate an XrandrOutput per output
+ # Split at output boundaries and instantiate an XrandrOutput per output
split_xrandr_output = re.split("(?m)^([^ ]+ (?:(?:dis)?connected|unknown connection).*)$", xrandr_output)
if len(split_xrandr_output) < 2:
raise AutorandrException("No output boundaries found", report_bug=True)
if profile_config[c].fingerprint != fingerprint or c == fp_map[fingerprint]:
continue
- print("%s: renaming display %s to %s" % (p, c, fp_map[fingerprint]))
+ print("%s: renaming display %s to %s" % (p, c, fp_map[fingerprint]), file=sys.stderr)
tmp_disp = profile_config[c]
# If we did not find a candidate, we might need to inject a call
# If there is no output to disable, we will enable 0x and x0 at the same time
if not found_top_left_monitor and len(disable_outputs) > 0:
- # If the call to 0x and x0 is splitted, inject one of them
+ # If the call to 0x and x0 is split, inject one of them
if found_top_monitor and found_left_monitor:
enable_outputs.insert(0, enable_outputs[0])
# Cannot work with this environment, skip.
continue
+ if "WAYLAND_DISPLAY" in process_environ and process_environ["WAYLAND_DISPLAY"]:
+ if "--debug" in argv:
+ print("Detected Wayland session '{0}'. Skipping.".format(process_environ["WAYLAND_DISPLAY"]))
+ continue
+
# To allow scripts to detect batch invocation (especially useful for predetect)
process_environ["AUTORANDR_BATCH_PID"] = str(os.getpid())
process_environ["UID"] = str(uid)
user = pwd.getpwuid(os.getuid())
user = user.pw_name if user else "#%d" % os.getuid()
print("autorandr running as user %s (started from batch instance)" % user)
+ if ("WAYLAND_DISPLAY" in os.environ and os.environ["WAYLAND_DISPLAY"]):
+ print("Detected Wayland session '{0}'. Exiting.".format(os.environ["WAYLAND_DISPLAY"]), file=sys.stderr)
+ sys.exit(1)
profiles = {}
profile_symlinks = {}
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <string.h>
+
+#ifndef AUTORANDR_PATH
+#define AUTORANDR_PATH "/usr/bin/autorandr"
+#endif
// indent -kr -i8
static int VERBOSE = 0;
kill(getpid(), signum);
}
-static void ar_log(const char *format, ...)
+__attribute__((format(printf, 1, 2))) static void ar_log(const char *format, ...)
{
va_list args;
fflush(stdout);
}
-static int ar_launch()
+static int ar_launch(void)
{
pid_t pid = fork();
if (pid == 0) {
- static char *argv[] =
- { "/usr/bin/autorandr", "--change", "--default", "default", NULL };
- execve(argv[0], argv, environ);
+ static char *argv[] = { AUTORANDR_PATH, "--change", "--default", "default", NULL};
+ if (execve(argv[0], argv, environ) == -1) {
+ int errsv = errno;
+ fprintf(stderr, "Error executing file: %s\n", strerror(errsv));
+ exit(errsv);
+ }
+
exit(127);
} else {
waitpid(pid, 0, 0);
xcb_timestamp_t last_timestamp = (xcb_timestamp_t) 0;
time_t last_time = time(NULL);
- while (1) {
-
- ar_log("Waiting for event\n");
- xcb_generic_event_t *evt = xcb_wait_for_event(c);
- if (!evt) {
- break;
- }
-
- // ar_log("Event type: %" PRIu8 "\n", evt->response_type);
- // ar_log("screen change masked: %" PRIu8 "\n",
- // evt->response_type &
- // XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
+ ar_log("Waiting for event\n");
+ xcb_generic_event_t *evt;
+ while ( (evt = xcb_wait_for_event(c)) ) {
+ ar_log("Event type: %" PRIu8 "\n", evt->response_type);
+ ar_log("screen change masked: %" PRIu8 "\n",
+ evt->response_type &
+ XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
if (evt->response_type &
XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE) {
--- /dev/null
+CFLAGS = -pipe \
+ -o2 \
+ -Wstrict-overflow=5 -fstack-protector-all \
+ -W -Wall -Wextra \
+ -Wbad-function-cast \
+ -Wcast-align \
+ -Wcast-qual \
+ -Wconversion \
+ -Wfloat-equal \
+ -Wformat-y2k \
+ -Winit-self \
+ -Winline \
+ -Winvalid-pch \
+ -Wmissing-declarations \
+ -Wmissing-field-initializers \
+ -Wmissing-format-attribute \
+ -Wmissing-include-dirs \
+ -Wmissing-noreturn \
+ -Wmissing-prototypes \
+ -Wnested-externs \
+ -Wnormalized=nfc \
+ -Wold-style-definition \
+ -Woverlength-strings \
+ -Wpacked \
+ -Wpadded \
+ -Wpointer-arith \
+ -Wredundant-decls \
+ -Wshadow \
+ -Wsign-compare \
+ -Wstack-protector \
+ -Wstrict-aliasing=2 \
+ -Wstrict-prototypes \
+ -Wundef \
+ -Wunsafe-loop-optimizations \
+ -Wvolatile-register-var \
+ -Wwrite-strings
+
+
+LAUNCHER_LDLIBS=$(shell pkg-config --libs pkg-config xcb xcb-randr 2>/dev/null)
+LAUNCHER_CFLAGS=$(shell pkg-config --cflags pkg-config xcb xcb-randr 2>/dev/null)
+USER_DEFS="-DAUTORANDR_PATH=\"$(shell which autorandr 2>/dev/null)\""
+#------------------------------------------------------------------------------
+.PHONY : all clean
+
+#------------------------------------------------------------------------------
+all : autorandr-launcher
+
+autorandr-launcher: autorandr_launcher.c
+ $(CC) $(CFLAGS) $(LAUNCHER_CFLAGS) $(USER_DEFS) -o $@ $+ $(LAUNCHER_LDLIBS)
+
+#------------------------------------------------------------------------------
+clean :
+ $(RM) autorandr-launcher *.o
-#!/bin/bash
+#!/usr/bin/env bash
# autorandr_nitrogen_wallpaper
# Copyright (c) 2015, Ondra 'Kepi' KudlĂk, http://kepi.cz
PROFILE_BG_FILE="bg-saved.$PROFILE.cfg"
PROFILE_BG="$NITROGEN_HOME/$PROFILE_BG_FILE"
+CP=$(which cp)
+MV=$(which mv)
+UNLINK=$(which unlink)
+NITROGEN=$(which nitrogen)
+
# save background for detected profile
if [[ $1 = 'savebg' ]]; then
- # nitrogen config doesnt exist, instruct to run it first
+ # nitrogen config doesn't exist, instruct to run it first
if [[ ! -f "$NITROGEN_BG" ]]; then
echo "wallpaper: you need to first run 'nitrogen' and set your wallpapers"
exit 2
fi
# nitrogen config exists but is broken symlink, just remove it and instruct to run it first
if [ ! -e "$NITROGEN_BG" ] ; then
- /usr/bin/unlink "$NITROGEN_BG"
+ $UNLINK "$NITROGEN_BG"
echo "wallpaper: you need to first run 'nitrogen' and set your wallpapers (config was broken)"
exit 3
fi
- /bin/cp -L "$NITROGEN_BG" "$PROFILE_BG"
+ $CP -L "$NITROGEN_BG" "$PROFILE_BG"
# load background for detected profile
else
# nitrogen original file exists and not symlink
if [[ -f "$NITROGEN_BG" ]] && [[ ! -L "$NITROGEN_BG" ]]; then
echo "wallpaper: Backing up nitrogen saved bg to $NITROGEN_BG.backup"
- /bin/mv "$NITROGEN_BG" "$NITROGEN_BG".backup
+ $MV "$NITROGEN_BG" "$NITROGEN_BG".backup
fi
# set symlink
echo "wallpaper: Found saved wallpaper for profile $PROFILE - changing"
ln -f -s "$PROFILE_BG_FILE" "$NITROGEN_BG"
# call nitrogen
- nitrogen --restore
+ $NITROGEN --restore
else
echo "wallpaper: No saved wallpaper found for profile $PROFILE"
fi
--- /dev/null
+# don't complete directories and paths
+complete -c autorandr -f
+
+set -l virtual_profiles off common clone-largest horizontal vertical
+set -l user_profiles (autorandr --list)
+set -l profile_users -d --default -s --save -l --load -r --remove
+
+complete -c autorandr -n "__fish_seen_subcommand_from $profile_users" \
+ -a "$virtual_profiles $user_profiles"
+
+complete -c autorandr -s -h -l help -d 'get help'
+complete -c autorandr -s -c -l change -d 'automatically load the first detected profile'
+complete -c autorandr -s -d -l default -d 'set default PROFILE'
+complete -c autorandr -s -l -l load -d 'load PROFILE'
+complete -c autorandr -s -s -l save -d 'save current setup to a PROFILE'
+complete -c autorandr -s -r -l remove -d 'remove PROFILE'
+complete -c autorandr -l current -d 'list curren active configurations'
+complete -c autorandr -l cycle -d 'cycle through all detected drofiles'
+complete -c autorandr -l config -d 'dump current xrandr setup'
+complete -c autorandr -l debug -d 'enable verbose output'
+complete -c autorandr -l dry-run -d 'don\'t change anything'
+complete -c autorandr -l fingerprint -d 'fingerprint current hardware'
+complete -c autorandr -l match-edid -d 'match displays using edid'
+complete -c autorandr -l force -d 'force loading of a profile'
+complete -c autorandr -l list -d 'list all profiles'
+complete -c autorandr -l skip-options -d 'Set a comma-separated lis of xrandr arguments to skip buth in change detection and profile application'
+complete -c autorandr -l ignore-lid -d 'By default, closed lids are considered as disconnected if other outputs are detected. This flag disables this behavior'
+complete -c autorandr -l version -d 'show version'
BuildRequires: desktop-file-utils
Recommends: (%{name}-bash-completion = %{version}-%{release} if bash)
+Recommends: (%{name}-fish-completion = %{version}-%{release} if fish)
Recommends: (%{name}-zsh-completion = %{version}-%{release} if zsh)
%description
%description bash-completion
This package provides bash-completion files for autorandr
+%package fish-completion
+Summary: Fish completion for autorandr
+Requires: %{name}
+Requires: fish-completion
+%description fish-completion
+This package provides fish-completion files for autorandr
%package zsh-completion
Summary: Zsh completion for autorandr
%make_install
install -vDm 644 README.md -t "%{buildroot}/usr/share/doc/%{name}/"
install -vDm 644 contrib/bash_completion/autorandr -t %{buildroot}%{_datadir}/bash-completion/completions/
+install -vDm 644 contrib/fish_completion/autorandr.fish -t %{buildroot}%{_datadir}/fish/vendor_completions.d/
install -vDm 644 contrib/zsh_completion/_autorandr -t %{buildroot}%{_datadir}/zsh/site-functions/
install -vDm 644 autorandr.1 -t %{buildroot}%{_mandir}/man1/
%files bash-completion
%{_datadir}/bash-completion/completions/autorandr
+%files fish-completion
+%{_datadir}/fish/vendor_completions.d/autorandr.fish
+
%files zsh-completion
%{_datadir}/zsh/site-functions/_autorandr
setup(
name='autorandr',
- version='1.13.3.post1',
+ version='1.14.post1',
description='Automatically select a display configuration based on connected devices',
long_description=long_description,