/** * @file * @section AUTHORS * * Authors: * Eamon Walsh * * @section LICENSE * * This file is in the public domain. * * @section DESCRIPTION * * This is the code that handles incoming libvchan events from linpicker-track. * This code shoud be robust against bad behavior on the other side, as * we don't trust the guest that is running linpicker-track. */ #include #include #include #include #include "fd.h" #include "comm.h" #include "view.h" #include "buffer.h" #include "client.h" #include "display.h" static void comm_do_update(struct client *c, struct buffer *b, struct view *v, struct lin_message *m) { /* Set view position */ if (m->flags & LINPICKER_FLAG_POSITION) { DFBRectangle bpos = { .x = m->x, .y = m->y, .w = m->w, .h = m->h }; DFBRectangle spos; /* Clip view rectangle to buffer */ if (bpos.x < 0) { bpos.w += bpos.x; bpos.x = 0; } if (bpos.x + bpos.w > b->desc.width) bpos.w = b->desc.width - bpos.x; if (bpos.w < 0) bpos.w = 0; if (bpos.y < 0) { bpos.h += bpos.y; bpos.y = 0; } if (bpos.y + bpos.h > b->desc.height) bpos.h = b->desc.height - bpos.y; if (bpos.h < 0) bpos.h = 0; spos = bpos; spos.x += b->xoff; spos.y += b->yoff; view_set_viewport(v, &bpos, &spos, m->w != v->bpos.w || m->h != v->bpos.h); } /* Set view stacking */ if (m->flags & LINPICKER_FLAG_TOPMOST) view_stack(v, VIEW_STACK_TOP, NULL); else if (m->flags & LINPICKER_FLAG_BOTMOST) view_stack(v, VIEW_STACK_BOTTOM, NULL); else if (m->flags & LINPICKER_FLAG_SIBLING) { struct view *s = view_lookup(c, m->sibling); if (s && s != v) view_stack(v, VIEW_STACK_ABOVE, s); } /* Set view visibility */ if (m->flags & LINPICKER_FLAG_SHOWN) v->mapped = 1; else if (m->flags & LINPICKER_FLAG_HIDDEN) v->mapped = 0; view_show(v); } static void comm_create(struct client *c, struct buffer *b, struct lin_message *m) { struct view *v = view_lookup(c, m->view); if (v) FD_LOG(1, "Warning: view %x already exists.\n", m->view); else { v = view_new(c, b, m->view, VIEW_FLAGS_CLIENT); if (!v) { FD_LOG(0, "Failed to create view!\n"); return; } v->mapped = 0; } comm_do_update(c, b, v, m); } static void comm_update(struct client *c, struct buffer *b, struct lin_message *m) { struct view *v = view_lookup(c, m->view); if (!v) { FD_LOG(1, "Warning: view %x does not exist.\n", m->view); return; } comm_do_update(c, b, v, m); } static void comm_destroy(struct client *c, struct buffer *b, struct lin_message *m) { struct view *v = view_lookup(c, m->view); if (v) view_remove(v); } static void comm_destroy_all(struct client *c, struct buffer *b) { struct view *v; top: TAILQ_FOREACH(v, &b->views, buffer_next) { if (v->flags & VIEW_FLAGS_THUMBNAIL) continue; if (v->flags & VIEW_FLAGS_BACKGROUND) continue; view_remove(v); break; } if (v) goto top; } void comm_process(struct client *c, struct buffer *b, struct lin_message *m) { switch (m->type) { case LINPICKER_RESET: comm_destroy_all(c, b); break; case LINPICKER_CREATE: comm_create(c, b, m); break; case LINPICKER_UPDATE: comm_update(c, b, m); break; case LINPICKER_DESTROY: comm_destroy(c, b, m); break; default: break; } }