From bd0c684c9941c24ee4191f4550ec966d5b1fa8ab Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Wed, 15 Feb 2012 11:33:41 -0800 Subject: Update twin ui to use discover server Signed-off-by: Geoff Levand --- ui/twin/pbt-scr.c | 459 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 459 insertions(+) create mode 100644 ui/twin/pbt-scr.c (limited to 'ui/twin/pbt-scr.c') diff --git a/ui/twin/pbt-scr.c b/ui/twin/pbt-scr.c new file mode 100644 index 0000000..8d6c498 --- /dev/null +++ b/ui/twin/pbt-scr.c @@ -0,0 +1,459 @@ +/* + * Copyright Geoff Levand + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#define _GNU_SOURCE +#include + +#include +#include + +#include "list/list.h" +#include "log/log.h" +#include "talloc/talloc.h" +#include "waiter/waiter.h" +#include "ui/common/ui-system.h" +#include "pbt-scr.h" + +void _pbt_dump_event(const char *text, twin_window_t *twindow, + const twin_event_t *tevent, const char *func, int line) +{ + switch(tevent->kind) { + case TwinEventButtonDown: + DBG("%s:%d: %s@%p: TwinEventButtonDown %x\n", func, line, text, + twindow, tevent->kind); + return; + case TwinEventButtonUp: + DBG("%s:%d: %s@%p: TwinEventButtonUp %x\n", func, line, text, + twindow, tevent->kind); + return; + case TwinEventMotion: + //DBG("%s:%d:%s@%p: TwinEventMotion %x\n", func, line, text, + // twindow, tevent->kind); + return; + case TwinEventEnter: + DBG("%s:%d: %s@%p: TwinEventEnter %x\n", func, line, text, + twindow, tevent->kind); + return; + case TwinEventLeave: + DBG("%s:%d: %s@%p: TwinEventLeave %x\n", func, line, text, + twindow, tevent->kind); + return; + case TwinEventKeyDown: + case TwinEventKeyUp: + { + const char *kind = (tevent->kind == TwinEventKeyDown) + ? "TwinEventKeyDown" : "TwinEventKeyUp "; + + switch(tevent->u.key.key) { + case (twin_keysym_t)XK_Up: + case (twin_keysym_t)KEY_UP: + DBG("%s:%d: %s@%p: %s = 'KEY_UP'\n", func, line, text, + twindow, kind); + return; + case (twin_keysym_t)XK_Down: + case (twin_keysym_t)KEY_DOWN: + DBG("%s:%d: %s@%p: %s = 'KEY_DOWN'\n", func, line, text, + twindow, kind); + return; + case (twin_keysym_t)XK_Right: + case (twin_keysym_t)KEY_RIGHT: + DBG("%s:%d: %s@%p: %s = 'KEY_RIGHT'\n", func, line, text, + twindow, kind); + return; + case (twin_keysym_t)XK_Left: + case (twin_keysym_t)KEY_LEFT: + DBG("%s:%d: %s@%p: %s = 'KEY_LEFT'\n", func, line, text, + twindow, kind); + return; + case (twin_keysym_t)XK_Escape: + case (twin_keysym_t)KEY_ESC: + DBG("%s:%d: %s@%p: %s = 'KEY_ESC'\n", func, line, text, + twindow, kind); + return; + case (twin_keysym_t)XK_Return: + case (twin_keysym_t)KEY_ENTER: + DBG("%s:%d: %s@%p: %s = 'KEY_ENTER'\n", func, line, text, + twindow, kind); + return; + case (twin_keysym_t)XK_Delete: + case (twin_keysym_t)KEY_DELETE: + DBG("%s:%d: %s@%p: %s = 'KEY_DELETE'\n", func, line, text, + twindow, kind); + return; + case (twin_keysym_t)XK_BackSpace: + case (twin_keysym_t)KEY_BACKSPACE: + DBG("%s:%d: %s@%p: %s = 'KEY_BACKSPACE'\n", func, line, text, + twindow, kind); + return; + default: + DBG("%s:%d: %s@%p: %s = %d (%xh) = '%c'\n", func, line, text, twindow, + kind, + tevent->u.key.key, tevent->u.key.key, + (char)tevent->u.key.key); + } + return; + } + default: + DBG("%s:%d: %s@%p: %x\n", func, line, text, twindow, tevent->kind); + break; + } +} + +/** + * pbt_background_load - Load the background pixmap from storage. + * @filename: File name of a jpg background. + * + * Returns the default background if @filename is NULL. Returns a default + * pattern if the load of @filename fails. + */ + +twin_pixmap_t *pbt_background_load(twin_screen_t *tscreen, + const char *filename) +{ + static const char *default_background_file = + PB_ARTWORK_PATH "/background.jpg"; + twin_pixmap_t *raw_background; + twin_pixmap_t *scaled_background; + + if (!filename) + filename = default_background_file; + + raw_background = twin_jpeg_to_pixmap(filename, TWIN_ARGB32); + + if (!raw_background) { + pb_log("%s: loading image '%s' failed\n", __func__, filename); + + /* Fallback to a default pattern */ + + return twin_make_pattern(); + } + + if (tscreen->height == raw_background->height && + tscreen->width == raw_background->width) + return raw_background; + + /* Scale as needed. */ + + twin_fixed_t sx, sy; + twin_operand_t srcop; + + scaled_background = twin_pixmap_create(TWIN_ARGB32, + tscreen->width, + tscreen->height); + if (!scaled_background) { + pb_log("%s: scale '%s' failed\n", __func__, filename); + twin_pixmap_destroy(raw_background); + return twin_make_pattern(); + } + sx = twin_fixed_div(twin_int_to_fixed(raw_background->width), + twin_int_to_fixed(tscreen->width)); + sy = twin_fixed_div(twin_int_to_fixed(raw_background->height), + twin_int_to_fixed(tscreen->height)); + + twin_matrix_scale(&raw_background->transform, sx, sy); + srcop.source_kind = TWIN_PIXMAP; + srcop.u.pixmap = raw_background; + twin_composite(scaled_background, 0, 0, &srcop, 0, 0, + NULL, 0, 0, TWIN_SOURCE, + tscreen->width, tscreen->height); + + twin_pixmap_destroy(raw_background); + + return scaled_background; +} + +const char *pbt_icon_chooser(const char *hint) +{ + if (strstr(hint, "net")) + return PB_ARTWORK_PATH "/network.png"; + + return NULL; +} + +/** + * pbt_icon_load - Load an icon pixmap from storage. + * @filename: File name of a png icon. + * + * Returns the default icon if @filename is NULL, or if the load + * of @filename fails. + * Caches pixmaps based on a hash of the @filename string. + */ + +twin_pixmap_t *pbt_icon_load(const char *filename) +{ + static const char *default_icon_file = PB_ARTWORK_PATH "/tux.png"; + struct cache_entry { + struct list_item list; + int hash; + twin_pixmap_t *icon; + }; + STATIC_LIST(icon_cache); + struct cache_entry new; + struct cache_entry *i; + + if (!filename) + filename = default_icon_file; + +retry: + new.hash = pb_elf_hash(filename); + + list_for_each_entry(&icon_cache, i, list) { + if (i->hash == new.hash) { + DBGS("found %p\n", i->icon); + return i->icon; + } + } + + new.icon = twin_png_to_pixmap(filename, TWIN_ARGB32); + + if (!new.icon) { + pb_log("%s: loading image '%s' failed\n", __func__, filename); + + if (filename == default_icon_file) + return NULL; + + filename = default_icon_file; + goto retry; + } + + DBGS("new %p\n", new.icon); + + i = talloc(NULL, struct cache_entry); + *i = new; + list_add(&icon_cache, &i->list); + + pbt_dump_pixmap(new.icon); + + return new.icon; +} + +/** + * pbt_border_draw - Draw a border on a pixmap. + * @pixmap: The image to operate on. + * @border: The border to draw. + */ + +void pbt_border_draw(twin_pixmap_t *pixmap, const struct pbt_border *border) +{ + twin_path_t *path = twin_path_create(); + twin_argb32_t fill = border->fill_color ? border->fill_color + : 0xff000000; /* default to black */ + + assert(path); + + //pbt_dump_pixmap(pixmap); + + if (border->left) { + twin_path_rectangle(path, 0, 0, + twin_int_to_fixed(border->left), + twin_int_to_fixed(pixmap->height)); + } + + if (border->right) { + twin_path_rectangle(path, + twin_int_to_fixed(pixmap->width - border->right), + 0, + twin_int_to_fixed(pixmap->width), + twin_int_to_fixed(pixmap->height)); + } + + if (border->top) { + twin_path_rectangle(path, 0, 0, + twin_int_to_fixed(pixmap->width), + twin_int_to_fixed(border->top)); + } + + if (border->bottom) { + twin_path_rectangle(path, 0, + twin_int_to_fixed(pixmap->height - border->bottom), + twin_int_to_fixed(pixmap->width), + twin_int_to_fixed(border->bottom)); + } + + twin_paint_path(pixmap, fill, path); + twin_path_empty(path); +} + +int pbt_window_contains(const twin_window_t *window, const twin_event_t *event) +{ + pbt_dump_pixmap(window->pixmap); + + if (event->u.pointer.x < window->pixmap->x) { + DBGS("%p: {%d,%d} left miss\n", window, event->u.pointer.x, event->u.pointer.y); + return 0; + } + if (event->u.pointer.x >= window->pixmap->x + window->pixmap->width) { + DBGS("%p: {%d,%d} right miss\n", window, event->u.pointer.x, event->u.pointer.y); + return 0; + } + if (event->u.pointer.y < window->pixmap->y) { + DBGS("%p: {%d,%d} high miss\n", window, event->u.pointer.x, event->u.pointer.y); + return 0; + } + if (event->u.pointer.y >= window->pixmap->y + window->pixmap->height){ + DBGS("%p: {%d,%d} low miss\n", window, event->u.pointer.x, event->u.pointer.y); + return 0; + } + + DBGS("%p: {%d,%d} hit\n", window, event->u.pointer.x, event->u.pointer.y); + return 1; +} + + +static __attribute__((unused)) void pbt_image_copy(twin_pixmap_t *dest, twin_pixmap_t *src) +{ + twin_operand_t op; + + assert(dest->height >= src->height); + + op.source_kind = TWIN_PIXMAP; + op.u.pixmap = src; + + twin_composite(dest, 0, 0, &op, 0, 0, NULL, + 0, 0, TWIN_SOURCE, src->width, src->height); +} + +void pbt_image_draw(twin_pixmap_t *dest, twin_pixmap_t *image) +{ + twin_operand_t src; + int offset; + + assert(dest->height >= image->height); + + src.source_kind = TWIN_PIXMAP; + src.u.pixmap = image; + + /* Center the image in the window. */ + + offset = (dest->height - image->height) / 2; + + twin_composite(dest, offset, offset, &src, 0, 0, NULL, + 0, 0, TWIN_SOURCE, image->width, image->height); +} + +static int pbt_twin_waiter_cb(struct pbt_twin_ctx *twin_ctx) +{ +#if defined(HAVE_LIBTWIN_TWIN_X11_H) + if (twin_ctx->backend == pbt_twin_x11) + twin_x11_process_events(twin_ctx->x11); +#endif +#if defined(HAVE_LIBTWIN_TWIN_FBDEV_H) + if (twin_ctx->backend == pbt_twin_fbdev) + twin_fbdev_process_events(twin_ctx->fbdev); +#endif + return 0; +}; + +static void pbt_scr_destructor(struct pbt_scr *scr) +{ + pb_log("%s\n", __func__); + + twin_x11_destroy(scr->twin_ctx.x11); + // FIXME: need cursor cleanup??? + memset(scr, 0, sizeof(*scr)); +} + +struct pbt_scr *pbt_scr_init(void *talloc_ctx, enum pbt_twin_backend backend, + unsigned int width, unsigned int height, + const char *filename_background, + twin_bool_t (*scr_event_cb)(twin_screen_t *tscreen, + twin_event_t *event)) +{ + struct pbt_scr *scr = talloc_zero(talloc_ctx, struct pbt_scr); + int waiter_fd = -1; + + assert(backend && backend < 3); + assert(width > 100); + assert(height > 100); + + if (!scr) { + pb_log("%s: alloc pbt_scr failed.\n", __func__); + goto fail_alloc; + } + + talloc_set_destructor(scr, (void *)pbt_scr_destructor); + + twin_feature_init(); // FIXME: need it??? + + scr->twin_ctx.backend = backend; + + if (backend == pbt_twin_x11) { + pb_log("%s: using twin x11 backend.\n", __func__); +#if !defined(HAVE_LIBTWIN_TWIN_X11_H) + assert(0); +#else + scr->twin_ctx.x11 = twin_x11_create_ext(XOpenDisplay(0), width, + height, 0); + + if (!scr->twin_ctx.x11) { + pb_log("%s: twin_x11_create_ext failed.\n", __func__); + perror("failed to create twin x11 context\n"); + goto fail_ctx_create; + } + + pb_log("%s: x11: %p\n", __func__, scr->twin_ctx.x11); + + assert(scr->twin_ctx.x11->screen); + scr->tscreen = scr->twin_ctx.x11->screen; + waiter_fd = ConnectionNumber(scr->twin_ctx.x11->dpy); +#endif + } else if (backend == pbt_twin_fbdev) { + pb_log("%s: using twin fbdev backend.\n", __func__); +#if !defined(HAVE_LIBTWIN_TWIN_FBDEV_H) + assert(0); +#else + scr->twin_ctx.fbdev = twin_fbdev_create_ext(-1, SIGUSR1, 0); + + if (!scr->twin_ctx.fbdev) { + pb_log("%s: twin_fbdev_create_ext failed.\n", __func__); + perror("failed to create twin fbdev context\n"); + goto fail_ctx_create; + } + + assert(scr->twin_ctx.fbdev->screen); + scr->tscreen = scr->twin_ctx.fbdev->screen; + waiter_fd = scr->twin_ctx.fbdev->vt_fd; + + twin_fbdev_activate(scr->twin_ctx.fbdev); +#endif + } + + scr->tscreen->event_filter = scr_event_cb; + + twin_screen_set_background(scr->tscreen, + pbt_background_load(scr->tscreen, filename_background)); + + assert(waiter_fd != -1); + + waiter_register(waiter_fd, WAIT_IN, (void *)pbt_twin_waiter_cb, + &scr->twin_ctx); + + return scr; + +fail_ctx_create: +fail_alloc: + return NULL; +} + +void pbt_window_redraw(twin_window_t *twindow) +{ + twin_window_damage(twindow, 0, 0, twindow->pixmap->width, + twindow->pixmap->height); + //twin_window_queue_paint(twindow); + twin_window_draw(twindow); +} -- cgit v1.2.1