1 #include "ecore_xcb_private.h"
2 #ifdef ECORE_XCB_CURSOR
3 # include <xcb/render.h>
4 # include <xcb/xcb_renderutil.h>
7 /* local function prototypes */
8 #ifdef ECORE_XCB_CURSOR
9 static xcb_render_pictforminfo_t *_ecore_xcb_cursor_format_get(void);
11 static void _ecore_xcb_cursor_default_size_get(void);
12 static void _ecore_xcb_cursor_dpi_size_get(void);
13 static void _ecore_xcb_cursor_guess_size(void);
14 #ifdef ECORE_XCB_CURSOR
15 static Ecore_X_Cursor _ecore_xcb_cursor_image_load_cursor(xcb_image_t *img,
19 static void _ecore_xcb_cursor_image_destroy(xcb_image_t *img);
22 static int _ecore_xcb_cursor_size = 0;
23 static Eina_Bool _ecore_xcb_cursor = EINA_FALSE;
24 #ifdef ECORE_XCB_CURSOR
25 static uint32_t _ecore_xcb_cursor_format_id = 0;
26 // static xcb_render_pictforminfo_t *_ecore_xcb_cursor_format = NULL;
30 _ecore_xcb_cursor_init(void)
32 LOGFN(__FILE__, __LINE__, __FUNCTION__);
37 _ecore_xcb_cursor_finalize(void)
39 LOGFN(__FILE__, __LINE__, __FUNCTION__);
41 #ifdef ECORE_XCB_CURSOR
42 _ecore_xcb_cursor = _ecore_xcb_render_argb_get();
44 /* find render pict format */
45 if (_ecore_xcb_cursor_format_id <= 0)
46 _ecore_xcb_cursor_format_id = _ecore_xcb_cursor_format_get()->id;
49 /* try to grab cursor size from XDefaults */
50 _ecore_xcb_cursor_default_size_get();
52 /* if that failed, try to get it from Xft Dpi setting */
53 if (_ecore_xcb_cursor_size == 0)
54 _ecore_xcb_cursor_dpi_size_get();
56 /* if that failed, try to guess from display size */
57 if (_ecore_xcb_cursor_size == 0)
58 _ecore_xcb_cursor_guess_size();
60 /* NB: Would normally add theme stuff here, but E cursor does not support
61 * xcursor themes. Delay parsing that stuff out until such time if/when the
62 * user selects to use X Cursor, rather than E cursor */
66 ecore_x_cursor_color_supported_get(void)
68 LOGFN(__FILE__, __LINE__, __FUNCTION__);
70 return _ecore_xcb_cursor;
74 ecore_x_cursor_new(Ecore_X_Window win,
81 Ecore_X_Cursor cursor = 0;
84 // LOGFN(__FILE__, __LINE__, __FUNCTION__);
87 #ifdef ECORE_XCB_CURSOR
88 if (_ecore_xcb_cursor)
90 img = _ecore_xcb_image_create_native(w, h, XCB_IMAGE_FORMAT_Z_PIXMAP,
91 32, NULL, (w * h * sizeof(int)),
93 cursor = _ecore_xcb_cursor_image_load_cursor(img, hot_x, hot_y);
94 _ecore_xcb_cursor_image_destroy(img);
101 xcb_pixmap_t pmap, mask;
103 uint8_t fr = 0x00, fg = 0x00, fb = 0x00;
104 uint8_t br = 0xff, bg = 0xff, bb = 0xff;
105 uint32_t brightest = 0, darkest = 255 * 3;
107 const uint32_t dither[2][2] =
113 img = _ecore_xcb_image_create_native(w, h, XCB_IMAGE_FORMAT_Z_PIXMAP,
115 if (img->data) free(img->data);
116 img->data = malloc(img->size);
118 pmap = xcb_generate_id(_ecore_xcb_conn);
119 xcb_create_pixmap(_ecore_xcb_conn, 1, pmap, win, w, h);
120 mask = xcb_generate_id(_ecore_xcb_conn);
121 xcb_create_pixmap(_ecore_xcb_conn, 1, mask, win, w, h);
123 pix = (uint32_t *)pixels;
124 for (y = 0; y < h; y++)
126 for (x = 0; x < w; x++)
130 a = (pix[0] >> 24) & 0xff;
131 r = (pix[0] >> 16) & 0xff;
132 g = (pix[0] >> 8) & 0xff;
136 if ((uint32_t)(r + g + b) > brightest)
138 brightest = r + g + b;
144 if ((uint32_t)(r + g + b) < darkest)
156 pix = (uint32_t *)pixels;
157 for (y = 0; y < h; y++)
159 for (x = 0; x < w; x++)
165 r = (pix[0] >> 16) & 0xff;
166 g = (pix[0] >> 8) & 0xff;
169 ((r - fr) * (r - fr)) +
170 ((g - fg) * (g - fg)) +
171 ((b - fb) * (b - fb));
173 ((r - br) * (r - br)) +
174 ((g - bg) * (g - bg)) +
175 ((b - bb) * (b - bb));
178 v = (((d2 * 255) / (d1 + d2)) * 5) / 256;
179 if (v > dither[x & 0x1][y & 0x1])
187 xcb_image_put_pixel(img, x, y, v);
192 gc = ecore_x_gc_new(pmap, 0, NULL);
193 xcb_put_image(_ecore_xcb_conn, img->format, pmap, gc, w, h,
194 0, 0, 0, img->depth, img->size, img->data);
197 pix = (uint32_t *)pixels;
198 for (y = 0; y < h; y++)
200 for (x = 0; x < w; x++)
204 v = (((pix[0] >> 24) & 0xff) * 5) / 256;
205 if (v > dither[x & 0x1][y & 0x1])
210 xcb_image_put_pixel(img, x, y, v);
215 gc = ecore_x_gc_new(mask, 0, NULL);
216 xcb_put_image(_ecore_xcb_conn, img->format, mask, gc, w, h,
217 0, 0, 0, img->depth, img->size, img->data);
220 if (img->data) free(img->data);
221 _ecore_xcb_cursor_image_destroy(img);
223 cursor = xcb_generate_id(_ecore_xcb_conn);
224 xcb_create_cursor(_ecore_xcb_conn, cursor, pmap, mask,
225 fr << 8 | fr, fg << 8 | fg, fb << 8 | fb,
226 br << 8 | br, bg << 8 | bg, bb << 8 | bb,
229 xcb_free_pixmap(_ecore_xcb_conn, pmap);
230 xcb_free_pixmap(_ecore_xcb_conn, mask);
239 ecore_x_cursor_free(Ecore_X_Cursor c)
241 // LOGFN(__FILE__, __LINE__, __FUNCTION__);
244 xcb_free_cursor(_ecore_xcb_conn, c);
248 * Returns the cursor for the given shape.
249 * Note that the return value must not be freed with
250 * ecore_x_cursor_free()!
253 ecore_x_cursor_shape_get(int shape)
255 Ecore_X_Cursor cursor = 0;
258 LOGFN(__FILE__, __LINE__, __FUNCTION__);
261 font = xcb_generate_id(_ecore_xcb_conn);
262 xcb_open_font(_ecore_xcb_conn, font, strlen("cursor"), "cursor");
264 cursor = xcb_generate_id(_ecore_xcb_conn);
265 /* FIXME: Add request check ?? */
266 xcb_create_glyph_cursor(_ecore_xcb_conn, cursor, font, font,
267 shape, shape + 1, 0, 0, 0, 65535, 65535, 65535);
269 xcb_close_font(_ecore_xcb_conn, font);
274 ecore_x_cursor_size_set(int size)
276 LOGFN(__FILE__, __LINE__, __FUNCTION__);
278 _ecore_xcb_cursor_size = size;
279 /* NB: May need to adjust size of current cursors here */
283 ecore_x_cursor_size_get(void)
285 LOGFN(__FILE__, __LINE__, __FUNCTION__);
287 return _ecore_xcb_cursor_size;
290 /* local functions */
291 #ifdef ECORE_XCB_CURSOR
292 static xcb_render_pictforminfo_t *
293 _ecore_xcb_cursor_format_get(void)
295 const xcb_render_query_pict_formats_reply_t *reply;
296 xcb_render_pictforminfo_t *ret = NULL;
300 reply = xcb_render_util_query_formats(_ecore_xcb_conn);
302 ret = xcb_render_util_find_standard_format(reply,
303 XCB_PICT_STANDARD_ARGB_32);
311 _ecore_xcb_cursor_default_size_get(void)
316 LOGFN(__FILE__, __LINE__, __FUNCTION__);
318 s = getenv("XCURSOR_SIZE");
321 _ecore_xcb_xdefaults_init();
322 v = _ecore_xcb_xdefaults_int_get("Xcursor", "size");
323 _ecore_xcb_xdefaults_shutdown();
327 if (v) _ecore_xcb_cursor_size = ((v * 16) / 72);
331 _ecore_xcb_cursor_dpi_size_get(void)
335 LOGFN(__FILE__, __LINE__, __FUNCTION__);
337 _ecore_xcb_xdefaults_init();
338 v = _ecore_xcb_xdefaults_int_get("Xft", "dpi");
339 if (v) _ecore_xcb_cursor_size = ((v * 16) / 72);
340 _ecore_xcb_xdefaults_shutdown();
344 _ecore_xcb_cursor_guess_size(void)
346 int w = 0, h = 0, s = 0;
348 LOGFN(__FILE__, __LINE__, __FUNCTION__);
350 ecore_x_screen_size_get(_ecore_xcb_screen, &w, &h);
353 _ecore_xcb_cursor_size = (s / 48);
356 #ifdef ECORE_XCB_CURSOR
357 static Ecore_X_Cursor
358 _ecore_xcb_cursor_image_load_cursor(xcb_image_t *img,
362 Ecore_X_Cursor cursor = 0;
365 xcb_render_picture_t pict;
369 pmap = xcb_generate_id(_ecore_xcb_conn);
370 xcb_create_pixmap(_ecore_xcb_conn, img->depth, pmap,
371 ((xcb_screen_t *)_ecore_xcb_screen)->root,
372 img->width, img->height);
374 gc = ecore_x_gc_new(pmap, 0, NULL);
375 xcb_put_image(_ecore_xcb_conn, img->format, pmap, gc,
376 img->width, img->height, 0, 0, 0, img->depth,
377 img->size, img->data);
380 pict = xcb_generate_id(_ecore_xcb_conn);
381 xcb_render_create_picture(_ecore_xcb_conn, pict, pmap,
382 _ecore_xcb_cursor_format_id, 0, NULL);
383 xcb_free_pixmap(_ecore_xcb_conn, pmap);
385 cursor = xcb_generate_id(_ecore_xcb_conn);
386 xcb_render_create_cursor(_ecore_xcb_conn, cursor, pict, hot_x, hot_y);
387 xcb_render_free_picture(_ecore_xcb_conn, pict);
395 _ecore_xcb_cursor_image_destroy(xcb_image_t *img)
398 if (img) xcb_image_destroy(img);