add new-output handler

This commit is contained in:
Leon Henrik Plickat
2024-03-21 03:40:46 +01:00
parent a5b129d637
commit 744ce4b1eb
8 changed files with 116 additions and 2 deletions

View File

@@ -20,6 +20,7 @@ OBJ=src/riverguile.o $\
src/call-user-command-handler.o $\
src/call-idle-handler.o $\
src/call-exit-handler.o $\
src/call-new-output-handler.o $\
src/load-script.o $\
protocol/river-layout-v3.o $\
protocol/ext-idle-notify-v1.o $\

View File

@@ -201,10 +201,35 @@ As of now, river only supports a single seat anyway.
.RE
.
.P
\fBnew-output\fR
.RE
.RS
A handler installed under this key will be called everytime a new output appears.
On binding, it is also called for all outputs that already exist at that time.
.P
Installing a new-output handler will cause riverguile to run continously.
.P
The handler procderure must accept a single argument, the global name of the
output (integer).
.P
Here is an example of a simple new-output handler which merely logs new outputs:
.P
.RS
.EX
(\fBinstall-handler\fR 'new-output
(\fBlambda\fR (output)
(\fBdisplay\fR "New output: ")
(\fBdisplay\fR output)
(\fBnewline\fR)))
.EE
.RE
.RE
.
.P
\fBexit\fR
.RE
.RS
This key allows you to installs a handler which is called when riverguile exits.
This key allows you to install a handler which is called when riverguile exits.
.P
The procedure takes no arguments.
.P

View File

@@ -0,0 +1,36 @@
#include <assert.h>
#include <libguile.h>
#include "output.h"
#include "riverguile.h"
#include "call-new-output-handler.h"
static void *call_new_output_handler_inner (void *data)
{
struct Call_new_output_handler_parameters *params = (struct Call_new_output_handler_parameters *)data;
return scm_call_1(
context.new_output_handler,
scm_from_uint32(params->output->name)
);
}
void *call_new_output_handler (void *data)
{
assert(context.new_output_handler != NULL);
assert(scm_is_true(scm_procedure_p(context.new_output_handler)) == 1);
/* Continuation barrier causes stack unwind on exceptions (i.e. errors
* in the user defined new-output handler) to stop here. Otherwise
* the entire stack created by scm_with_guile() would be unwound. This
* makes responding to exceptions nicer.
*/
SCM call_result = scm_c_with_continuation_barrier(
call_new_output_handler_inner, data
);
if ( call_result == NULL )
return (void *)"ERROR: An exception occured while calling the user-command handler.\n";
return NULL;
}

View File

@@ -0,0 +1,11 @@
#ifndef RIVERGUILE_CALL_NEW_OUTPUT_HANDLER_H
#define RIVERGUILE_CALL_NEW_OUTPUT_HANDLER_H
struct Call_new_output_handler_parameters
{
struct Output *output;
};
void *call_new_output_handler (void *data);
#endif

View File

@@ -9,6 +9,7 @@
#include "seat.h"
#include "river-control-unstable-v1.h"
#include "call-new-output-handler.h"
/**
* ISO C forbids casting a function pointer to a void pointer because on some
@@ -77,7 +78,29 @@ static SCM install_handler (SCM key, SCM proc)
return SCM_UNSPECIFIED;
}
if ( scm_is_eq(scm_from_utf8_symbol("layout-demand"), key) == 1 )
if ( scm_is_eq(scm_from_utf8_symbol("new-output"), key) == 1 )
{
context.mode = CONTINOUS;
context.new_output_handler = proc;
/* Call handler for all already existing outputs. */
struct Output *output;
wl_list_for_each(output, &context.outputs, link)
{
struct Call_new_output_handler_parameters params = {
.output = output,
};
void *res = scm_with_guile(call_new_output_handler, (void *)&params);
if ( res != NULL )
{
fputs(res, stderr);
fputs("INFO: This error is not fatal.\n", stderr);
continue;
}
}
}
else if ( scm_is_eq(scm_from_utf8_symbol("layout-demand"), key) == 1 )
{
if ( context.layout_manager == NULL )
{

View File

@@ -11,6 +11,7 @@
#include "output.h"
#include "call-layout-demand-handler.h"
#include "call-user-command-handler.h"
#include "call-new-output-handler.h"
static void layout_handle_layout_demand (void *data, struct river_layout_v3 *river_layout_v3,
uint32_t view_count, uint32_t width, uint32_t height, uint32_t tags, uint32_t serial)
@@ -106,6 +107,21 @@ struct Output *output_create (struct wl_output *wl_output, uint32_t name)
output->name = name;
output->wl_output = wl_output;
/* If we have a new-output handler installed, send it. */
if ( context.new_output_handler != NULL )
{
struct Call_new_output_handler_parameters params = {
.output = output,
};
void *res = scm_with_guile(call_new_output_handler, (void *)&params);
if ( res != NULL )
{
fputs(res, stderr);
fputs("INFO: This error is not fatal.\n", stderr);
}
}
/* Only bind layout if we need it. Outputs advertised in the initial
* registry burst, before the script is loaded, will always skip this,
* however it is necessary for outputs added later.

View File

@@ -34,6 +34,7 @@ struct Context context = {
* that is intended or will disappear in the future. Special care must be taken
* to never call any scm_* function on these while they are NULL.
*/
.new_output_handler = NULL,
.layout_demand_handler = NULL,
.user_command_handler = NULL,
.exit_handler = NULL,

View File

@@ -22,6 +22,7 @@ enum Riverguile_mode
struct Context
{
SCM new_output_handler;
SCM layout_demand_handler;
SCM user_command_handler;
SCM exit_handler;