load script after initial registry burst

This makes the logic of installing idle handlers and layout handlers a bit
cleaner and allows us to send wayland request from the script in the future.
This commit is contained in:
Leon Henrik Plickat
2024-01-07 06:24:23 +01:00
parent 732c1adb55
commit 153b5e0858
11 changed files with 304 additions and 152 deletions

View File

@@ -118,54 +118,66 @@ static const struct wl_registry_listener registry_listener = {
.global_remove = registry_handle_global_remove,
};
static void sync_handle_done (void *, struct wl_callback *, uint32_t);
static const struct wl_callback_listener sync_callback_listener = {
.done = sync_handle_done,
};
static void sync_handle_done (void *data, struct wl_callback *wl_callback, uint32_t other_data)
{
static int i = 0;
if ( i == 1 )
{
assert(context.mode == ONESHOT);
context.loop = false;
return;
}
wl_callback_destroy(wl_callback);
context.sync_callback = NULL;
if ( context.layout_manager == NULL )
/* Load the script after connecting to the server and binding interfaces
* to allow calling Wayland requests from it.
*/
assert(context.path != NULL);
void *res = scm_with_guile(load_script, (void *)context.path);
if ( res != NULL )
{
fputs("ERROR: Wayland server does not support river-layout-v3.\n", stderr);
fputs((char *)res, stderr);
context.ret = EXIT_FAILURE;
context.loop = false;
return;
}
if ( context.idle_notifier == NULL )
if ( context.layout_demand_handler == NULL
&& context.user_command_handler != NULL )
{
if ( wl_list_length(&context.unconfigured_idles) > 0 )
{
fputs("ERROR: Wayland server does not support ext-idle-notify-v1.\n", stderr);
fputs("INFO: This error is not fatal.\n", stderr);
}
fputs("ERROR: Installing user-command handler without installing a layout-demand handler is not allowed.\n", stderr);
fputs("INFO: This error is not fatal, but means riverguile will not provide any layout.\n", stderr);
}
else
switch (context.mode)
{
struct Seat *seat;
wl_list_for_each(seat, &context.seats, link)
case ONESHOT:
/* Oneshot mode. Sync again so we are sure that all commands
* have been send, then exit.
*/
assert(i == 0);
i++;
context.sync_callback = wl_display_sync(context.wl_display);
wl_callback_add_listener(context.sync_callback, &sync_callback_listener, NULL);
fputs("INFO: No handlers installed: Riverguile will exit.\n", stderr);
break;
struct Idle *idle, *tmp_i;
wl_list_for_each_safe(idle, tmp_i, &context.unconfigured_idles, link)
idle_configure(idle, seat);
case CONTINOUS:
fputs("INFO: At least one handler installed: Riverguile will run continously.\n", stderr);
break;
}
/* If outputs were registered before the river_layout_manager is
* available, they won't have a river_layout, so we need to create
* those here.
*/
struct Output *output;
wl_list_for_each(output, &context.outputs, link)
output_configure(output);
}
static const struct wl_callback_listener sync_callback_listener = {
.done = sync_handle_done,
};
static void handle_interrupt (int signum)
{
fputs("Killed 💀\n", stderr);
fputs("INFO: Killed 💀\n", stderr);
context.loop = false;
longjmp(skip_main_loop, 1);
}
@@ -211,7 +223,6 @@ static void handle_error (int signum)
kill(getpid(), signum);
}
static char *formatted_buffer (const char *fmt, ...)
{
/* Determine length of formatted text. */
@@ -286,36 +297,29 @@ static char *get_script_path (void)
if ( path != NULL )
free(path);
fputs("ERROR: No layout script found.\n", stderr);
fputs("ERROR: No script found.\n", stderr);
return NULL;
}
int main(int argc, char *argv[])
{
fputs("INFO: Welcome to riverguile!\n", stderr);
signal(SIGSEGV, handle_error);
signal(SIGFPE, handle_error);
signal(SIGINT, handle_interrupt);
wl_list_init(&context.outputs);
wl_list_init(&context.seats);
wl_list_init(&context.unconfigured_idles);
// TODO use argv[1] if present
char *path = get_script_path();
if ( path == NULL )
context.path = get_script_path();
if ( context.path == NULL )
{
context.ret = EXIT_FAILURE;
goto early_exit;
}
void *res = scm_with_guile(load_script, (void *)path);
if ( res != NULL )
{
fputs((char *)res, stderr);
context.ret = EXIT_FAILURE;
context.loop = false;
goto early_exit;
}
fprintf(stderr, "INFO: Found script: %s\n", context.path);
/* We query the display name here instead of letting wl_display_connect()
* figure it out itself, because libwayland (for legacy reasons) falls
@@ -348,13 +352,14 @@ int main(int argc, char *argv[])
while ( context.loop && wl_display_dispatch(context.wl_display) > 0 );
if ( context.exit_handler != NULL )
call_exit_handler();
struct Idle *idle, *tmp_i;
wl_list_for_each_safe(idle, tmp_i, &context.unconfigured_idles, link)
{
wl_list_remove(&idle->link);
idle_destroy(idle);
void *res = scm_with_guile(call_exit_handler, NULL);
if ( res != NULL )
{
fputs((char *)res, stderr);
context.ret = EXIT_FAILURE;
context.loop = false;
}
}
struct Output *output, *tmp_o;
@@ -382,9 +387,10 @@ int main(int argc, char *argv[])
wl_display_disconnect(context.wl_display);
early_exit:
if ( path != NULL )
free(path);
if ( context.path != NULL )
free(context.path);
fputs("INFO: Exiting.\n", stderr);
return context.ret;
}