Compare commits
34 Commits
6148d62ba2
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
f26cfd3bb5
|
|||
|
f2ec611c26
|
|||
|
5b64c639ac
|
|||
|
8096a1b2c9
|
|||
|
bb4fdcd936
|
|||
|
d06beedcaa
|
|||
|
dc3f0d6d05
|
|||
|
9e91058ed9
|
|||
|
fbc7454647
|
|||
|
94bc8c251c
|
|||
|
e83cfa3c15
|
|||
|
29c89942ce
|
|||
|
9042aeaa93
|
|||
|
180b16faee
|
|||
|
674ea6d9a6
|
|||
|
9ccdc3430c
|
|||
|
4a22708f52
|
|||
|
128ef14c39
|
|||
|
9def673a2b
|
|||
|
36df9cc6c9
|
|||
|
d97a6e3f16
|
|||
|
e073fc400e
|
|||
|
fefeb242ae
|
|||
|
37b6ce3560
|
|||
|
5c32057c42
|
|||
|
87e5285622
|
|||
|
7e30dfb6f0
|
|||
|
4cc1baf429
|
|||
|
957aed63a8
|
|||
|
59b78ebc5c
|
|||
|
c291e4b6ac
|
|||
|
81c3c9ec3f
|
|||
|
fbc1f18393
|
|||
|
4cad7806ab
|
@@ -16,30 +16,52 @@ set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/liberty/cmake)
|
|||||||
include (AddThreads)
|
include (AddThreads)
|
||||||
|
|
||||||
find_package (PkgConfig REQUIRED)
|
find_package (PkgConfig REQUIRED)
|
||||||
pkg_check_modules (dependencies REQUIRED libpulse x11 xext xextproto dbus-1)
|
pkg_check_modules (x REQUIRED x11 xext xextproto)
|
||||||
|
pkg_check_modules (pulse REQUIRED libpulse)
|
||||||
|
pkg_check_modules (dbus REQUIRED dbus-1)
|
||||||
pkg_check_modules (gdm gdm glib-2.0 gio-2.0)
|
pkg_check_modules (gdm gdm glib-2.0 gio-2.0)
|
||||||
include_directories (${dependencies_INCLUDE_DIRS})
|
include_directories (
|
||||||
|
${x_INCLUDE_DIRS} ${pulse_INCLUDE_DIRS} ${dbus_INCLUDE_DIRS})
|
||||||
|
link_directories (
|
||||||
|
${x_LIBRARY_DIRS} ${pulse_LIBRARY_DIRS} ${dbus_LIBRARY_DIRS})
|
||||||
|
|
||||||
option (WITH_GDM "Compile with GDM support" ${gdm_FOUND})
|
option (WITH_GDM "Compile with GDM utilities" ${gdm_FOUND})
|
||||||
|
|
||||||
# Generate a configuration file
|
# Generate a configuration file
|
||||||
configure_file (${PROJECT_SOURCE_DIR}/config.h.in ${PROJECT_BINARY_DIR}/config.h)
|
configure_file (${PROJECT_SOURCE_DIR}/config.h.in
|
||||||
|
${PROJECT_BINARY_DIR}/config.h)
|
||||||
include_directories (${PROJECT_BINARY_DIR})
|
include_directories (${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
foreach (name brightness fancontrol-ng iexec input-switch priod siprandom)
|
set (targets wmstatus paswitch siprandom genpass)
|
||||||
|
if ("${CMAKE_SYSTEM_NAME}" STREQUAL Linux)
|
||||||
|
# These use Linux i2c APIs, but can be made to work on macOS
|
||||||
|
list (APPEND targets brightness input-switch)
|
||||||
|
# Only iexec could be made to use kqueue
|
||||||
|
list (APPEND targets fancontrol-ng priod iexec)
|
||||||
|
elseif ("${CMAKE_SYSTEM_NAME}" MATCHES BSD)
|
||||||
|
# Need this for SIGWINCH in FreeBSD and OpenBSD respectively;
|
||||||
|
# our POSIX version macros make it undefined
|
||||||
|
add_definitions (-D__BSD_VISIBLE=1 -D_BSD_SOURCE=1)
|
||||||
|
elseif (APPLE)
|
||||||
|
add_definitions (-D_DARWIN_C_SOURCE)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
foreach (name big-brother ${targets})
|
||||||
add_executable (${name} ${name}.c)
|
add_executable (${name} ${name}.c)
|
||||||
endforeach ()
|
endforeach ()
|
||||||
|
|
||||||
foreach (name big-brother paswitch wmstatus)
|
target_link_libraries (big-brother ${x_LIBRARIES})
|
||||||
add_executable (${name} ${name}.c)
|
target_link_libraries (paswitch ${pulse_LIBRARIES})
|
||||||
target_link_libraries (${name} ${dependencies_LIBRARIES})
|
target_link_libraries (wmstatus
|
||||||
endforeach ()
|
${x_LIBRARIES} ${pulse_LIBRARIES} ${dbus_LIBRARIES})
|
||||||
add_threads (wmstatus)
|
add_threads (wmstatus)
|
||||||
|
|
||||||
if (WITH_GDM)
|
if (WITH_GDM)
|
||||||
include_directories (${gdm_INCLUDE_DIRS})
|
list (APPEND targets gdm-switch-user)
|
||||||
add_executable (gdm-switch-user gdm-switch-user.c)
|
add_executable (gdm-switch-user gdm-switch-user.c)
|
||||||
|
target_include_directories (gdm-switch-user PUBLIC ${gdm_INCLUDE_DIRS})
|
||||||
|
target_link_directories (gdm-switch-user PUBLIC ${gdm_LIBRARY_DIRS})
|
||||||
target_link_libraries (gdm-switch-user ${gdm_LIBRARIES})
|
target_link_libraries (gdm-switch-user ${gdm_LIBRARIES})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
@@ -50,28 +72,44 @@ include (GNUInstallDirs)
|
|||||||
set (SYSTEMD_UNITDIR /lib/systemd/system
|
set (SYSTEMD_UNITDIR /lib/systemd/system
|
||||||
CACHE PATH "Base directory for systemd unit files")
|
CACHE PATH "Base directory for systemd unit files")
|
||||||
|
|
||||||
configure_file (${PROJECT_SOURCE_DIR}/fancontrol-ng.service.in
|
if ("${CMAKE_SYSTEM_NAME}" STREQUAL Linux)
|
||||||
${PROJECT_BINARY_DIR}/fancontrol-ng.service @ONLY)
|
configure_file (${PROJECT_SOURCE_DIR}/fancontrol-ng.service.in
|
||||||
install (FILES fancontrol-ng.conf.example
|
${PROJECT_BINARY_DIR}/fancontrol-ng.service @ONLY)
|
||||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/fancontrol-ng)
|
install (FILES fancontrol-ng.conf.example
|
||||||
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/fancontrol-ng)
|
||||||
|
|
||||||
configure_file (${PROJECT_SOURCE_DIR}/priod.service.in
|
configure_file (${PROJECT_SOURCE_DIR}/priod.service.in
|
||||||
${PROJECT_BINARY_DIR}/priod.service @ONLY)
|
${PROJECT_BINARY_DIR}/priod.service @ONLY)
|
||||||
install (FILES priod.conf.example
|
install (FILES priod.conf.example
|
||||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/priod)
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/priod)
|
||||||
|
|
||||||
# System-wide unit files should be installed under /lib and not /usr/lib
|
# System-wide unit files should be installed under /lib and not /usr/lib
|
||||||
install (FILES
|
install (FILES
|
||||||
${PROJECT_BINARY_DIR}/fancontrol-ng.service
|
${PROJECT_BINARY_DIR}/fancontrol-ng.service
|
||||||
${PROJECT_BINARY_DIR}/priod.service
|
${PROJECT_BINARY_DIR}/priod.service
|
||||||
DESTINATION "${SYSTEMD_UNITDIR}")
|
DESTINATION "${SYSTEMD_UNITDIR}")
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (WITH_GDM)
|
if (WITH_GDM)
|
||||||
install (TARGETS gdm-switch-user DESTINATION ${CMAKE_INSTALL_BINDIR})
|
install (TARGETS gdm-switch-user DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
install (TARGETS wmstatus paswitch brightness input-switch fancontrol-ng priod
|
# These should be accessible by users, but need to touch system devices.
|
||||||
iexec siprandom DESTINATION ${CMAKE_INSTALL_BINDIR})
|
# Use the setuid bit, for simplicity.
|
||||||
|
set (SETUID "SETUID" CACHE STRING "Set this empty on permission issues")
|
||||||
|
foreach (target brightness input-switch)
|
||||||
|
if (${target} IN_LIST targets)
|
||||||
|
list (REMOVE_ITEM targets ${target})
|
||||||
|
install (TARGETS ${target} DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
PERMISSIONS
|
||||||
|
OWNER_WRITE OWNER_READ OWNER_EXECUTE
|
||||||
|
GROUP_READ GROUP_EXECUTE
|
||||||
|
WORLD_READ WORLD_EXECUTE
|
||||||
|
${SETUID})
|
||||||
|
endif ()
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
install (TARGETS ${targets} DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
install (PROGRAMS shellify DESTINATION ${CMAKE_INSTALL_BINDIR})
|
install (PROGRAMS shellify DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||||
|
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2015 - 2021, Přemysl Eric Janouch <p@janouch.name>
|
Copyright (c) 2015 - 2025, Přemysl Eric Janouch <p@janouch.name>
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
purpose with or without fee is hereby granted.
|
purpose with or without fee is hereby granted.
|
||||||
|
|||||||
@@ -28,17 +28,17 @@ to other people as well:
|
|||||||
- 'big-brother' tracks the title of the active window and the idle state of
|
- 'big-brother' tracks the title of the active window and the idle state of
|
||||||
the user and writes these events to standard output.
|
the user and writes these events to standard output.
|
||||||
|
|
||||||
Don't expect them to work under any OS that isn't Linux.
|
Few of them are useful outside of Linux.
|
||||||
|
|
||||||
Packages
|
Packages
|
||||||
--------
|
--------
|
||||||
Regular releases are sporadic. git master should be stable enough. You can get
|
Regular releases are sporadic. git master should be stable enough.
|
||||||
a package with the latest development version from Archlinux's AUR.
|
|
||||||
|
|
||||||
Building
|
Building
|
||||||
--------
|
--------
|
||||||
Build dependencies: CMake, pkg-config, liberty (included) +
|
Build dependencies: CMake, pkg-config, liberty (included) +
|
||||||
Runtime dependencies: libpulse, libx11, dbus-1, libgdm (optional)
|
Runtime dependencies: libpulse, libx11, dbus-1 +
|
||||||
|
Optional runtime dependencies: libgdm (gdm-switch-user)
|
||||||
|
|
||||||
$ git clone --recursive https://git.janouch.name/p/desktop-tools.git
|
$ git clone --recursive https://git.janouch.name/p/desktop-tools.git
|
||||||
$ mkdir desktop-tools/build
|
$ mkdir desktop-tools/build
|
||||||
|
|||||||
2
ddc-ci.c
2
ddc-ci.c
@@ -46,7 +46,7 @@ log_message_custom (void *user_data, const char *quote, const char *fmt,
|
|||||||
static void
|
static void
|
||||||
wait_ms (long ms)
|
wait_ms (long ms)
|
||||||
{
|
{
|
||||||
struct timespec ts = { 0, ms * 1000 * 1000 };
|
struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
|
||||||
nanosleep (&ts, NULL);
|
nanosleep (&ts, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ config_validate_nonnegative (const struct config_item *item, struct error **e)
|
|||||||
return error_set (e, "must be non-negative");
|
return error_set (e, "must be non-negative");
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct config_schema g_config_device[] =
|
static const struct config_schema g_config_device[] =
|
||||||
{
|
{
|
||||||
{ .name = "name",
|
{ .name = "name",
|
||||||
.comment = "Device identifier",
|
.comment = "Device identifier",
|
||||||
@@ -137,7 +137,7 @@ static struct config_schema g_config_device[] =
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct config_schema g_config_pwm[] =
|
static const struct config_schema g_config_pwm[] =
|
||||||
{
|
{
|
||||||
{ .name = "temp",
|
{ .name = "temp",
|
||||||
.comment = "Path to temperature sensor output",
|
.comment = "Path to temperature sensor output",
|
||||||
@@ -415,7 +415,7 @@ device_create (struct app_context *ctx, const char *path,
|
|||||||
// There is no room for errors in the configuration, everything must be valid.
|
// There is no room for errors in the configuration, everything must be valid.
|
||||||
// Thus the reset to defaults on invalid values is effectively disabled here.
|
// Thus the reset to defaults on invalid values is effectively disabled here.
|
||||||
static bool
|
static bool
|
||||||
apply_schema (struct config_schema *schema, struct config_item *object,
|
apply_schema (const struct config_schema *schema, struct config_item *object,
|
||||||
struct error **e)
|
struct error **e)
|
||||||
{
|
{
|
||||||
struct error *warning = NULL, *error = NULL;
|
struct error *warning = NULL, *error = NULL;
|
||||||
@@ -445,7 +445,7 @@ static bool
|
|||||||
check_device_configuration (struct config_item *subtree, struct error **e)
|
check_device_configuration (struct config_item *subtree, struct error **e)
|
||||||
{
|
{
|
||||||
// Check regular fields in the device object
|
// Check regular fields in the device object
|
||||||
for (struct config_schema *s = g_config_device; s->name; s++)
|
for (const struct config_schema *s = g_config_device; s->name; s++)
|
||||||
if (!apply_schema (s, subtree, e))
|
if (!apply_schema (s, subtree, e))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -465,7 +465,7 @@ check_device_configuration (struct config_item *subtree, struct error **e)
|
|||||||
while ((pwm = str_map_iter_next (&iter)))
|
while ((pwm = str_map_iter_next (&iter)))
|
||||||
{
|
{
|
||||||
const char *subpath = iter.link->key;
|
const char *subpath = iter.link->key;
|
||||||
for (struct config_schema *s = g_config_pwm; s->name; s++)
|
for (const struct config_schema *s = g_config_pwm; s->name; s++)
|
||||||
if (!apply_schema (s, pwm, &error))
|
if (!apply_schema (s, pwm, &error))
|
||||||
{
|
{
|
||||||
error_set (e, "PWM `%s': %s", subpath, error->message);
|
error_set (e, "PWM `%s': %s", subpath, error->message);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Public domain
|
// Public domain
|
||||||
#include <gdm-user-switching.h>
|
#include <gdm/gdm-user-switching.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
|
|||||||
151
genpass.c
Normal file
151
genpass.c
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* genpass.c: password generator
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025, Přemysl Eric Janouch <p@janouch.name>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#undef PROGRAM_NAME
|
||||||
|
#define PROGRAM_NAME "genpass"
|
||||||
|
#include "liberty/liberty.c"
|
||||||
|
|
||||||
|
static struct str
|
||||||
|
parse_group (const char *group)
|
||||||
|
{
|
||||||
|
bool present[0x100] = {};
|
||||||
|
for (size_t i = 0; group[i]; i++)
|
||||||
|
{
|
||||||
|
unsigned char c = group[i];
|
||||||
|
if (!i || c != '-' || !group[i + 1])
|
||||||
|
present[c] = true;
|
||||||
|
else if (group[i + 1] < group[i - 1])
|
||||||
|
exit_fatal ("character ranges must be increasing");
|
||||||
|
else
|
||||||
|
for (c = group[i - 1]; ++c <= group[i + 1]; )
|
||||||
|
present[c] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct str alphabet = str_make ();
|
||||||
|
for (size_t i = 1; i < N_ELEMENTS (present); i++)
|
||||||
|
if (present[i])
|
||||||
|
str_append_c (&alphabet, i);
|
||||||
|
if (!alphabet.len)
|
||||||
|
exit_fatal ("empty group");
|
||||||
|
return alphabet;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_program_arguments (int argc, char **argv,
|
||||||
|
unsigned long *length, struct strv *groups, struct str *alphabet)
|
||||||
|
{
|
||||||
|
static const struct opt opts[] =
|
||||||
|
{
|
||||||
|
{ 'l', "length", "CHARACTERS", 0, "set password length" },
|
||||||
|
{ 'd', "debug", NULL, 0, "run in debug mode" },
|
||||||
|
{ 'h', "help", NULL, 0, "display this help and exit" },
|
||||||
|
{ 'V', "version", NULL, 0, "output version information and exit" },
|
||||||
|
{ 0, NULL, NULL, 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct opt_handler oh =
|
||||||
|
opt_handler_make (argc, argv, opts, "GROUP...", "Password generator.");
|
||||||
|
|
||||||
|
int c;
|
||||||
|
while ((c = opt_handler_get (&oh)) != -1)
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'l':
|
||||||
|
if (!xstrtoul (length, optarg, 10) || *length <= 0)
|
||||||
|
print_fatal ("invalid length argument");
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
g_debug_mode = true;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
opt_handler_usage (&oh, stdout);
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
case 'V':
|
||||||
|
printf (PROGRAM_NAME " " PROGRAM_VERSION "\n");
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
default:
|
||||||
|
print_error ("wrong options");
|
||||||
|
opt_handler_usage (&oh, stderr);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
struct str alphabet = parse_group (argv[i]);
|
||||||
|
strv_append_owned (groups, str_steal (&alphabet));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool present[0x100] = {};
|
||||||
|
for (size_t i = 0; i < groups->len; i++)
|
||||||
|
for (size_t k = 0; groups->vector[i][k]; k++)
|
||||||
|
{
|
||||||
|
unsigned char c = groups->vector[i][k];
|
||||||
|
if (present[c])
|
||||||
|
exit_fatal ("groups are not disjunct");
|
||||||
|
present[c] = true;
|
||||||
|
}
|
||||||
|
for (size_t i = 1; i < N_ELEMENTS (present); i++)
|
||||||
|
if (present[i])
|
||||||
|
str_append_c (alphabet, i);
|
||||||
|
|
||||||
|
if (groups->len > *length)
|
||||||
|
exit_fatal ("the requested length is less than the number of groups");
|
||||||
|
if (!groups->len)
|
||||||
|
{
|
||||||
|
opt_handler_usage (&oh, stderr);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
opt_handler_free (&oh);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
unsigned long length = 8;
|
||||||
|
struct strv groups = strv_make ();
|
||||||
|
struct str alphabet = str_make ();
|
||||||
|
parse_program_arguments (argc, argv, &length, &groups, &alphabet);
|
||||||
|
|
||||||
|
unsigned seed = 0;
|
||||||
|
if (!random_bytes (&seed, sizeof seed, NULL))
|
||||||
|
exit_fatal ("failed to initialize random numbers");
|
||||||
|
srand (seed);
|
||||||
|
|
||||||
|
// Select from a joined alphabet, but make sure all groups are represented.
|
||||||
|
struct str candidate = str_make ();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
restart:
|
||||||
|
for (size_t i = length; i--; )
|
||||||
|
str_append_c (&candidate, alphabet.str[rand () % alphabet.len]);
|
||||||
|
for (size_t i = 0; i < groups.len; i++)
|
||||||
|
if (!strpbrk (candidate.str, groups.vector[i]))
|
||||||
|
{
|
||||||
|
str_reset (&candidate);
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("%s\n", candidate.str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
121
iexec.c
121
iexec.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* iexec.c: run a program and restart on file change
|
* iexec.c: run a program and restart on file change
|
||||||
*
|
*
|
||||||
* Copyright (c) 2017, Přemysl Eric Janouch <p@janouch.name>
|
* Copyright (c) 2017 - 2023, Přemysl Eric Janouch <p@janouch.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted.
|
* purpose with or without fee is hereby granted.
|
||||||
@@ -24,34 +24,54 @@
|
|||||||
// This can also work on BSD if someone puts in the effort to support kqueue
|
// This can also work on BSD if someone puts in the effort to support kqueue
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
|
|
||||||
static pid_t g_child;
|
static struct
|
||||||
static bool g_restarting = false;
|
{
|
||||||
static int g_inotify_fd, g_inotify_wd;
|
pid_t child; ///< Watched child or 0
|
||||||
|
bool exits; ///< Don't restart child when it exits
|
||||||
|
bool respawn; ///< Respawn child ASAP
|
||||||
|
bool killing; ///< Waiting for child to die
|
||||||
|
int inotify_fd, inotify_wd;
|
||||||
|
}
|
||||||
|
g;
|
||||||
|
|
||||||
|
// Note that this program doesn't queue up file-based restarts
|
||||||
|
static void
|
||||||
|
handle_inotify_event (const struct inotify_event *e, const char *base)
|
||||||
|
{
|
||||||
|
if (e->wd != g.inotify_wd || strcmp (e->name, base))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g.child)
|
||||||
|
{
|
||||||
|
print_debug ("file changed, killing child");
|
||||||
|
if (kill (g.child, SIGINT))
|
||||||
|
print_error ("kill: %s", strerror (errno));
|
||||||
|
g.killing = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print_debug ("file changed, respawning");
|
||||||
|
g.respawn = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_file_change (const char *base)
|
handle_file_change (const char *base)
|
||||||
{
|
{
|
||||||
char buf[4096]; ssize_t len; const struct inotify_event *e;
|
char buf[4096];
|
||||||
while ((len = read (g_inotify_fd, buf, sizeof buf)) > 0)
|
ssize_t len = 0;
|
||||||
for (char *ptr = buf; ptr < buf + len; ptr += sizeof *e + e->len)
|
struct inotify_event *e = NULL;
|
||||||
{
|
while ((len = read (g.inotify_fd, buf, sizeof buf)) > 0)
|
||||||
e = (const struct inotify_event *) buf;
|
for (char *ptr = buf; ptr < buf + len; ptr += sizeof *e + e->len)
|
||||||
if (e->wd != g_inotify_wd || strcmp (e->name, base))
|
handle_inotify_event ((e = (struct inotify_event *) buf), base);
|
||||||
continue;
|
|
||||||
|
|
||||||
print_debug ("file changed, killing child");
|
|
||||||
g_restarting = true;
|
|
||||||
if (kill (g_child, SIGINT))
|
|
||||||
print_error ("kill: %s", strerror (errno));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
spawn (char *argv[])
|
spawn (char *argv[])
|
||||||
{
|
{
|
||||||
if ((g_child = fork ()) == -1)
|
if ((g.child = fork ()) == -1)
|
||||||
exit_fatal ("fork: %s", strerror (errno));
|
exit_fatal ("fork: %s", strerror (errno));
|
||||||
else if (g_child)
|
else if (g.child)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// A linker can create spurious CLOSE_WRITEs, wait until it's executable
|
// A linker can create spurious CLOSE_WRITEs, wait until it's executable
|
||||||
@@ -64,23 +84,22 @@ spawn (char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
check_child_death (char *argv[])
|
check_child_death (void)
|
||||||
{
|
{
|
||||||
if (waitpid (g_child, NULL, WNOHANG) != g_child)
|
int status = 0;
|
||||||
|
if (waitpid (g.child, &status, WNOHANG) != g.child)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!g_restarting)
|
g.child = 0;
|
||||||
|
if (!g.killing)
|
||||||
{
|
{
|
||||||
print_debug ("child died on its own, not respawning");
|
print_debug ("child died on its own, not respawning");
|
||||||
return false;
|
return g.exits;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
print_debug ("child died on request, respawning");
|
|
||||||
spawn (argv);
|
|
||||||
g_restarting = false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g.killing = false;
|
||||||
|
print_debug ("child died on request, respawning");
|
||||||
|
return g.respawn = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -93,8 +112,11 @@ sigchld_handler (int signum)
|
|||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
const char *target = NULL;
|
||||||
static const struct opt opts[] =
|
static const struct opt opts[] =
|
||||||
{
|
{
|
||||||
|
{ 'f', "file", "PATH", 0, "watch this path rather than the program" },
|
||||||
|
{ 'e', "exits", NULL, 0, "allow the program to exit on its own" },
|
||||||
{ 'd', "debug", NULL, 0, "run in debug mode" },
|
{ 'd', "debug", NULL, 0, "run in debug mode" },
|
||||||
{ 'h', "help", NULL, 0, "display this help and exit" },
|
{ 'h', "help", NULL, 0, "display this help and exit" },
|
||||||
{ 'V', "version", NULL, 0, "output version information and exit" },
|
{ 'V', "version", NULL, 0, "output version information and exit" },
|
||||||
@@ -102,7 +124,7 @@ main (int argc, char *argv[])
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct opt_handler oh = opt_handler_make (argc, argv, opts,
|
struct opt_handler oh = opt_handler_make (argc, argv, opts,
|
||||||
"PROGRAM [ARG...]", "Run a program and restart on file change.");
|
"PROGRAM [ARG...]", "Run a program and restart it when it changes.");
|
||||||
|
|
||||||
// We have to turn that off as it causes more trouble than what it's worth
|
// We have to turn that off as it causes more trouble than what it's worth
|
||||||
cstr_set (&oh.opt_string, xstrdup_printf ("+%s", oh.opt_string));
|
cstr_set (&oh.opt_string, xstrdup_printf ("+%s", oh.opt_string));
|
||||||
@@ -111,6 +133,12 @@ main (int argc, char *argv[])
|
|||||||
while ((c = opt_handler_get (&oh)) != -1)
|
while ((c = opt_handler_get (&oh)) != -1)
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
|
case 'f':
|
||||||
|
target = optarg;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
g.exits = true;
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
g_debug_mode = true;
|
g_debug_mode = true;
|
||||||
break;
|
break;
|
||||||
@@ -136,6 +164,9 @@ main (int argc, char *argv[])
|
|||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
|
if (!target)
|
||||||
|
target = argv[0];
|
||||||
|
|
||||||
(void) signal (SIGPIPE, SIG_IGN);
|
(void) signal (SIGPIPE, SIG_IGN);
|
||||||
struct sigaction sa = { .sa_handler = sigchld_handler };
|
struct sigaction sa = { .sa_handler = sigchld_handler };
|
||||||
sigemptyset (&sa.sa_mask);
|
sigemptyset (&sa.sa_mask);
|
||||||
@@ -148,27 +179,33 @@ main (int argc, char *argv[])
|
|||||||
if (sigprocmask (SIG_BLOCK, &chld, &orig))
|
if (sigprocmask (SIG_BLOCK, &chld, &orig))
|
||||||
exit_fatal ("sigprocmask: %s", strerror (errno));
|
exit_fatal ("sigprocmask: %s", strerror (errno));
|
||||||
|
|
||||||
char *path = xstrdup (argv[0]);
|
char *path = NULL;
|
||||||
|
char *dir = dirname ((path = xstrdup (target)));
|
||||||
|
|
||||||
if ((g_inotify_fd = inotify_init1 (IN_NONBLOCK)) < 0)
|
if ((g.inotify_fd = inotify_init1 (IN_NONBLOCK)) < 0)
|
||||||
exit_fatal ("inotify_init1: %s", strerror (errno));
|
exit_fatal ("inotify_init1: %s", strerror (errno));
|
||||||
if ((g_inotify_wd = inotify_add_watch (g_inotify_fd,
|
if ((g.inotify_wd = inotify_add_watch (g.inotify_fd,
|
||||||
dirname (path), IN_MOVED_TO | IN_CLOSE_WRITE)) < 0)
|
dir, IN_MOVED_TO | IN_CLOSE_WRITE)) < 0)
|
||||||
exit_fatal ("inotify_add_watch: %s", strerror (errno));
|
exit_fatal ("inotify_add_watch: %s", strerror (errno));
|
||||||
|
|
||||||
free (path);
|
free (path);
|
||||||
char *base = basename ((path = xstrdup (argv[0])));
|
char *base = basename ((path = xstrdup (target)));
|
||||||
spawn (argv);
|
g.respawn = true;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
fd_set r; FD_SET (g_inotify_fd, &r);
|
if (g.respawn)
|
||||||
(void) pselect (g_inotify_fd + 1, &r, NULL, NULL, NULL, &orig);
|
{
|
||||||
|
spawn (argv);
|
||||||
|
g.respawn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd_set r; FD_SET (g.inotify_fd, &r);
|
||||||
|
(void) pselect (g.inotify_fd + 1, &r, NULL, NULL, NULL, &orig);
|
||||||
handle_file_change (base);
|
handle_file_change (base);
|
||||||
}
|
}
|
||||||
while (check_child_death (argv));
|
while (check_child_death ());
|
||||||
|
|
||||||
free (path);
|
free (path);
|
||||||
close (g_inotify_fd);
|
xclose (g.inotify_fd);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* input-switch.c: switches display input via DDC/CI
|
* input-switch.c: switches display input via DDC/CI
|
||||||
*
|
*
|
||||||
* Copyright (c) 2017, Přemysl Eric Janouch <p@janouch.name>
|
* Copyright (c) 2017 - 2022, Přemysl Eric Janouch <p@janouch.name>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted.
|
* purpose with or without fee is hereby granted.
|
||||||
@@ -28,10 +28,59 @@
|
|||||||
#include "ddc-ci.c"
|
#include "ddc-ci.c"
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
|
// This list is from the MCCS 2.2a specification
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int code; ///< Input code
|
||||||
|
const char *name; ///< Input name
|
||||||
|
int index; ///< Input index
|
||||||
|
}
|
||||||
|
g_inputs[] =
|
||||||
|
{
|
||||||
|
{ 0x01, "VGA", 1, }, // Analog video (R/G/B) 1
|
||||||
|
{ 0x02, "VGA", 2, }, // Analog video (R/G/B) 2
|
||||||
|
{ 0x03, "DVI", 1, }, // Digital video (TMDS) 1 DVI 1
|
||||||
|
{ 0x04, "DVI", 2, }, // Digital video (TMDS) 2 DVI 2
|
||||||
|
{ 0x05, "composite", 1, }, // Composite video 1
|
||||||
|
{ 0x06, "composite", 2, }, // Composite video 2
|
||||||
|
{ 0x07, "S-Video", 1, }, // S-video 1
|
||||||
|
{ 0x08, "S-Video", 2, }, // S-video 2
|
||||||
|
{ 0x09, "tuner", 1, }, // Tuner 1
|
||||||
|
{ 0x0A, "tuner", 2, }, // Tuner 2
|
||||||
|
{ 0x0B, "tuner", 3, }, // Tuner 3
|
||||||
|
{ 0x0C, "component", 1, }, // Component video (YPbPr/YCbCr) 1
|
||||||
|
{ 0x0D, "component", 2, }, // Component video (YPbPr/YCbCr) 2
|
||||||
|
{ 0x0E, "component", 3, }, // Component video (YPbPr/YCbCr) 3
|
||||||
|
{ 0x0F, "DP", 1, }, // DisplayPort 1
|
||||||
|
{ 0x10, "DP", 2, }, // DisplayPort 2
|
||||||
|
{ 0x11, "HDMI", 1, }, // Digital Video (TMDS) 3 HDMI 1
|
||||||
|
{ 0x12, "HDMI", 2, }, // Digital Video (TMDS) 4 HDMI 2
|
||||||
|
{ 0x15, "bnq-tb", 1, }, // Thunderbolt on BenQ PD3220U (no spec)
|
||||||
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
typedef bool (*ActionFunc) (int fd, int param, struct error **);
|
typedef bool (*ActionFunc) (int fd, int param, struct error **);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
get_input_source (int fd, int input, struct error **e)
|
||||||
|
{
|
||||||
|
struct vcp_feature_readout readout = {};
|
||||||
|
if (!vcp_get_feature (fd, VCP_INPUT_SOURCE, &readout, e))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
(void) input;
|
||||||
|
for (size_t i = 0; i < N_ELEMENTS (g_inputs); i++)
|
||||||
|
if (g_inputs[i].code == readout.cur)
|
||||||
|
{
|
||||||
|
printf ("input is %s %d\n", g_inputs[i].name, g_inputs[i].index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("input is %d\n", readout.cur);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
set_input_source (int fd, int input, struct error **e)
|
set_input_source (int fd, int input, struct error **e)
|
||||||
{
|
{
|
||||||
@@ -114,36 +163,6 @@ i2c (ActionFunc action, int param)
|
|||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
// This list is from the MCCS 2.2a specification
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
int code; ///< Input code
|
|
||||||
const char *name; ///< Input name
|
|
||||||
int index; ///< Input index
|
|
||||||
}
|
|
||||||
g_inputs[] =
|
|
||||||
{
|
|
||||||
{ 0x01, "vga", 1, }, // Analog video (R/G/B) 1
|
|
||||||
{ 0x02, "vga", 2, }, // Analog video (R/G/B) 2
|
|
||||||
{ 0x03, "dvi", 1, }, // Digital video (TMDS) 1 DVI 1
|
|
||||||
{ 0x04, "dvi", 2, }, // Digital video (TMDS) 2 DVI 2
|
|
||||||
{ 0x05, "composite", 1, }, // Composite video 1
|
|
||||||
{ 0x06, "composite", 2, }, // Composite video 2
|
|
||||||
{ 0x07, "s-video", 1, }, // S-video 1
|
|
||||||
{ 0x08, "s-video", 2, }, // S-video 2
|
|
||||||
{ 0x09, "tuner", 1, }, // Tuner 1
|
|
||||||
{ 0x0A, "tuner", 2, }, // Tuner 2
|
|
||||||
{ 0x0B, "tuner", 3, }, // Tuner 3
|
|
||||||
{ 0x0C, "component", 1, }, // Component video (YPbPr/YCbCr) 1
|
|
||||||
{ 0x0D, "component", 2, }, // Component video (YPbPr/YCbCr) 2
|
|
||||||
{ 0x0E, "component", 3, }, // Component video (YPbPr/YCbCr) 3
|
|
||||||
{ 0x0F, "dp", 1, }, // DisplayPort 1
|
|
||||||
{ 0x10, "dp", 2, }, // DisplayPort 2
|
|
||||||
{ 0x11, "hdmi", 1, }, // Digital Video (TMDS) 3 HDMI 1
|
|
||||||
{ 0x12, "hdmi", 2, }, // Digital Video (TMDS) 4 HDMI 2
|
|
||||||
{ 0x15, "bnq-tb", 1, }, // Thunderbolt on BenQ PD3220U (no spec)
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@@ -151,9 +170,14 @@ main (int argc, char *argv[])
|
|||||||
|
|
||||||
if (argc <= 1)
|
if (argc <= 1)
|
||||||
{
|
{
|
||||||
printf ("Usage: %s <input> [<index>]\n", argv[0]);
|
printf ("Usage: %s {? | INPUT [INDEX]}\n", argv[0]);
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
if (!strcmp (argv[1], "?"))
|
||||||
|
{
|
||||||
|
i2c (get_input_source, -1);
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long input_source = 0;
|
unsigned long input_source = 0;
|
||||||
if (xstrtoul (&input_source, argv[1], 10))
|
if (xstrtoul (&input_source, argv[1], 10))
|
||||||
|
|||||||
2
liberty
2
liberty
Submodule liberty updated: 782a9a5977...75fc6f1c37
@@ -290,7 +290,7 @@ on_sink_info (pa_context *context, const pa_sink_info *info, int eol,
|
|||||||
sink->ports_len++;
|
sink->ports_len++;
|
||||||
|
|
||||||
struct port *port = sink->ports =
|
struct port *port = sink->ports =
|
||||||
xcalloc (sizeof *sink->ports, sink->ports_len);
|
xcalloc (sink->ports_len, sizeof *sink->ports);
|
||||||
for (struct pa_sink_port_info **iter = info->ports; *iter; iter++)
|
for (struct pa_sink_port_info **iter = info->ports; *iter; iter++)
|
||||||
{
|
{
|
||||||
port->name = xstrdup ((*iter)->name);
|
port->name = xstrdup ((*iter)->name);
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ my %legends;
|
|||||||
sub retrieve_legends {
|
sub retrieve_legends {
|
||||||
# HTTP/Tiny supports TLS, but with non-core IO::Socket::SSL, so use cURL
|
# HTTP/Tiny supports TLS, but with non-core IO::Socket::SSL, so use cURL
|
||||||
open(my $sock, '-|', 'curl', '-sSA', $agent,
|
open(my $sock, '-|', 'curl', '-sSA', $agent,
|
||||||
"$base/weathericon/2.0/legends.txt") or return $!;
|
'https://raw.githubusercontent.com/' .
|
||||||
|
'metno/weathericons/main/weather/legend.csv') or return $!;
|
||||||
while (local $_ = <$sock>) { $legends{$1} = $2 if /^(.+?),(.+?),/ }
|
while (local $_ = <$sock>) { $legends{$1} = $2 if /^(.+?),(.+?),/ }
|
||||||
close($sock);
|
close($sock);
|
||||||
}
|
}
|
||||||
|
|||||||
1062
wmstatus.c
1062
wmstatus.c
File diff suppressed because it is too large
Load Diff
63
wmstatus.conf.example
Normal file
63
wmstatus.conf.example
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# vim: set ft=libertyconf:
|
||||||
|
keys = {
|
||||||
|
# This key should be labeled L on normal Qwert[yz] layouts
|
||||||
|
"Mod4 n" = "exec dm-tool lock" # gdm-switch-user
|
||||||
|
|
||||||
|
# xmodmap grep -e Alt_R -e Meta_R -e ISO_Level3_Shift -e Mode_switch
|
||||||
|
# can be used to figure out which modifier is AltGr
|
||||||
|
|
||||||
|
"Mod4 Up" = "mpd-play-toggle"
|
||||||
|
"Mod4 Down" = "mpd stop"
|
||||||
|
"Mod4 Left" = "mpd previous"
|
||||||
|
"Mod4 Right" = "mpd next"
|
||||||
|
"Mod4 Shift Left" = "mpd seekcur -10"
|
||||||
|
"Mod4 Shift Right" = "mpd seekcur +10"
|
||||||
|
"XF86AudioPlay" = "mpd-play-toggle"
|
||||||
|
"XF86AudioPrev" = "mpd previous"
|
||||||
|
"XF86AudioNext" = "mpd next"
|
||||||
|
|
||||||
|
"Mod4 F1" = "xkb-lock-group 0"
|
||||||
|
"Mod4 F2" = "xkb-lock-group 1"
|
||||||
|
"Mod4 F3" = "xkb-lock-group 2"
|
||||||
|
"Mod4 F4" = "xkb-lock-group 3"
|
||||||
|
|
||||||
|
"Mod4 Control F1" = "exec input-switch vga 1"
|
||||||
|
"Mod4 Control Shift F1" = "exec input-switch vga 2"
|
||||||
|
"Mod4 Control F2" = "exec input-switch dvi 1"
|
||||||
|
"Mod4 Control Shift F2" = "exec input-switch dvi 2"
|
||||||
|
"Mod4 Control F3" = "exec input-switch hdmi 1"
|
||||||
|
"Mod4 Control Shift F3" = "exec input-switch hdmi 2"
|
||||||
|
"Mod4 Control F4" = "exec input-switch dp 1"
|
||||||
|
"Mod4 Control Shift F4" = "exec input-switch dp 2"
|
||||||
|
|
||||||
|
"Mod4 Home" = "exec brightness +10"
|
||||||
|
"Mod4 End" = "exec brightness -10"
|
||||||
|
"XF86MonBrightnessUp" = "exec brightness +10"
|
||||||
|
"XF86MonBrightnessDown" = "exec brightness -10"
|
||||||
|
|
||||||
|
# We need to wait a little while until user releases the key
|
||||||
|
"Mod4 F5" = "exec sh -c 'sleep 1; xset dpms force standby'"
|
||||||
|
"Mod4 Shift F5" = "insomnia"
|
||||||
|
"Mod4 Pause" = "exec sh -c 'sleep 1; xset dpms force standby'"
|
||||||
|
"Mod4 Shift Pause" = "insomnia"
|
||||||
|
|
||||||
|
"Mod4 Insert" = "audio-switch"
|
||||||
|
"Mod4 Delete" = "audio-mute"
|
||||||
|
"Mod4 Shift Delete" = "audio-mic-mute"
|
||||||
|
"Mod4 Page_Up" = "audio-volume +5"
|
||||||
|
"Mod4 Shift Page_Up" = "audio-volume +1"
|
||||||
|
"Mod4 Page_Down" = "audio-volume -5"
|
||||||
|
"Mod4 Shift Page_Down" = "audio-volume -1"
|
||||||
|
" XF86AudioRaiseVolume" = "audio-volume +5"
|
||||||
|
"Shift XF86AudioRaiseVolume" = "audio-volume +1"
|
||||||
|
" XF86AudioLowerVolume" = "audio-volume -5"
|
||||||
|
"Shift XF86AudioLowerVolume" = "audio-volume -1"
|
||||||
|
" XF86AudioMute" = "audio-mute"
|
||||||
|
" XF86AudioMicMute" = "audio-mic-mute"
|
||||||
|
|
||||||
|
"Control XF86AudioRaiseVolume" = "noise-adjust +1"
|
||||||
|
"Control XF86AudioLowerVolume" = "noise-adjust -1"
|
||||||
|
|
||||||
|
# Turns on or off Pioneer integrated amplifiers
|
||||||
|
"Mod4 Control Delete" = "exec elksmart-comm --nec A538"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user