add river-control-unstable-v1 support
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
#include "output.h"
|
||||
#include "seat.h"
|
||||
|
||||
#include "river-control-unstable-v1.h"
|
||||
|
||||
/**
|
||||
* ISO C forbids casting a function pointer to a void pointer because on some
|
||||
* architectures they have different sizes. However scm_c_define_gsubr() wants
|
||||
@@ -155,6 +157,72 @@ static SCM install_handler (SCM key, SCM proc)
|
||||
return SCM_BOOL_T;
|
||||
}
|
||||
|
||||
static SCM riverctl (SCM first, SCM rest)
|
||||
{
|
||||
if ( context.river_control == NULL )
|
||||
{
|
||||
fputs("ERROR: User script attempts to send river command but river-control-unstable-v1 not available.\n", stderr);
|
||||
fputs("INFO: This error is not fatal, however riverguile will not be able to send any commands to river.\n", stderr);
|
||||
return SCM_BOOL_F;
|
||||
}
|
||||
if ( wl_list_length(&context.seats) == 0 )
|
||||
{
|
||||
fputs("ERROR: User script attempts to send river command but server did not advertise any seats.\n", stderr);
|
||||
fputs("INFO: This error is not fatal, however riverguile will not be able to send any commands to river.\n", stderr);
|
||||
return SCM_BOOL_F;
|
||||
}
|
||||
|
||||
if ( scm_is_string(first) != 1 )
|
||||
goto error;
|
||||
|
||||
assert(scm_is_true(scm_list_p(rest)) == 1);
|
||||
const uint32_t rest_len = scm_to_uint32(scm_length(rest));
|
||||
for (uint32_t i = 0; i < rest_len; i++)
|
||||
if ( scm_is_string(scm_list_ref(rest, scm_from_uint32(i))) != 1 )
|
||||
goto error;
|
||||
|
||||
char *first_owned = scm_to_utf8_stringn(first, 0);
|
||||
zriver_control_v1_add_argument(context.river_control, first_owned);
|
||||
free(first_owned);
|
||||
|
||||
for (uint32_t i = 0; i < rest_len; i++)
|
||||
{
|
||||
char *owned = scm_to_utf8_stringn(scm_list_ref(rest, scm_from_uint32(i)), 0);
|
||||
zriver_control_v1_add_argument(context.river_control, owned);
|
||||
free(owned);
|
||||
}
|
||||
|
||||
/* Just use the first seat. River only supports a single one anyway. */
|
||||
struct Seat *seat;
|
||||
wl_list_for_each(seat, &context.seats, link)
|
||||
break;
|
||||
|
||||
/* While river does tell us about the status of the command, I do not
|
||||
* want to make use of that in riverguile for multiple reasons.
|
||||
* For one, the reporting is of course async, meaning we could not raise
|
||||
* a guile error in response to failed commands, even if we wanted to.
|
||||
* Riverguile could allow to install a handler for the callback, however
|
||||
* I do not sett the use. There are two riverctl commands that return
|
||||
* useful data as a string, however using that for scripting would be
|
||||
* very hacky and I prefer dedicated well designed interfaces. So we
|
||||
* just destroy the callback before it even fires.
|
||||
*/
|
||||
zriver_command_callback_v1_destroy(
|
||||
zriver_control_v1_run_command(context.river_control, seat->wl_seat)
|
||||
);
|
||||
|
||||
return SCM_BOOL_T;
|
||||
error:
|
||||
scm_error_scm(
|
||||
scm_from_utf8_symbol("wrong-type-arg"),
|
||||
scm_from_utf8_string("riverctl"),
|
||||
scm_from_utf8_string("All arguments must be strings."),
|
||||
SCM_BOOL_F,
|
||||
SCM_BOOL_F
|
||||
);
|
||||
return SCM_UNSPECIFIED;
|
||||
}
|
||||
|
||||
static void *load_script_inner (void *data)
|
||||
{
|
||||
const char *path = (char *)data;
|
||||
@@ -172,6 +240,7 @@ void *load_script (void *data)
|
||||
/* Note: All guile objects are garbage collected. */
|
||||
|
||||
scm_c_define_gsubr_fix("install-handler", 2, 0, 0, install_handler);
|
||||
scm_c_define_gsubr_fix("riverctl", 1, 0, 1, riverctl);
|
||||
|
||||
/* Continuation barrier causes stack unwind on exceptions to stop here.
|
||||
* Otherwise the entire stack created by scm_with_guile() would be
|
||||
|
||||
Reference in New Issue
Block a user