# HG changeset patch # User wycc # Date 1286204636 -28800 # Node ID 095cf170f5fdee3f6543a73636fd6013b46d6fd2 # Parent 55767e44443668e9a290ca5b8bddf427951541df# Parent 62ef69e02e8560d7bd6a9f796064a52344819a55 Merge from the head diff -r 55767e444436 -r 095cf170f5fd include/Makefile.am --- a/include/Makefile.am Sun Oct 03 07:42:07 2010 +0800 +++ b/include/Makefile.am Mon Oct 04 23:03:56 2010 +0800 @@ -12,9 +12,16 @@ mb_shapes.h \ mb_tools.h \ mb_prop.h \ - mb_X_supp.h \ mb_img_ldr.h \ mb_af.h \ mb_ani_menu.h \ mbbutton.h \ mb_so.h + +if X_BACKEND +include_HEADERS += mb_X_supp.h +endif + +if DFB_BACKEND +include_HEADERS += mb_dfb_supp.h +endif diff -r 55767e444436 -r 095cf170f5fd include/mb.h --- a/include/mb.h Sun Oct 03 07:42:07 2010 +0800 +++ b/include/mb.h Mon Oct 04 23:03:56 2010 +0800 @@ -10,6 +10,9 @@ #ifdef X_BACKEND #include "mb_X_supp.h" #endif +#ifdef DFB_BACKEND +#include "mb_dfb_supp.h" +#endif #include "mb_animate.h" #include "mb_shapes.h" diff -r 55767e444436 -r 095cf170f5fd include/mb_dfb_supp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/mb_dfb_supp.h Mon Oct 04 23:03:56 2010 +0800 @@ -0,0 +1,38 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +#ifndef __DFB_SUPP_H_ +#define __DFB_SUPP_H_ + +#include "mb_types.h" +#include "mb_timer.h" +#include "mb_redraw_man.h" +#include "mb_img_ldr.h" + +/*! \ingroup xkb + * @{ + */ +typedef struct _X_kb_info X_kb_info_t; + +struct _X_kb_event { + event_t event; + int keycode; + int sym; +}; +typedef struct _X_kb_event X_kb_event_t; + +/* @} */ + +typedef struct _X_MB_runtime X_MB_runtime_t; + +extern void X_MB_handle_connection(void *rt); +extern void *X_MB_new(const char *display_name, int w, int h); +extern void X_MB_free(void *xmb_rt); +extern void X_MB_free_keep_win(void *rt); + +extern subject_t *X_MB_kbevents(void *xmb_rt); +extern redraw_man_t *X_MB_rdman(void *xmb_rt); +extern mb_tman_t *X_MB_tman(void *xmb_rt); +extern ob_factory_t *X_MB_ob_factory(void *xmb_rt); +extern mb_img_ldr_t *X_MB_img_ldr(void *xmb_rt); + +#endif diff -r 55767e444436 -r 095cf170f5fd include/mb_graph_engine_cairo.h --- a/include/mb_graph_engine_cairo.h Sun Oct 03 07:42:07 2010 +0800 +++ b/include/mb_graph_engine_cairo.h Mon Oct 04 23:03:56 2010 +0800 @@ -20,6 +20,7 @@ #define mbe_scaled_font_text_extents cairo_scaled_font_text_extents #define mbe_image_surface_get_stride cairo_image_surface_get_stride #define mbe_image_surface_get_height cairo_image_surface_get_height +#define mbe_directfb_surface_create cairo_directfb_surface_create #define mbe_image_surface_get_width cairo_image_surface_get_width #define mbe_image_surface_get_data cairo_image_surface_get_data #define mbe_scaled_font_reference cairo_scaled_font_reference diff -r 55767e444436 -r 095cf170f5fd src/Makefile.am --- a/src/Makefile.am Sun Oct 03 07:42:07 2010 +0800 +++ b/src/Makefile.am Mon Oct 04 23:03:56 2010 +0800 @@ -38,6 +38,10 @@ libmbfly_la_SOURCES += X_supp.c endif +if DFB_BACKEND +libmbfly_la_SOURCES += dfb_supp.c +endif + libmbfly_la_LDFLAGS = if CAIRO_GRAPH_ENGINE diff -r 55767e444436 -r 095cf170f5fd src/dfb_supp.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dfb_supp.c Mon Oct 04 23:03:56 2010 +0800 @@ -0,0 +1,552 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 +#include +#include +#include +#include +#include +#include +#include "mb_graph_engine.h" +#include "mb_redraw_man.h" +#include "mb_timer.h" +#include "mb_dfb_supp.h" +#include "config.h" + +#define ERR -1 +#define OK 0 + +#define ONLY_MOUSE_MOVE_RAW 1 + +/*! \ingroup xkb + * @{ + */ +struct _X_kb_info { + int keycode_min, keycode_max; + int ksym_per_code; + subject_t *kbevents; + ob_factory_t *ob_factory; +}; + +/* @} */ +#define MAX_MONITORS 200 +typedef struct { + int type; + int fd; + mb_eventcb_t f; + void *arg; +} monitor_t; + +struct _X_MB_runtime { + IDirectFB *dfb; + IDirectFBSurface *primary; + mbe_surface_t *surface, *backend_surface; + mbe_pattern_t *surface_ptn; + mbe_t *cr, *backend_cr; + redraw_man_t *rdman; + mb_tman_t *tman; + mb_img_ldr_t *img_ldr; + int w, h; + + X_kb_info_t kbinfo; + monitor_t monitors[MAX_MONITORS]; + int n_monitor; + +#ifndef ONLY_MOUSE_MOVE_RAW + /* States */ + shape_t *last; +#endif + + /* + * Following variables are used by handle_single_x_event() + */ + int last_evt_type; /* Type of last event */ + int eflag; + int ex1, ey1, ex2, ey2; /* Aggregate expose events */ + int mflag; + int mx, my; /* Position of last motion event */ + int mbut_state; /* Button state of last motion event */ +}; + +/*! \defgroup xkb X Keyboard Handling + * + * Accept keyboard events from X server and delivery it to + * application through observer pattern. There is a subject, + * per X-connection, for that. + * @{ + */ +static int keycode2sym(X_kb_info_t *kbinfo, unsigned int keycode) { + int sym_idx; + int sym; + + sym_idx = kbinfo->ksym_per_code * (keycode - kbinfo->keycode_min); +/* sym = kbinfo->syms[sym_idx];*/ + return sym; +} + +static void X_kb_destroy(X_kb_info_t *kbinfo) { + subject_free(kbinfo->kbevents); +} + +/* @} */ + +static unsigned int get_button_state(unsigned int state) { + return 0; +} + +static unsigned int get_button(unsigned int button) { + return 0; +} + +/*! \brief Notify observers of the shape at specified + * position for mouse event. + * + * Observers of parent shapes may be called if the subject is not + * with SUBF_STOP_PROPAGATE flag. The subject of mouse event + * for a shape is returned by sh_get_mouse_event_subject(). + */ +static void notify_coord_or_shape(redraw_man_t *rdman, + mb_obj_t *obj, + co_aix x, co_aix y, int etype, + unsigned int state, + unsigned int button) { + mouse_event_t mouse_event; + subject_t *subject; + + mouse_event.event.type = etype; + mouse_event.x = x; + mouse_event.y = y; + mouse_event.but_state = state; + mouse_event.button = button; + + if(IS_MBO_SHAPES(obj)) + subject = sh_get_mouse_event_subject((shape_t *)obj); + else + subject = coord_get_mouse_event((coord_t *)obj); + + subject_notify(subject, (event_t *)&mouse_event); +} + +/*! \brief Handle motion event. + */ +static void +handle_motion_event(X_MB_runtime_t *rt) { + redraw_man_t *rdman = rt->rdman; + int x, y; + int state; + shape_t *shape; + coord_t *root; + int in_stroke; + + x = rt->mx; + y = rt->my; + state = rt->mbut_state; + + shape = find_shape_at_pos(rdman, x, y, + &in_stroke); +#ifdef ONLY_MOUSE_MOVE_RAW + if(shape != NULL) { + notify_coord_or_shape(rdman, (mb_obj_t *)shape, + x, y, EVT_MOUSE_MOVE_RAW, state, 0); + } else { + root = rdman_get_root(rdman); + notify_coord_or_shape(rdman, (mb_obj_t *)root, + x, y, EVT_MOUSE_MOVE_RAW, state, 0); + } +#else + if(shape != NULL) { + if(rt->last != shape) { + if(rt->last) + notify_coord_or_shape(rdman, rt->last, x, y, + EVT_MOUSE_OUT, state, 0); + notify_coord_or_shape(rdman, shape, x, y, + EVT_MOUSE_OVER, state, 0); + rt->last = shape; + } else + notify_coord_or_shape(rdman, shape, x, y, + EVT_MOUSE_MOVE, state, 0); + } else { + if(rt->last) { + notify_coord_or_shape(rdman, rt->last, x, y, + EVT_MOUSE_OUT, state, 0); + rt->last = NULL; + } + } +#endif + + rt->mflag = 0; +} + +/*! \brief Redraw exposed area. + */ +static void +handle_expose_event(X_MB_runtime_t *rt) { + redraw_man_t *rdman = rt->rdman; + int ex1, ey1, ex2, ey2; + + ex1 = rt->ex1; + ey1 = rt->ey1; + ex2 = rt->ex2; + ey2 = rt->ey2; + + rdman_redraw_area(rdman, ex1, ey1, (ex2 - ex1), (ey2 - ey1)); + + rt->eflag = 0; +} + +/*! \brief Call when no more event in an event iteration. + * + * No more event means event queue is emplty. This function will + * perform some actions according current internal state. + */ +static void +no_more_event(X_MB_runtime_t *rt) { + if(rt->mflag) + handle_motion_event(rt); + if(rt->eflag) + handle_expose_event(rt); +} + +/*! \brief Handle connection coming data and timeout of timers. + * + * \param display is a Display returned by XOpenDisplay(). + * \param rdman is a redraw manager. + * \param tman is a timer manager. + * + * The display is managed by specified rdman and tman. rdman draws + * on the display, and tman trigger actions according timers. + */ +void X_MB_handle_connection(void *be) { + X_MB_runtime_t *rt = (X_MB_runtime_t *) be; + redraw_man_t *rdman = rt->rdman; + mb_tman_t *tman = rt->tman; + int fd = 0; + mb_timeval_t now, tmo; + struct timeval tv; + fd_set rfds,wfds; + int nfds; + int r, r1,i; + + handle_x_event(rt); + +/* fd = XConnectionNumber(display);*/ + nfds = fd + 1; + while(1) { + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_SET(fd, &rfds); + for(i=0;in_monitor;i++) { + if (rt->monitors[i].type == MONITOR_READ) + FD_SET(rt->monitors[i].fd, &rfds); + else if (rt->monitors[i].type == MONITOR_WRITE) + FD_SET(rt->monitors[i].fd, &wfds); + } + + get_now(&now); + r = mb_tman_next_timeout(tman, &now, &tmo); + + if(r == 0) { + tv.tv_sec = MB_TIMEVAL_SEC(&tmo); + tv.tv_usec = MB_TIMEVAL_USEC(&tmo); + r1 = select(nfds, &rfds, NULL, NULL, &tv); + } else + r1 = select(nfds, &rfds, NULL, NULL, NULL); + + if(r1 == -1) { + perror("select"); + break; + } + + if(r1 == 0) { + get_now(&now); + mb_tman_handle_timeout(tman, &now); + rdman_redraw_changed(rdman); + } else if(FD_ISSET(fd, &rfds)){ + handle_x_event(rt); + } else { + for(i=0;in_monitor;i++) { + if (rt->monitors[i].type == MONITOR_READ) { + if (FD_ISSET(rt->monitors[i].fd, &rfds)) + rt->monitors[i].f(rt->monitors[i].fd,rt->monitors[i].arg); + } else if (rt->monitors[i].type == MONITOR_WRITE) { + if (FD_ISSET(rt->monitors[i].fd, &wfds)) + rt->monitors[i].f(rt->monitors[i].fd,rt->monitors[i].arg); + } + } + } + } +} + +#define ERR -1 +#define OK 0 + +static int dfb_init_connection(int w, int h, + IDirectFB **dfb, + IDirectFBSurface **primary) { + DFBSurfaceDescription dsc; + + DirectFBInit(NULL, NULL); + DirectFBCreate(dfb); + (*dfb)->SetCooperativeLevel(*dfb, DFSCL_FULLSCREEN); + dsc.flags = DSDESC_CAPS; + dsc.caps = DSCAPS_PRIMARY; + (*dfb)->CreateSurface(*dfb, &dsc, primary); + (*primary)->GetSize(*primary, &w, &h); + (*primary)->SetColor(*primary, 0xff, 0xff, 0xff, 0xff); + (*primary)->FillRectangle(*primary, 0, 0, w, h); + + return OK; +} + +/*! \brief Initialize a MadButterfy runtime for DirectFB. + * + * This one is very like X_MB_init(), except it accepts a + * X_MB_runtime_t object initialized with a display connected to a DirectFB + * server and an opened window. + * + * Following field of the X_MB_runtime_t object should be initialized. + * - w, h + * - win + * - dfb + * - primary + */ +static int X_MB_init_with_win_internal(X_MB_runtime_t *xmb_rt) { + mb_img_ldr_t *img_ldr; + int w, h; + + w = xmb_rt->w; + h = xmb_rt->h; + + xmb_rt->surface = + mbe_image_surface_create(MB_IFMT_ARGB32, w, h); + + xmb_rt->surface_ptn = + mbe_pattern_create_for_surface(xmb_rt->surface); + + if (xmb_rt->backend_surface == NULL) + xmb_rt->backend_surface = + mbe_directfb_surface_create(xmb_rt->dfb, xmb_rt->primary); + + xmb_rt->cr = mbe_create(xmb_rt->surface); + xmb_rt->backend_cr = mbe_create(xmb_rt->backend_surface); + + mbe_set_source(xmb_rt->backend_cr, xmb_rt->surface_ptn); + + xmb_rt->rdman = (redraw_man_t *)malloc(sizeof(redraw_man_t)); + redraw_man_init(xmb_rt->rdman, xmb_rt->cr, xmb_rt->backend_cr); + // FIXME: This is a wired loopback reference. This is inly required when we need + // to get the xmb_rt->tman for the animation. We should relocate the tman + // to the redraw_man_t instead. + xmb_rt->rdman->rt = xmb_rt; + + xmb_rt->tman = mb_tman_new(); + + img_ldr = simple_mb_img_ldr_new(""); + xmb_rt->img_ldr = img_ldr; + rdman_set_img_ldr(xmb_rt->rdman, img_ldr); + memset(xmb_rt->monitors,0,sizeof(xmb_rt->monitors)); + +#ifndef ONLY_MOUSE_MOVE_RAW + xmb_rt->last = NULL; +#endif + +/* X_kb_init(&xmb_rt->kbinfo, xmb_rt->display, xmb_rt->rdman);*/ + + return OK; +} + +/*! \brief Initialize a MadButterfy runtime for DirectFB. + * + * It setups a runtime environment to run MadButterfly with DirectFB. + * Users should specify width and height of the opening window. + */ +static int X_MB_init(X_MB_runtime_t *xmb_rt, const char *display_name, + int w, int h) { + int r; + + memset(xmb_rt, 0, sizeof(X_MB_runtime_t)); + + xmb_rt->w = w; + xmb_rt->h = h; + r = dfb_init_connection(w, h, &xmb_rt->dfb, &xmb_rt->primary); + + if(r != OK) + return ERR; + + r = X_MB_init_with_win_internal(xmb_rt); + + return r; +} + +static void X_MB_destroy(X_MB_runtime_t *xmb_rt) { + if (xmb_rt->rdman) { + redraw_man_destroy(xmb_rt->rdman); + free(xmb_rt->rdman); + } + + if (xmb_rt->tman) + mb_tman_free(xmb_rt->tman); + + if (xmb_rt->img_ldr) + MB_IMG_LDR_FREE(xmb_rt->img_ldr); + + if (xmb_rt->cr) + mbe_destroy(xmb_rt->cr); + + if (xmb_rt->backend_cr) + mbe_destroy(xmb_rt->backend_cr); + + if(xmb_rt->surface) + mbe_surface_destroy(xmb_rt->surface); + + if(xmb_rt->surface_ptn) + mbe_pattern_destroy(xmb_rt->surface_ptn); + + if(xmb_rt->backend_surface) + mbe_surface_destroy(xmb_rt->backend_surface); + + if (xmb_rt->primary) + xmb_rt->primary->Release(xmb_rt->primary); + + if (xmb_rt->dfb) + xmb_rt->dfb->Release(xmb_rt->dfb); +} + +void *X_MB_new(const char *display_name, int w, int h) { + X_MB_runtime_t *rt; + int r; + + rt = O_ALLOC(X_MB_runtime_t); + + if (rt == NULL) + return NULL; + + r = X_MB_init(rt, display_name, w, h); + + if (r != OK) { + free(rt); + return NULL; + } + + return rt; +} + +void X_MB_free(void *rt) { + X_MB_destroy((X_MB_runtime_t *) rt); + free(rt); +} + +/*! \brief Free runtime created with X_MB_new_with_win(). + */ +void +X_MB_free_keep_win(void *rt) { + X_MB_destroy_keep_win((X_MB_runtime_t *) rt); + free(rt); +} + +subject_t *X_MB_kbevents(void *rt) { + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + return xmb_rt->kbinfo.kbevents; +} + +redraw_man_t *X_MB_rdman(void *rt) { + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + return xmb_rt->rdman; +} + +mb_tman_t *X_MB_tman(void *rt) { + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + return xmb_rt->tman; +} + +ob_factory_t *X_MB_ob_factory(void *rt) { + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + ob_factory_t *factory; + + factory = rdman_get_ob_factory(xmb_rt->rdman); + return factory; +} + +mb_img_ldr_t *X_MB_img_ldr(void *rt) { + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + mb_img_ldr_t *img_ldr; + + img_ldr = xmb_rt->img_ldr; + + return img_ldr; +} + +void X_MB_add_event(void *rt, int type, int fd, mb_eventcb_t f,void *arg) +{ + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + int i; + + for(i=0;in_monitor;i++) { + if (xmb_rt->monitors[i].type == type && xmb_rt->monitors[i].fd == fd) { + xmb_rt->monitors[i].f = f; + xmb_rt->monitors[i].arg = arg; + return; + } + } + for(i=0;in_monitor;i++) { + if (xmb_rt->monitors[i].type == 0) { + xmb_rt->monitors[i].type = type; + xmb_rt->monitors[i].fd = fd; + xmb_rt->monitors[i].f = f; + xmb_rt->monitors[i].arg = arg; + return; + } + } + if (i == MAX_MONITORS) return; + xmb_rt->monitors[i].type = type; + xmb_rt->monitors[i].fd = fd; + xmb_rt->monitors[i].f = f; + xmb_rt->monitors[i].arg = arg; + i++; + xmb_rt->n_monitor=i; +} + +void X_MB_remove_event(void *rt, int type, int fd) +{ + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; + int i; + for(i=0;in_monitor;i++) { + if (xmb_rt->monitors[i].type == type && xmb_rt->monitors[i].fd == fd) { + xmb_rt->monitors[i].type = 0; + return; + } + } +} + +mb_backend_t backend = { X_MB_new, + X_MB_free, + X_MB_add_event, + X_MB_remove_event, + X_MB_handle_connection, + X_MB_kbevents, + X_MB_rdman, + X_MB_tman, + X_MB_ob_factory, + X_MB_img_ldr + }; + +/*! \defgroup x_supp_nodejs_sup Export functions for supporting nodejs plugin. + * + * These functions are for internal using. + * @{ + */ +/*! \brief Exported for nodejs plugin to call handle_x_event. + */ +void _X_MB_handle_x_event_for_nodejs(void *rt) { + handle_x_event((X_MB_runtime_t *)rt); +} + +/*! \brief Called at end of an iteration of X event loop. + */ +void +_X_MB_no_more_event(void *rt) { + X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *)rt; + + no_more_event(xmb_rt); +} + +/* @} */