#include <inttypes.h>
#include <locale.h>
#include <signal.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include "console.h"
+#include "eloop.h"
#include "log.h"
#include "output.h"
+#include "vt.h"
static volatile sig_atomic_t terminate;
-static void sig_term(int sig)
-{
- terminate = 1;
-}
+struct console {
+ struct kmscon_eloop *loop;
+ struct kmscon_signal *sig_term;
+ struct kmscon_signal *sig_int;
+ struct kmscon_compositor *comp;
+ struct kmscon_vt *vt;
+ struct kmscon_console *con;
+ struct kmscon_idle *idle;
+
+ uint32_t max_x;
+ uint32_t max_y;
+};
-static int map_outputs(struct kmscon_compositor *comp,
- struct kmscon_console *con)
+static void map_outputs(struct console *con)
{
int ret;
struct kmscon_output *iter;
- iter = kmscon_compositor_get_outputs(comp);
+ if (kmscon_compositor_is_asleep(con->comp))
+ return;
+
+ kmscon_console_draw(con->con);
+
+ iter = kmscon_compositor_get_outputs(con->comp);
for ( ; iter; iter = kmscon_output_next(iter)) {
if (!kmscon_output_is_active(iter))
continue;
ret = kmscon_output_use(iter);
- if (ret) {
- log_warning("Cannot use output %p: %d\n", iter, ret);
+ if (ret)
continue;
- }
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
- kmscon_console_map(con);
+ kmscon_console_map(con->con);
ret = kmscon_output_swap(iter);
- if (ret) {
- log_warning("Cannot swap buffers of output %p: %d\n",
- iter, ret);
+ if (ret)
continue;
- }
}
+}
- return 0;
+static void draw(struct kmscon_idle *idle, void *data)
+{
+ struct console *con = data;
+
+ kmscon_eloop_rm_idle(idle);
+ map_outputs(con);
}
-static int run_console(struct kmscon_compositor *comp)
+static void schedule_draw(struct console *con)
+{
+ int ret;
+
+ ret = kmscon_eloop_add_idle(con->loop, con->idle, draw, con);
+ if (ret && ret != -EALREADY)
+ log_warning("Cannot schedule draw function\n");
+}
+
+static void activate_outputs(struct console *con)
{
struct kmscon_output *iter;
struct kmscon_mode *mode;
- struct kmscon_console *con;
int ret;
- uint32_t max_x, max_y, x, y;
+ uint32_t x, y;
- max_x = 0;
- max_y = 0;
+ con->max_x = 0;
+ con->max_y = 0;
- iter = kmscon_compositor_get_outputs(comp);
+ iter = kmscon_compositor_get_outputs(con->comp);
for ( ; iter; iter = kmscon_output_next(iter)) {
- log_info("Activating output %p...\n", iter);
- ret = kmscon_output_activate(iter, NULL);
- if (ret) {
- log_err("Cannot activate output: %d\n", ret);
- continue;
+ if (!kmscon_output_is_active(iter)) {
+ ret = kmscon_output_activate(iter, NULL);
+ if (ret)
+ continue;
}
mode = kmscon_output_get_current(iter);
x = kmscon_mode_get_width(mode);
y = kmscon_mode_get_height(mode);
- if (x > max_x)
- max_x = x;
- if (y > max_y)
- max_y = y;
+ if (x > con->max_x)
+ con->max_x = x;
+ if (y > con->max_y)
+ con->max_y = y;
}
- if (max_x == 0 || max_y == 0) {
- log_err("Cannot retrieve output resolution\n");
- return -EINVAL;
+ if (con->max_x == 0)
+ con->max_x = 800;
+ if (con->max_y == 0)
+ con->max_y = 600;
+
+ kmscon_console_set_res(con->con, con->max_x, con->max_y);
+ schedule_draw(con);
+}
+
+static void sig_term(struct kmscon_signal *sig, int signum, void *data)
+{
+ terminate = 1;
+}
+
+static bool vt_switch(struct kmscon_vt *vt, int action, void *data)
+{
+ struct console *con = data;
+ int ret;
+
+ if (action == KMSCON_VT_ENTER) {
+ ret = kmscon_compositor_wake_up(con->comp);
+ if (ret == 0) {
+ log_info("No output found\n");
+ } else if (ret > 0) {
+ ret = kmscon_compositor_use(con->comp);
+ if (!ret)
+ activate_outputs(con);
+ }
+ } else {
+ kmscon_compositor_sleep(con->comp);
}
- ret = kmscon_console_new(&con);
- if (ret) {
- log_err("Cannot create console: %d\n", ret);
+ return true;
+}
+
+static void destroy_eloop(struct console *con)
+{
+ kmscon_eloop_rm_idle(con->idle);
+ kmscon_idle_unref(con->idle);
+ kmscon_compositor_unref(con->comp);
+ kmscon_console_unref(con->con);
+ kmscon_vt_unref(con->vt);
+ kmscon_eloop_rm_signal(con->sig_int);
+ kmscon_eloop_rm_signal(con->sig_term);
+ kmscon_eloop_unref(con->loop);
+}
+
+static int setup_eloop(struct console *con)
+{
+ int ret;
+
+ ret = kmscon_eloop_new(&con->loop);
+ if (ret)
return ret;
- }
- ret = kmscon_console_set_res(con, max_x, max_y);
- if (ret) {
- log_err("Cannot set console resolution: %d\n", ret);
- goto err_unref;
- }
+ ret = kmscon_eloop_new_signal(con->loop, &con->sig_term, SIGTERM,
+ sig_term, NULL);
+ if (ret)
+ goto err_loop;
- while (!terminate) {
- kmscon_console_draw(con);
- map_outputs(comp, con);
- usleep(10000);
- }
+ ret = kmscon_eloop_new_signal(con->loop, &con->sig_int, SIGINT,
+ sig_term, NULL);
+ if (ret)
+ goto err_loop;
+
+ ret = kmscon_vt_new(&con->vt, vt_switch, con);
+ if (ret)
+ goto err_loop;
+
+ ret = kmscon_vt_open(con->vt, KMSCON_VT_NEW);
+ if (ret)
+ goto err_loop;
+
+ ret = kmscon_vt_connect_eloop(con->vt, con->loop);
+ if (ret)
+ goto err_loop;
+
+ ret = kmscon_console_new(&con->con);
+ if (ret)
+ goto err_loop;
+
+ ret = kmscon_compositor_new(&con->comp);
+ if (ret)
+ goto err_loop;
- log_info("Terminating due to user request\n");
+ ret = kmscon_idle_new(&con->idle);
+ if (ret)
+ goto err_loop;
-err_unref:
- kmscon_console_unref(con);
+ return 0;
+
+err_loop:
+ destroy_eloop(con);
return ret;
}
int main(int argc, char **argv)
{
- struct kmscon_compositor *comp;
+ struct console con;
int ret;
- struct sigaction sig;
setlocale(LC_ALL, "");
+ memset(&con, 0, sizeof(con));
- memset(&sig, 0, sizeof(sig));
- sig.sa_handler = sig_term;
- sigaction(SIGTERM, &sig, NULL);
- sigaction(SIGINT, &sig, NULL);
-
- ret = kmscon_compositor_new(&comp);
+ ret = setup_eloop(&con);
if (ret) {
- log_err("Cannot create compositor: %d\n", ret);
+ log_err("Cannot setup eloop\n");
return abs(ret);
}
- ret = kmscon_compositor_wake_up(comp);
- if (ret < 0) {
- log_err("Cannot wake up compositor: %d\n", ret);
- goto err_unref;
- }
+ schedule_draw(&con);
- if (ret == 0) {
- log_err("No output available\n");
- ret = -EINVAL;
- goto err_unref;
+ while (!terminate) {
+ ret = kmscon_eloop_dispatch(con.loop, -1);
+ if (ret)
+ break;
}
- kmscon_compositor_use(comp);
- ret = run_console(comp);
-
-err_unref:
- kmscon_compositor_unref(comp);
+ destroy_eloop(&con);
return abs(ret);
}