Ecore_X(cb): Rework cursor code to be more like the Xlib version.

SVN revision: 62727
This commit is contained in:
Christopher Michael 2011-08-23 16:39:52 +00:00
parent b28995b31d
commit 4d6e04c512
3 changed files with 224 additions and 276 deletions

View File

@ -1,37 +1,33 @@
#include "ecore_xcb_private.h"
# include <xcb/xproto.h>
# include <xcb/xcb_image.h>
#ifdef ECORE_XCB_CURSOR
# include <xcb/render.h>
# include <xcb/xcb_renderutil.h>
#endif
/* local function prototypes */
static xcb_image_t *_ecore_xcb_cursor_image_create(int w, int h, int *pixels);
static Ecore_X_Cursor _ecore_xcb_cursor_image_load_cursor(Ecore_X_Window win, int w, int h, int hot_x, int hot_y, int *pixels, xcb_image_t *img);
#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_argb_cursor(Ecore_X_Window win, int w, int h, int hot_x, int hot_y, xcb_image_t *img);
static xcb_render_pictforminfo_t *_ecore_xcb_cursor_find_image_format(void);
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 xcb_render_pictforminfo_t *_ecore_xcb_cursor_format = NULL;
#endif
static int _ecore_xcb_cursor_size = 0;
static Eina_Bool _ecore_xcb_cursor = EINA_FALSE;
void
_ecore_xcb_cursor_init(void)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
#ifdef ECORE_XCB_CURSOR
/* NB: noop */
#endif
/* NB: No-op */
}
void
@ -42,53 +38,24 @@ _ecore_xcb_cursor_finalize(void)
#ifdef ECORE_XCB_CURSOR
_ecore_xcb_cursor = _ecore_xcb_render_argb_get();
/* find render pict format */
_ecore_xcb_cursor_format = _ecore_xcb_cursor_format_get();
#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)
/* 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 fails, try to guess from display size */
if (_ecore_xcb_cursor_size == 0)
/* 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 */
#endif
}
/*
* 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__);
font = xcb_generate_id(_ecore_xcb_conn);
xcb_open_font(_ecore_xcb_conn, font, strlen("cursor"), "cursor");
cursor = xcb_generate_id(_ecore_xcb_conn);
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_free(Ecore_X_Cursor cursor)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
xcb_free_cursor(_ecore_xcb_conn, cursor);
}
EAPI Eina_Bool
@ -107,45 +74,182 @@ ecore_x_cursor_new(Ecore_X_Window win, int *pixels, int w, int h, int hot_x, int
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (_ecore_xcb_cursor) // argb
{
if ((img = _ecore_xcb_cursor_image_create(w, h, pixels)))
{
#ifdef ECORE_XCB_CURSOR
cursor =
_ecore_xcb_cursor_image_load_argb_cursor(win, w, h,
hot_x, hot_y, img);
#else
cursor =
_ecore_xcb_cursor_image_load_cursor(win, w, h,
hot_x, hot_y, pixels, img);
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
}
else
DBG("Failed to create new cursor image");
}
else
{
if ((img = _ecore_xcb_cursor_image_create(w, h, pixels)))
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] =
{
cursor =
_ecore_xcb_cursor_image_load_cursor(win, w, h,
hot_x, hot_y, pixels, img);
{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++;
}
}
else
DBG("Failed to create new cursor image");
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;
}
if (cursor)
{
uint32_t mask, list;
return 0;
}
mask = XCB_CW_CURSOR;
list = cursor;
xcb_change_window_attributes(_ecore_xcb_conn, win, mask, &list);
ecore_x_flush();
}
EAPI void
ecore_x_cursor_free(Ecore_X_Cursor c)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
xcb_free_cursor(_ecore_xcb_conn, c);
}
EAPI Ecore_X_Cursor
ecore_x_cursor_shape_get(int shape)
{
Ecore_X_Cursor cursor = 0;
xcb_font_t font;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
}
@ -154,8 +258,8 @@ ecore_x_cursor_size_set(int size)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
// NB: size_set only needed for non-argb cursors
_ecore_xcb_cursor_size = size;
/* NB: May need to adjust size of current cursors here */
}
EAPI int
@ -167,173 +271,27 @@ ecore_x_cursor_size_get(void)
}
/* local functions */
static xcb_image_t *
_ecore_xcb_cursor_image_create(int w, int h, int *pixels)
{
// NB: May be able to use shm here, but the image NEEDS to be in
// native format
if (_ecore_xcb_cursor)
{
#ifdef ECORE_XCB_CURSOR
return xcb_image_create_native(_ecore_xcb_conn, w, h,
XCB_IMAGE_FORMAT_Z_PIXMAP,
32, pixels, (w * h * sizeof(int)),
(uint8_t *)pixels);
#else
return xcb_image_create_native(_ecore_xcb_conn, w, h,
XCB_IMAGE_FORMAT_Z_PIXMAP,
1, pixels, (w * h * sizeof(int)),
(uint8_t *)pixels);
#endif
}
else
{
return xcb_image_create_native(_ecore_xcb_conn, w, h,
XCB_IMAGE_FORMAT_Z_PIXMAP, 1,
NULL, ~0, NULL);
}
}
static Ecore_X_Cursor
_ecore_xcb_cursor_image_load_cursor(Ecore_X_Window win, int w, int h, int hot_x, int hot_y, int *pixels, xcb_image_t *img)
static xcb_render_pictforminfo_t *
_ecore_xcb_cursor_format_get(void)
{
xcb_pixmap_t pixmap, mask;
Ecore_X_Cursor cursor;
Ecore_X_GC gc;
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}
};
const xcb_render_query_pict_formats_reply_t *reply;
xcb_render_pictforminfo_t *ret = NULL;
pixmap = xcb_generate_id(_ecore_xcb_conn);
xcb_create_pixmap(_ecore_xcb_conn, 1, pixmap, win, w, h);
reply = xcb_render_util_query_formats(_ecore_xcb_conn);
if (reply)
ret = xcb_render_util_find_standard_format(reply,
XCB_PICT_STANDARD_ARGB_32);
mask = xcb_generate_id(_ecore_xcb_conn);
xcb_create_pixmap(_ecore_xcb_conn, 1, mask, win, w, h);
img->data = malloc(img->size);
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++;
}
}
// img->depth was 1
gc = ecore_x_gc_new(pixmap, 0, NULL);
xcb_put_image(_ecore_xcb_conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
pixmap, 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++;
}
}
// img->depth was 1
gc = ecore_x_gc_new(mask, 0, NULL);
xcb_put_image(_ecore_xcb_conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
mask, gc, w, h, 0, 0, 0, img->depth, img->size, img->data);
ecore_x_gc_free(gc);
cursor = xcb_generate_id(_ecore_xcb_conn);
xcb_create_cursor(_ecore_xcb_conn, cursor, pixmap, 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, pixmap);
xcb_free_pixmap(_ecore_xcb_conn, mask);
ecore_x_flush();
return cursor;
return ret;
}
#endif
static void
_ecore_xcb_cursor_default_size_get(void)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
/* char *v = NULL; */
/* v = getenv("XCURSOR_SIZE"); */
@ -345,6 +303,8 @@ _ecore_xcb_cursor_default_size_get(void)
static void
_ecore_xcb_cursor_dpi_size_get(void)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
/* int v = 0; */
/* v = _ecore_xcb_resource_get_int("Xft", "dpi"); */
@ -356,6 +316,8 @@ _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;
@ -364,53 +326,39 @@ _ecore_xcb_cursor_guess_size(void)
#ifdef ECORE_XCB_CURSOR
static Ecore_X_Cursor
_ecore_xcb_cursor_image_load_argb_cursor(Ecore_X_Window win, int w, int h, int hot_x, int hot_y, xcb_image_t *img)
_ecore_xcb_cursor_image_load_cursor(xcb_image_t *img, int hot_x, int hot_y)
{
xcb_pixmap_t pixmap;
xcb_render_picture_t pict;
Ecore_X_Cursor cursor;
Ecore_X_Cursor cursor = 0;
Ecore_X_GC gc;
xcb_pixmap_t pmap;
xcb_render_picture_t pict;
if (!_ecore_xcb_cursor_format)
_ecore_xcb_cursor_format = _ecore_xcb_cursor_find_image_format();
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);
pixmap = xcb_generate_id(_ecore_xcb_conn);
xcb_create_pixmap(_ecore_xcb_conn, 32, pixmap, win, w, h);
// img->depth was 32
gc = ecore_x_gc_new(pixmap, 0, NULL);
xcb_put_image(_ecore_xcb_conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
pixmap, gc, w, h, 0, 0, 0,
img->depth, img->size, img->data);
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, pixmap,
xcb_render_create_picture(_ecore_xcb_conn, pict, pmap,
_ecore_xcb_cursor_format->id, 0, NULL);
xcb_free_pixmap(_ecore_xcb_conn, pixmap);
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);
ecore_x_flush();
return cursor;
}
static xcb_render_pictforminfo_t *
_ecore_xcb_cursor_find_image_format(void)
{
const xcb_render_query_pict_formats_reply_t *reply;
xcb_render_pictforminfo_t *ret = NULL;
reply = xcb_render_util_query_formats(_ecore_xcb_conn);
if (reply)
{
ret = xcb_render_util_find_standard_format(reply,
XCB_PICT_STANDARD_ARGB_32);
// free(reply);
}
return ret;
}
#endif
static void
_ecore_xcb_cursor_image_destroy(xcb_image_t *img)
{
if (img) xcb_image_destroy(img);
}

View File

@ -1,7 +1,6 @@
#include "ecore_xcb_private.h"
#include <sys/ipc.h>
#include <sys/shm.h>
#include <xcb/xcb_image.h>
#include <xcb/xcb_event.h>
#include <xcb/shm.h>
@ -19,7 +18,6 @@ struct _Ecore_X_Image
/* local function prototypes */
static void _ecore_xcb_image_shm_check(void);
static void _ecore_xcb_image_shm_create(Ecore_X_Image *im);
static xcb_image_t *_ecore_xcb_image_create_native(int w, int h, xcb_image_format_t format, uint8_t depth, void *base, uint32_t bytes, uint8_t *data);
static xcb_format_t *_ecore_xcb_image_find_format(const xcb_setup_t *setup, uint8_t depth);
/* local variables */
@ -586,7 +584,6 @@ _ecore_xcb_image_shm_create(Ecore_X_Image *im)
if (!im->xim) return;
im->shminfo.shmid = shmget(IPC_PRIVATE, im->xim->size, (IPC_CREAT | 0666));
// shmget(IPC_PRIVATE, im->xim->stride * im->xim->height, (IPC_CREAT | 0666));
if (im->shminfo.shmid == (uint32_t)-1)
{
xcb_image_destroy(im->xim);
@ -618,7 +615,7 @@ _ecore_xcb_image_shm_create(Ecore_X_Image *im)
im->bpp = 4;
}
static xcb_image_t *
xcb_image_t *
_ecore_xcb_image_create_native(int w, int h, xcb_image_format_t format, uint8_t depth, void *base, uint32_t bytes, uint8_t *data)
{
static uint8_t dpth = 0;

View File

@ -13,6 +13,7 @@
# include <xcb/xcb.h>
# include <xcb/bigreq.h>
# include <xcb/shm.h>
# include <xcb/xcb_image.h>
/* EFL includes */
# include "Ecore.h"
@ -334,4 +335,6 @@ Ecore_X_Window_State _ecore_xcb_netwm_window_state_get(Ecore_X_Atom atom);
int _ecore_xcb_error_handle(xcb_generic_error_t *err);
int _ecore_xcb_io_error_handle(xcb_generic_error_t *err);
xcb_image_t *_ecore_xcb_image_create_native(int w, int h, xcb_image_format_t format, uint8_t depth, void *base, uint32_t bytes, uint8_t *data);
#endif