1
0
mirror of https://github.com/emersion/kanshi synced 2024-09-18 09:51:36 +02:00

Factor out event loop.

This rework is necessary because it will allow us to add signal handlers
via signalfd and a varlink interface for IPC.

Co-authored-by: Érico Nogueira <erico.erc@gmail.com>
This commit is contained in:
Jason Francis 2021-07-06 23:54:51 -03:00 committed by Simon Ser
parent fd565f4415
commit bec47f49e3
4 changed files with 96 additions and 14 deletions

65
event-loop.c Normal file
View File

@ -0,0 +1,65 @@
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "kanshi.h"
enum readfds_type {
FD_WAYLAND,
FD_COUNT,
};
int kanshi_main_loop(struct kanshi_state *state) {
struct pollfd readfds[FD_COUNT] = {0};
readfds[FD_WAYLAND].fd = wl_display_get_fd(state->display);
readfds[FD_WAYLAND].events = POLLIN;
while (state->running) {
while (wl_display_prepare_read(state->display) != 0) {
if (wl_display_dispatch_pending(state->display) == -1) {
return EXIT_FAILURE;
}
}
int ret;
while (true) {
ret = wl_display_flush(state->display);
if (ret != -1 || errno != EAGAIN) {
break;
}
}
if (ret < 0 && errno != EPIPE) {
goto read_error;
}
do {
ret = poll(readfds, sizeof(readfds) / sizeof(readfds[0]), -1);
} while (ret == -1 && errno == EINTR);
/* will only be -1 if errno wasn't EINTR */
if (ret == -1) {
goto read_error;
}
if (wl_display_read_events(state->display) == -1) {
return EXIT_FAILURE;
}
if (wl_display_dispatch_pending(state->display) == -1) {
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
read_error:
wl_display_cancel_read(state->display);
return EXIT_FAILURE;
}

View File

@ -41,6 +41,7 @@ struct kanshi_head {
struct kanshi_state {
bool running;
struct wl_display *display;
struct zwlr_output_manager_v1 *output_manager;
struct kanshi_config *config;
@ -48,6 +49,7 @@ struct kanshi_state {
struct wl_list heads;
uint32_t serial;
struct kanshi_profile *current_profile;
struct kanshi_profile *pending_profile;
};
struct kanshi_pending_profile {
@ -55,4 +57,6 @@ struct kanshi_pending_profile {
struct kanshi_profile *profile;
};
int kanshi_main_loop(struct kanshi_state *state);
#endif

40
main.c
View File

@ -1,6 +1,7 @@
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <signal.h>
@ -187,13 +188,16 @@ static struct kanshi_mode *match_mode(struct kanshi_head *head,
static void apply_profile(struct kanshi_state *state,
struct kanshi_profile *profile,
struct kanshi_profile_output **matches) {
if (state->current_profile == profile) {
if (state->pending_profile == profile || state->current_profile == profile) {
return;
}
fprintf(stderr, "applying profile '%s'\n", profile->name);
struct kanshi_pending_profile *pending = calloc(1, sizeof(*pending));
pending->state = state;
pending->profile = profile;
state->pending_profile = profile;
struct zwlr_output_configuration_v1 *config =
zwlr_output_manager_v1_create_configuration(state->output_manager,
@ -406,21 +410,25 @@ static void output_manager_handle_head(void *data,
zwlr_output_head_v1_add_listener(wlr_head, &head_listener, head);
}
static void output_manager_handle_done(void *data,
struct zwlr_output_manager_v1 *manager, uint32_t serial) {
struct kanshi_state *state = data;
state->serial = serial;
static bool try_apply_profiles(struct kanshi_state *state) {
assert(wl_list_length(&state->heads) <= HEADS_MAX);
// matches[i] gives the kanshi_profile_output for the i-th head
struct kanshi_profile_output *matches[HEADS_MAX];
struct kanshi_profile *profile = match(state, matches);
if (profile != NULL) {
fprintf(stderr, "applying profile '%s'\n", profile->name);
apply_profile(state, profile, matches);
} else {
fprintf(stderr, "no profile matched\n");
return true;
}
fprintf(stderr, "no profile matched\n");
return false;
}
static void output_manager_handle_done(void *data,
struct zwlr_output_manager_v1 *manager, uint32_t serial) {
struct kanshi_state *state = data;
state->serial = serial;
try_apply_profiles(state);
}
static void output_manager_handle_finished(void *data,
@ -520,8 +528,10 @@ int main(int argc, char *argv[]) {
struct kanshi_state state = {
.running = true,
.display = display,
.config = config,
};
int ret = EXIT_SUCCESS;
wl_list_init(&state.heads);
struct wl_registry *registry = wl_display_get_registry(display);
@ -532,12 +542,14 @@ int main(int argc, char *argv[]) {
if (state.output_manager == NULL) {
fprintf(stderr, "compositor doesn't support "
"wlr-output-management-unstable-v1\n");
return EXIT_FAILURE;
ret = EXIT_FAILURE;
goto done;
}
while (state.running && wl_display_dispatch(display) != -1) {
// This space intentionally left blank
}
ret = kanshi_main_loop(&state);
return EXIT_SUCCESS;
done:
wl_display_disconnect(display);
return ret;
}

View File

@ -43,6 +43,7 @@ executable(
files(
'main.c',
'parser.c',
'event-loop.c',
),
include_directories: include_directories('include'),
dependencies: [wayland_client, client_protos],