From dd7595a3475407a7fa96a97393bae8c5220e8762 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Wed, 4 Jan 2012 18:41:13 +1000 Subject: Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje. Note that embryo wont be used, but I'm not sure yet if you can build edje without it. --- .../ecore/src/lib/ecore_x/xcb/ecore_xcb_cursor.c | 400 +++++++++++++++++++++ 1 file changed, 400 insertions(+) create mode 100644 libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_cursor.c (limited to 'libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_cursor.c') diff --git a/libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_cursor.c b/libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_cursor.c new file mode 100644 index 0000000..755df04 --- /dev/null +++ b/libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_cursor.c @@ -0,0 +1,400 @@ +#include "ecore_xcb_private.h" +#ifdef ECORE_XCB_CURSOR +# include +# include +#endif + +/* local function prototypes */ +#ifdef ECORE_XCB_CURSOR +static xcb_render_pictforminfo_t *_ecore_xcb_cursor_format_get(void); +#endif +static void _ecore_xcb_cursor_default_size_get(void); +static void _ecore_xcb_cursor_dpi_size_get(void); +static void _ecore_xcb_cursor_guess_size(void); +#ifdef ECORE_XCB_CURSOR +static Ecore_X_Cursor _ecore_xcb_cursor_image_load_cursor(xcb_image_t *img, + int hot_x, + int hot_y); +#endif +static void _ecore_xcb_cursor_image_destroy(xcb_image_t *img); + +/* local variables */ +static int _ecore_xcb_cursor_size = 0; +static Eina_Bool _ecore_xcb_cursor = EINA_FALSE; +#ifdef ECORE_XCB_CURSOR +static uint32_t _ecore_xcb_cursor_format_id = 0; +// static xcb_render_pictforminfo_t *_ecore_xcb_cursor_format = NULL; +#endif + +void +_ecore_xcb_cursor_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + /* NB: No-op */ +} + +void +_ecore_xcb_cursor_finalize(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_CURSOR + _ecore_xcb_cursor = _ecore_xcb_render_argb_get(); + + /* find render pict format */ + if (_ecore_xcb_cursor_format_id <= 0) + _ecore_xcb_cursor_format_id = _ecore_xcb_cursor_format_get()->id; +#endif + + /* try to grab cursor size from XDefaults */ + _ecore_xcb_cursor_default_size_get(); + + /* if that failed, try to get it from Xft Dpi setting */ + if (_ecore_xcb_cursor_size == 0) + _ecore_xcb_cursor_dpi_size_get(); + + /* if that failed, try to guess from display size */ + if (_ecore_xcb_cursor_size == 0) + _ecore_xcb_cursor_guess_size(); + + /* NB: Would normally add theme stuff here, but E cursor does not support + * xcursor themes. Delay parsing that stuff out until such time if/when the + * user selects to use X Cursor, rather than E cursor */ +} + +EAPI Eina_Bool +ecore_x_cursor_color_supported_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_cursor; +} + +EAPI Ecore_X_Cursor +ecore_x_cursor_new(Ecore_X_Window win, + int *pixels, + int w, + int h, + int hot_x, + int hot_y) +{ + Ecore_X_Cursor cursor = 0; + xcb_image_t *img; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_CURSOR + if (_ecore_xcb_cursor) + { + img = _ecore_xcb_image_create_native(w, h, XCB_IMAGE_FORMAT_Z_PIXMAP, + 32, NULL, (w * h * sizeof(int)), + (uint8_t *)pixels); + cursor = _ecore_xcb_cursor_image_load_cursor(img, hot_x, hot_y); + _ecore_xcb_cursor_image_destroy(img); + return cursor; + } + else +#endif + { + Ecore_X_GC gc; + xcb_pixmap_t pmap, mask; + uint32_t *pix; + uint8_t fr = 0x00, fg = 0x00, fb = 0x00; + uint8_t br = 0xff, bg = 0xff, bb = 0xff; + uint32_t brightest = 0, darkest = 255 * 3; + uint16_t x, y; + const uint32_t dither[2][2] = + { + {0, 2}, + {3, 1} + }; + + img = _ecore_xcb_image_create_native(w, h, XCB_IMAGE_FORMAT_Z_PIXMAP, + 1, NULL, ~0, NULL); + if (img->data) free(img->data); + img->data = malloc(img->size); + + pmap = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, 1, pmap, win, w, h); + mask = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, 1, mask, win, w, h); + + pix = (uint32_t *)pixels; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + uint8_t r, g, b, a; + + a = (pix[0] >> 24) & 0xff; + r = (pix[0] >> 16) & 0xff; + g = (pix[0] >> 8) & 0xff; + b = (pix[0]) & 0xff; + if (a > 0) + { + if ((uint32_t)(r + g + b) > brightest) + { + brightest = r + g + b; + br = r; + bg = g; + bb = b; + } + + if ((uint32_t)(r + g + b) < darkest) + { + darkest = r + g + b; + fr = r; + fg = g; + fb = b; + } + } + pix++; + } + } + + pix = (uint32_t *)pixels; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + uint32_t v; + uint8_t r, g, b; + int32_t d1, d2; + + r = (pix[0] >> 16) & 0xff; + g = (pix[0] >> 8) & 0xff; + b = (pix[0]) & 0xff; + d1 = + ((r - fr) * (r - fr)) + + ((g - fg) * (g - fg)) + + ((b - fb) * (b - fb)); + d2 = + ((r - br) * (r - br)) + + ((g - bg) * (g - bg)) + + ((b - bb) * (b - bb)); + if (d1 + d2) + { + v = (((d2 * 255) / (d1 + d2)) * 5) / 256; + if (v > dither[x & 0x1][y & 0x1]) + v = 1; + else + v = 0; + } + else + v = 0; + + xcb_image_put_pixel(img, x, y, v); + pix++; + } + } + + gc = ecore_x_gc_new(pmap, 0, NULL); + xcb_put_image(_ecore_xcb_conn, img->format, pmap, gc, w, h, + 0, 0, 0, img->depth, img->size, img->data); + ecore_x_gc_free(gc); + + pix = (uint32_t *)pixels; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + uint32_t v; + + v = (((pix[0] >> 24) & 0xff) * 5) / 256; + if (v > dither[x & 0x1][y & 0x1]) + v = 1; + else + v = 0; + + xcb_image_put_pixel(img, x, y, v); + pix++; + } + } + + gc = ecore_x_gc_new(mask, 0, NULL); + xcb_put_image(_ecore_xcb_conn, img->format, mask, gc, w, h, + 0, 0, 0, img->depth, img->size, img->data); + ecore_x_gc_free(gc); + + if (img->data) free(img->data); + _ecore_xcb_cursor_image_destroy(img); + + cursor = xcb_generate_id(_ecore_xcb_conn); + xcb_create_cursor(_ecore_xcb_conn, cursor, pmap, mask, + fr << 8 | fr, fg << 8 | fg, fb << 8 | fb, + br << 8 | br, bg << 8 | bg, bb << 8 | bb, + hot_x, hot_y); + + xcb_free_pixmap(_ecore_xcb_conn, pmap); + xcb_free_pixmap(_ecore_xcb_conn, mask); + + return cursor; + } + + return 0; +} + +EAPI void +ecore_x_cursor_free(Ecore_X_Cursor c) +{ +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_free_cursor(_ecore_xcb_conn, c); +} + +/* + * Returns the cursor for the given shape. + * Note that the return value must not be freed with + * ecore_x_cursor_free()! + */ +EAPI Ecore_X_Cursor +ecore_x_cursor_shape_get(int shape) +{ + Ecore_X_Cursor cursor = 0; + xcb_font_t font; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + font = xcb_generate_id(_ecore_xcb_conn); + xcb_open_font(_ecore_xcb_conn, font, strlen("cursor"), "cursor"); + + cursor = xcb_generate_id(_ecore_xcb_conn); + /* FIXME: Add request check ?? */ + xcb_create_glyph_cursor(_ecore_xcb_conn, cursor, font, font, + shape, shape + 1, 0, 0, 0, 65535, 65535, 65535); + + xcb_close_font(_ecore_xcb_conn, font); + return cursor; +} + +EAPI void +ecore_x_cursor_size_set(int size) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_cursor_size = size; + /* NB: May need to adjust size of current cursors here */ +} + +EAPI int +ecore_x_cursor_size_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_cursor_size; +} + +/* local functions */ +#ifdef ECORE_XCB_CURSOR +static xcb_render_pictforminfo_t * +_ecore_xcb_cursor_format_get(void) +{ + const xcb_render_query_pict_formats_reply_t *reply; + xcb_render_pictforminfo_t *ret = NULL; + + CHECK_XCB_CONN; + + reply = xcb_render_util_query_formats(_ecore_xcb_conn); + if (reply) + ret = xcb_render_util_find_standard_format(reply, + XCB_PICT_STANDARD_ARGB_32); + + return ret; +} + +#endif + +static void +_ecore_xcb_cursor_default_size_get(void) +{ + char *s = NULL; + int v = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + s = getenv("XCURSOR_SIZE"); + if (!s) + { + _ecore_xcb_xdefaults_init(); + v = _ecore_xcb_xdefaults_int_get("Xcursor", "size"); + _ecore_xcb_xdefaults_shutdown(); + } + else + v = atoi(s); + if (v) _ecore_xcb_cursor_size = ((v * 16) / 72); +} + +static void +_ecore_xcb_cursor_dpi_size_get(void) +{ + int v = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_xdefaults_init(); + v = _ecore_xcb_xdefaults_int_get("Xft", "dpi"); + if (v) _ecore_xcb_cursor_size = ((v * 16) / 72); + _ecore_xcb_xdefaults_shutdown(); +} + +static void +_ecore_xcb_cursor_guess_size(void) +{ + int w = 0, h = 0, s = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_screen_size_get(_ecore_xcb_screen, &w, &h); + if (h < w) s = h; + else s = w; + _ecore_xcb_cursor_size = (s / 48); +} + +#ifdef ECORE_XCB_CURSOR +static Ecore_X_Cursor +_ecore_xcb_cursor_image_load_cursor(xcb_image_t *img, + int hot_x, + int hot_y) +{ + Ecore_X_Cursor cursor = 0; + Ecore_X_GC gc; + xcb_pixmap_t pmap; + xcb_render_picture_t pict; + + CHECK_XCB_CONN; + + pmap = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, img->depth, pmap, + ((xcb_screen_t *)_ecore_xcb_screen)->root, + img->width, img->height); + + gc = ecore_x_gc_new(pmap, 0, NULL); + xcb_put_image(_ecore_xcb_conn, img->format, pmap, gc, + img->width, img->height, 0, 0, 0, img->depth, + img->size, img->data); + ecore_x_gc_free(gc); + + pict = xcb_generate_id(_ecore_xcb_conn); + xcb_render_create_picture(_ecore_xcb_conn, pict, pmap, + _ecore_xcb_cursor_format_id, 0, NULL); + xcb_free_pixmap(_ecore_xcb_conn, pmap); + + cursor = xcb_generate_id(_ecore_xcb_conn); + xcb_render_create_cursor(_ecore_xcb_conn, cursor, pict, hot_x, hot_y); + xcb_render_free_picture(_ecore_xcb_conn, pict); + + return cursor; +} + +#endif + +static void +_ecore_xcb_cursor_image_destroy(xcb_image_t *img) +{ + CHECK_XCB_CONN; + if (img) xcb_image_destroy(img); +} + -- cgit v1.1