test_console: Use new eloop and VT subsystem
authorDavid Herrmann <dh.herrmann@googlemail.com>
Sat, 3 Dec 2011 15:49:44 +0000 (16:49 +0100)
committerDavid Herrmann <dh.herrmann@googlemail.com>
Sat, 3 Dec 2011 15:49:44 +0000 (16:49 +0100)
The test_console application now supports VT-switching and monitor-hotplug. New
monitors are detected when switching VTs. Full hotplug-support will be added
later.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
tests/test_console.c

index 6eab19a..c29ecd8 100644 (file)
@@ -46,6 +46,7 @@
 #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);
 }