diff options
Diffstat (limited to 'abs/mv-core/ghosd/ghosd-0.0.1/ghosd/ghosd-main.c')
-rw-r--r-- | abs/mv-core/ghosd/ghosd-0.0.1/ghosd/ghosd-main.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/abs/mv-core/ghosd/ghosd-0.0.1/ghosd/ghosd-main.c b/abs/mv-core/ghosd/ghosd-0.0.1/ghosd/ghosd-main.c new file mode 100644 index 0000000..bac397e --- /dev/null +++ b/abs/mv-core/ghosd/ghosd-0.0.1/ghosd/ghosd-main.c @@ -0,0 +1,158 @@ +/* ghosd -- OSD with fake transparency, cairo, and pango. + * Copyright (C) 2006 Evan Martin <martine@danga.com> + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <sys/poll.h> +#include <time.h> +#include <unistd.h> + +#include "ghosd.h" +#include "ghosd-internal.h" + +static void +ghosd_main_iteration(Ghosd *ghosd) { + XEvent ev, pev; + XNextEvent(ghosd->dpy, &ev); + + /* smash multiple configure/exposes into one. */ + if (ev.type == ConfigureNotify) { + while (XPending(ghosd->dpy)) { + XPeekEvent(ghosd->dpy, &pev); + if (pev.type != ConfigureNotify && pev.type != Expose) + break; + XNextEvent(ghosd->dpy, &ev); + } + } + + switch (ev.type) { + case Expose: + break; + case ConfigureNotify: + if (ghosd->width > 0) { + /* XXX if the window manager disagrees with our positioning here, + * we loop. */ + if (ghosd->x != ev.xconfigure.x || + ghosd->y != ev.xconfigure.y) { + /*width = ev.xconfigure.width; + height = ev.xconfigure.height;*/ + XMoveResizeWindow(ghosd->dpy, ghosd->win, + ghosd->x, ghosd->y, ghosd->width, ghosd->height); + } + } + break; + } +} + +void +ghosd_main_iterations(Ghosd *ghosd) { + while (XPending(ghosd->dpy)) + ghosd_main_iteration(ghosd); +} + +typedef struct { + GhosdRenderFunc render_func; + void *render_data; + cairo_surface_t* surface; + float alpha; +} GhosdFlashData; + +static void +ghosd_flash_render(Ghosd *ghosd, cairo_t *cr, void* data) { + GhosdFlashData *flash = data; + + /* the first time we render, let the client render into their own surface. */ + if (flash->surface == NULL) { + cairo_t *rendered_cr; + flash->surface = cairo_surface_create_similar(cairo_get_target(cr), + CAIRO_CONTENT_COLOR_ALPHA, + ghosd->width, ghosd->height); + rendered_cr = cairo_create(flash->surface); + flash->render_func(ghosd, rendered_cr, flash->render_data); + cairo_destroy(rendered_cr); + } + + /* now that we have a rendered surface, all we normally do is copy that to + * the screen. */ + cairo_set_source_surface(cr, flash->surface, 0, 0); + cairo_paint_with_alpha(cr, flash->alpha); +} + +void +ghosd_main_until(Ghosd *ghosd, struct timeval *until) { + struct timeval tv_now; + + ghosd_main_iterations(ghosd); + + for (;;) { + gettimeofday(&tv_now, NULL); + int dt = (until->tv_sec - tv_now.tv_sec )*1000 + + (until->tv_usec - tv_now.tv_usec)/1000; + if (dt <= 0) break; + + struct pollfd pollfd = { ghosd_get_socket(ghosd), POLLIN, 0 }; + int ret = poll(&pollfd, 1, dt); + if (ret < 0) { + perror("poll"); + exit(1); + } else if (ret > 0) { + ghosd_main_iterations(ghosd); + } else { + /* timer expired. */ + break; + } + } +} + +void +ghosd_flash(Ghosd *ghosd, int fade_ms, int total_display_ms) { + GhosdFlashData flash = {0}; + flash.render_func = ghosd->render_func; + flash.render_data = ghosd->render_data; + ghosd->render_func = ghosd_flash_render; + ghosd->render_data = &flash; + + ghosd_render(ghosd); + ghosd_show(ghosd); + + const int STEP_MS = 50; + const float dalpha = 1.0 / (fade_ms / (float)STEP_MS); + struct timeval tv_nextupdate; + + /* fade in. */ + for (flash.alpha = 0; flash.alpha < 1.0; flash.alpha += dalpha) { + if (flash.alpha > 1.0) flash.alpha = 1.0; + ghosd_render(ghosd); + + gettimeofday(&tv_nextupdate, NULL); + tv_nextupdate.tv_usec += STEP_MS*1000; + ghosd_main_until(ghosd, &tv_nextupdate); + } + + /* full display. */ + flash.alpha = 1.0; + ghosd_render(ghosd); + + gettimeofday(&tv_nextupdate, NULL); + tv_nextupdate.tv_usec += (total_display_ms - (2*fade_ms))*1000; + ghosd_main_until(ghosd, &tv_nextupdate); + + /* fade out. */ + for (flash.alpha = 1.0; flash.alpha > 0.0; flash.alpha -= dalpha) { + ghosd_render(ghosd); + + gettimeofday(&tv_nextupdate, NULL); + tv_nextupdate.tv_usec += STEP_MS*1000; + ghosd_main_until(ghosd, &tv_nextupdate); + } + + flash.alpha = 0; + ghosd_render(ghosd); + ghosd_main_iterations(ghosd); +} + +/* vim: set ts=2 sw=2 et cino=(0 : */ |