/** * @file * @section AUTHORS * * Authors: * Eamon Walsh * * @section LICENSE * * This file is in the public domain. * * @section DESCRIPTION * * This is the "subclass" of display that implements the Combined * Desktop with views from multiple guest framebuffers stacked together. */ #include #include #include #include #include #include #include "common.h" #include "sys-queue.h" #include "xen_linpicker.h" #include "client.h" #include "display.h" #include "sclient.h" static struct display sd; static fd_set keys_down; static int nkeys; static unsigned char *background; static int dclient_key(struct display *d, bool down, int keycode) { /* * Make the mouse_client the focus_client if: * 1. The current focus_client is not mouse_client. * 2. A mouse button has been pressed. * 3. No keys or buttons were pressed before. */ if (d->mouse_client != d->focus_client && nkeys == 0 && down && keycode >= BTN_MISC && keycode < KEY_OK) { d->focus_client = d->mouse_client; d->focus_view = d->mouse_view; display_update_seclabel(d); if (d->focus_view) view_stack(d->focus_view, VIEW_STACK_TOP, NULL); } /* Update the key state. */ if (down && !FD_ISSET(keycode, &keys_down)) { FD_SET(keycode, &keys_down); nkeys++; } if (!down && FD_ISSET(keycode, &keys_down)) { FD_CLR(keycode, &keys_down); nkeys--; } /* Forward the actual key event. */ if (d->focus_client && d->focus_client->input) xenfb_send_key(d->focus_client->input, down, keycode); return 0; } static int dclient_position(struct display *d, int x, int y) { struct view *v; struct client *c; TAILQ_FOREACH(v, &d->views, display_next) if (x >= v->spos.x && x < (v->spos.x + v->spos.w) && y >= v->spos.y && y < (v->spos.y + v->spos.h) && v->mapped) break; /* Track what view the mouse is over for use in dclient_key */ if (d->mouse_view != v) d->mouse_view = v; /* What client is the mouse over? */ c = v ? v->buffer->client : NULL; /* * Make this client the mouse_client if: * 1. The current mouse_client is not client. * 2. No keys or mouse buttons are pressed. */ if (c != d->mouse_client && nkeys == 0) { d->mouse_client = c; display_update_mouselabel(d, c); } return 0; } static int dclient_mouse(struct display *d, struct mouse_event *m) { struct buffer *b; /* Update position */ dclient_position(d, m->x, m->y); /* Forward the actual motion event. */ if (d->mouse_client && d->mouse_client->input) { b = LIST_FIRST(&d->mouse_client->buffers); /* Remove the buffer offset */ /* Clamp the position to the buffer bounds */ /* Scale the position to the dimensions the frontend expects */ if (b->xoff > 0 || b->yoff > 0) { m->x = scale_value(m->x - b->xoff, b->desc.width, display_get_width()); m->y = scale_value(m->y - b->yoff, b->desc.height, display_get_height()); } xen_linpicker_input_send(d->mouse_client->input, m); } return 0; } int dclient_setup(void) { DFBSurfaceDescription sdesc; struct buffer *b; int width = display_get_width(); int height = display_get_height(); background = malloc(width * height); if (!background) return -1; sclient_read_background_image(DESKTOP_BG_FILE, background, width, height); /* Set up preallocated DirectFB surface with the data */ memset(&sdesc, 0, sizeof(sdesc)); sdesc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_CAPS | DSDESC_PIXELFORMAT | DSDESC_PREALLOCATED; sdesc.width = width; sdesc.height = height; sdesc.pixelformat = DSPF_RGB332; sdesc.preallocated[0].data = background; sdesc.preallocated[0].pitch = width; b = buffer_new(sd.client, &sdesc, BUFFER_FLAG_DESKTOP_BG); if (b == NULL) { free(background); return -1; } sd.bg_view = b->bg_view; return 0; } struct display * dclient_new(void) { struct client *c = client_add(-1, 1024, 1024); if (!c) return NULL; /* XXX Label the client */ c->label.label = strdup("COMBINED DESKTOP"); c->label.shortlabel = strdup("D"); c->label.fg = (struct sec_color){ 0xff, 0xff, 0 }; c->label.bg = (struct sec_color){ 0, 0, 0xff }; /* Set up input methods */ sd.send_key = dclient_key; sd.send_mouse = dclient_mouse; sd.update_position = dclient_position; sd.type = DISPLAY_DESKTOP; sd.client = c; LIST_INIT(&sd.buffers); TAILQ_INIT(&sd.views); return &sd; }