Compare commits
11 Commits
29c89942ce
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
f26cfd3bb5
|
|||
|
f2ec611c26
|
|||
|
5b64c639ac
|
|||
|
8096a1b2c9
|
|||
|
bb4fdcd936
|
|||
|
d06beedcaa
|
|||
|
dc3f0d6d05
|
|||
|
9e91058ed9
|
|||
|
fbc7454647
|
|||
|
94bc8c251c
|
|||
|
e83cfa3c15
|
@@ -25,7 +25,7 @@ include_directories (
|
|||||||
link_directories (
|
link_directories (
|
||||||
${x_LIBRARY_DIRS} ${pulse_LIBRARY_DIRS} ${dbus_LIBRARY_DIRS})
|
${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
|
configure_file (${PROJECT_SOURCE_DIR}/config.h.in
|
||||||
@@ -33,7 +33,7 @@ configure_file (${PROJECT_SOURCE_DIR}/config.h.in
|
|||||||
include_directories (${PROJECT_BINARY_DIR})
|
include_directories (${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
set (targets wmstatus paswitch siprandom)
|
set (targets wmstatus paswitch siprandom genpass)
|
||||||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL Linux)
|
if ("${CMAKE_SYSTEM_NAME}" STREQUAL Linux)
|
||||||
# These use Linux i2c APIs, but can be made to work on macOS
|
# These use Linux i2c APIs, but can be made to work on macOS
|
||||||
list (APPEND targets brightness input-switch)
|
list (APPEND targets brightness input-switch)
|
||||||
@@ -58,9 +58,10 @@ target_link_libraries (wmstatus
|
|||||||
add_threads (wmstatus)
|
add_threads (wmstatus)
|
||||||
|
|
||||||
if (WITH_GDM)
|
if (WITH_GDM)
|
||||||
include_directories (${gdm_INCLUDE_DIRS})
|
list (APPEND targets gdm-switch-user)
|
||||||
link_directories (${gdm_LIBRARY_DIRS})
|
|
||||||
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 ()
|
||||||
|
|
||||||
@@ -95,6 +96,7 @@ endif ()
|
|||||||
|
|
||||||
# These should be accessible by users, but need to touch system devices.
|
# These should be accessible by users, but need to touch system devices.
|
||||||
# Use the setuid bit, for simplicity.
|
# Use the setuid bit, for simplicity.
|
||||||
|
set (SETUID "SETUID" CACHE STRING "Set this empty on permission issues")
|
||||||
foreach (target brightness input-switch)
|
foreach (target brightness input-switch)
|
||||||
if (${target} IN_LIST targets)
|
if (${target} IN_LIST targets)
|
||||||
list (REMOVE_ITEM targets ${target})
|
list (REMOVE_ITEM targets ${target})
|
||||||
@@ -103,7 +105,7 @@ foreach (target brightness input-switch)
|
|||||||
OWNER_WRITE OWNER_READ OWNER_EXECUTE
|
OWNER_WRITE OWNER_READ OWNER_EXECUTE
|
||||||
GROUP_READ GROUP_EXECUTE
|
GROUP_READ GROUP_EXECUTE
|
||||||
WORLD_READ WORLD_EXECUTE
|
WORLD_READ WORLD_EXECUTE
|
||||||
SETUID)
|
${SETUID})
|
||||||
endif ()
|
endif ()
|
||||||
endforeach ()
|
endforeach ()
|
||||||
|
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2015 - 2024, 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.
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ Regular releases are sporadic. git master should be stable enough.
|
|||||||
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);
|
||||||
|
|||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
99
wmstatus.c
99
wmstatus.c
@@ -809,10 +809,10 @@ static const struct config_schema g_config_general[] =
|
|||||||
|
|
||||||
static const struct config_schema g_config_mpd[] =
|
static const struct config_schema g_config_mpd[] =
|
||||||
{
|
{
|
||||||
|
// XXX: We might want to allow config item defaults to not disable nulls.
|
||||||
{ .name = "address",
|
{ .name = "address",
|
||||||
.comment = "MPD host or socket",
|
.comment = "MPD host or socket",
|
||||||
.type = CONFIG_ITEM_STRING,
|
.type = CONFIG_ITEM_STRING },
|
||||||
.default_ = "\"localhost\"" },
|
|
||||||
{ .name = "service",
|
{ .name = "service",
|
||||||
.comment = "MPD service name or port",
|
.comment = "MPD service name or port",
|
||||||
.type = CONFIG_ITEM_STRING,
|
.type = CONFIG_ITEM_STRING,
|
||||||
@@ -1809,8 +1809,12 @@ mpd_on_io_hook (void *user_data, bool outgoing, const char *line)
|
|||||||
static void
|
static void
|
||||||
on_mpd_reconnect (void *user_data)
|
on_mpd_reconnect (void *user_data)
|
||||||
{
|
{
|
||||||
// FIXME: the user should be able to disable MPD
|
|
||||||
struct app_context *ctx = user_data;
|
struct app_context *ctx = user_data;
|
||||||
|
struct config_item *root = ctx->config.root;
|
||||||
|
const char *address = get_config_string (root, "mpd.address");
|
||||||
|
const char *service = get_config_string (root, "mpd.service");
|
||||||
|
if (!address)
|
||||||
|
return;
|
||||||
|
|
||||||
struct mpd_client *c = &ctx->mpd_client;
|
struct mpd_client *c = &ctx->mpd_client;
|
||||||
c->user_data = ctx;
|
c->user_data = ctx;
|
||||||
@@ -1820,10 +1824,7 @@ on_mpd_reconnect (void *user_data)
|
|||||||
c->on_io_hook = mpd_on_io_hook;
|
c->on_io_hook = mpd_on_io_hook;
|
||||||
|
|
||||||
struct error *e = NULL;
|
struct error *e = NULL;
|
||||||
struct config_item *root = ctx->config.root;
|
if (!mpd_client_connect (&ctx->mpd_client, address, service, &e))
|
||||||
if (!mpd_client_connect (&ctx->mpd_client,
|
|
||||||
get_config_string (root, "mpd.address"),
|
|
||||||
get_config_string (root, "mpd.service"), &e))
|
|
||||||
{
|
{
|
||||||
print_error ("%s: %s", "cannot connect to MPD", e->message);
|
print_error ("%s: %s", "cannot connect to MPD", e->message);
|
||||||
error_free (e);
|
error_free (e);
|
||||||
@@ -2249,7 +2250,7 @@ action_noise_adjust (struct app_context *ctx, const struct strv *args)
|
|||||||
long arg = strtol (args->vector[0], NULL, 10);
|
long arg = strtol (args->vector[0], NULL, 10);
|
||||||
ctx->noise_fadeout_samples = 0;
|
ctx->noise_fadeout_samples = 0;
|
||||||
ctx->noise_fadeout_iterator = 0;
|
ctx->noise_fadeout_iterator = 0;
|
||||||
if (!ctx->noise_end_time && (arg < 0 || !noise_start (ctx)))
|
if (!ctx->noise_end_time && (arg <= 0 || !noise_start (ctx)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
time_t now = time (NULL);
|
time_t now = time (NULL);
|
||||||
@@ -2581,7 +2582,7 @@ action_xkb_lock_group (struct app_context *ctx, const struct strv *args)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
long group = strtol (args->vector[0], NULL, 10) - 1;
|
long group = strtol (args->vector[0], NULL, 10);
|
||||||
if (group < XkbGroup1Index || group > XkbGroup4Index)
|
if (group < XkbGroup1Index || group > XkbGroup4Index)
|
||||||
print_warning ("invalid XKB group index: %s", args->vector[0]);
|
print_warning ("invalid XKB group index: %s", args->vector[0]);
|
||||||
else
|
else
|
||||||
@@ -2701,14 +2702,14 @@ parse_key_modifier (const char *modifier, unsigned *mods)
|
|||||||
}
|
}
|
||||||
modifiers[] =
|
modifiers[] =
|
||||||
{
|
{
|
||||||
{"Shift", ShiftMask},
|
{ "Shift", ShiftMask },
|
||||||
{"Lock", LockMask},
|
{ "Lock", LockMask },
|
||||||
{"Control", ControlMask},
|
{ "Control", ControlMask },
|
||||||
{"Mod1", Mod1Mask},
|
{ "Mod1", Mod1Mask },
|
||||||
{"Mod2", Mod2Mask},
|
{ "Mod2", Mod2Mask },
|
||||||
{"Mod3", Mod3Mask},
|
{ "Mod3", Mod3Mask },
|
||||||
{"Mod4", Mod4Mask},
|
{ "Mod4", Mod4Mask },
|
||||||
{"Mod5", Mod5Mask},
|
{ "Mod5", Mod5Mask },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t k = 0; k < N_ELEMENTS (modifiers); k++)
|
for (size_t k = 0; k < N_ELEMENTS (modifiers); k++)
|
||||||
@@ -3039,6 +3040,30 @@ sway_append_command_argument (struct str *out, const char *word)
|
|||||||
str_append_c (out, '\'');
|
str_append_c (out, '\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
sway_shell_command_for_action (const struct strv *args)
|
||||||
|
{
|
||||||
|
// The i3/Sway quoting is properly fucked up,
|
||||||
|
// and its exec command forwards to `sh -c`.
|
||||||
|
struct str shell_command = str_make ();
|
||||||
|
if (strcmp (args->vector[0], "exec"))
|
||||||
|
{
|
||||||
|
// argv[0] would need realpath() applied on it.
|
||||||
|
shell_quote (PROGRAM_NAME, &shell_command);
|
||||||
|
str_append (&shell_command, " -- ");
|
||||||
|
shell_quote (args->vector[0], &shell_command);
|
||||||
|
str_append_c (&shell_command, ' ');
|
||||||
|
}
|
||||||
|
for (size_t i = 1; i < args->len; i++)
|
||||||
|
{
|
||||||
|
shell_quote (args->vector[i], &shell_command);
|
||||||
|
str_append_c (&shell_command, ' ');
|
||||||
|
}
|
||||||
|
if (shell_command.len)
|
||||||
|
shell_command.str[--shell_command.len] = 0;
|
||||||
|
return str_steal (&shell_command);
|
||||||
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
sway_bindsym (const char *combination, const char *action)
|
sway_bindsym (const char *combination, const char *action)
|
||||||
{
|
{
|
||||||
@@ -3063,25 +3088,6 @@ sway_bindsym (const char *combination, const char *action)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The i3/Sway quoting is properly fucked up,
|
|
||||||
// and its exec command forwards to `sh -c`.
|
|
||||||
struct str shell_command = str_make ();
|
|
||||||
if (strcmp (handler.name, "exec"))
|
|
||||||
{
|
|
||||||
// argv[0] would need realpath() applied on it.
|
|
||||||
shell_quote (PROGRAM_NAME, &shell_command);
|
|
||||||
str_append (&shell_command, " -- ");
|
|
||||||
shell_quote (handler.name, &shell_command);
|
|
||||||
str_append_c (&shell_command, ' ');
|
|
||||||
}
|
|
||||||
for (size_t i = 1; i < args.len; i++)
|
|
||||||
{
|
|
||||||
shell_quote (args.vector[i], &shell_command);
|
|
||||||
str_append_c (&shell_command, ' ');
|
|
||||||
}
|
|
||||||
if (shell_command.len)
|
|
||||||
shell_command.str[--shell_command.len] = 0;
|
|
||||||
|
|
||||||
// This command name may not be quoted.
|
// This command name may not be quoted.
|
||||||
// Note that i3-msg doesn't accept bindsym at all, only swaymsg does.
|
// Note that i3-msg doesn't accept bindsym at all, only swaymsg does.
|
||||||
struct str sway_command = str_make ();
|
struct str sway_command = str_make ();
|
||||||
@@ -3089,9 +3095,24 @@ sway_bindsym (const char *combination, const char *action)
|
|||||||
char *recombined = strv_join (&keys, "+");
|
char *recombined = strv_join (&keys, "+");
|
||||||
sway_append_command_argument (&sway_command, recombined);
|
sway_append_command_argument (&sway_command, recombined);
|
||||||
free (recombined);
|
free (recombined);
|
||||||
sway_append_command_argument (&sway_command, "exec");
|
|
||||||
sway_append_command_argument (&sway_command, shell_command.str);
|
if (handler.handler == action_xkb_lock_group)
|
||||||
str_free (&shell_command);
|
{
|
||||||
|
// This should also switch the XWayland layout,
|
||||||
|
// though it has been observed to not take effect immediately.
|
||||||
|
sway_append_command_argument (&sway_command, "input");
|
||||||
|
sway_append_command_argument (&sway_command, "type:keyboard");
|
||||||
|
sway_append_command_argument (&sway_command, "xkb_switch_layout");
|
||||||
|
for (size_t i = 1; i < args.len; i++)
|
||||||
|
sway_append_command_argument (&sway_command, args.vector[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sway_append_command_argument (&sway_command, "exec");
|
||||||
|
char *shell_command = sway_shell_command_for_action (&args);
|
||||||
|
sway_append_command_argument (&sway_command, shell_command);
|
||||||
|
free (shell_command);
|
||||||
|
}
|
||||||
|
|
||||||
struct strv argv = strv_make ();
|
struct strv argv = strv_make ();
|
||||||
strv_append (&argv, "swaymsg");
|
strv_append (&argv, "swaymsg");
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ keys = {
|
|||||||
"XF86AudioPrev" = "mpd previous"
|
"XF86AudioPrev" = "mpd previous"
|
||||||
"XF86AudioNext" = "mpd next"
|
"XF86AudioNext" = "mpd next"
|
||||||
|
|
||||||
"Mod4 F1" = "xkb-lock-group 1"
|
"Mod4 F1" = "xkb-lock-group 0"
|
||||||
"Mod4 F2" = "xkb-lock-group 2"
|
"Mod4 F2" = "xkb-lock-group 1"
|
||||||
"Mod4 F3" = "xkb-lock-group 3"
|
"Mod4 F3" = "xkb-lock-group 2"
|
||||||
"Mod4 F4" = "xkb-lock-group 4"
|
"Mod4 F4" = "xkb-lock-group 3"
|
||||||
|
|
||||||
"Mod4 Control F1" = "exec input-switch vga 1"
|
"Mod4 Control F1" = "exec input-switch vga 1"
|
||||||
"Mod4 Control Shift F1" = "exec input-switch vga 2"
|
"Mod4 Control Shift F1" = "exec input-switch vga 2"
|
||||||
@@ -57,4 +57,7 @@ keys = {
|
|||||||
|
|
||||||
"Control XF86AudioRaiseVolume" = "noise-adjust +1"
|
"Control XF86AudioRaiseVolume" = "noise-adjust +1"
|
||||||
"Control XF86AudioLowerVolume" = "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