mirror of
https://github.com/emersion/kanshi
synced 2024-11-22 15:51:58 +01: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:
parent
fd565f4415
commit
bec47f49e3
65
event-loop.c
Normal file
65
event-loop.c
Normal 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;
|
||||
}
|
@ -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
40
main.c
@ -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;
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ executable(
|
||||
files(
|
||||
'main.c',
|
||||
'parser.c',
|
||||
'event-loop.c',
|
||||
),
|
||||
include_directories: include_directories('include'),
|
||||
dependencies: [wayland_client, client_protos],
|
||||
|
Loading…
Reference in New Issue
Block a user