1 #include "ecore_xcb_private.h"
2 # include <xcb/xproto.h>
3 # include <xcb/xcb_image.h>
4 #ifdef ECORE_XCB_CURSOR
5 # include <xcb/render.h>
6 # include <xcb/xcb_renderutil.h>
9 /* local function prototypes */
10 static xcb_image_t *_ecore_xcb_cursor_image_create(int w, int h, int *pixels);
11 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);
12 #ifdef ECORE_XCB_CURSOR
13 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);
14 static xcb_render_pictforminfo_t *_ecore_xcb_cursor_find_image_format(void);
18 #ifdef ECORE_XCB_CURSOR
19 static xcb_render_pictforminfo_t *_ecore_xcb_cursor_format = NULL;
21 static int _ecore_xcb_cursor_size = 0;
22 static Eina_Bool _ecore_xcb_cursor = EINA_FALSE;
25 _ecore_xcb_cursor_init(void)
27 LOGFN(__FILE__, __LINE__, __FUNCTION__);
29 #ifdef ECORE_XCB_CURSOR
35 _ecore_xcb_cursor_finalize(void)
37 LOGFN(__FILE__, __LINE__, __FUNCTION__);
39 #ifdef ECORE_XCB_CURSOR
40 _ecore_xcb_cursor = _ecore_xcb_render_argb_get();
45 * Returns the cursor for the given shape.
46 * Note that the return value must not be freed with
47 * ecore_x_cursor_free()!
50 ecore_x_cursor_shape_get(int shape)
52 Ecore_X_Cursor cursor = 0;
55 LOGFN(__FILE__, __LINE__, __FUNCTION__);
57 font = xcb_generate_id(_ecore_xcb_conn);
58 xcb_open_font(_ecore_xcb_conn, font, strlen("cursor"), "cursor");
60 cursor = xcb_generate_id(_ecore_xcb_conn);
61 xcb_create_glyph_cursor(_ecore_xcb_conn, cursor, font, font,
62 shape, shape + 1, 0, 0, 0, 65535, 65535, 65535);
63 xcb_close_font(_ecore_xcb_conn, font);
69 ecore_x_cursor_free(Ecore_X_Cursor cursor)
71 LOGFN(__FILE__, __LINE__, __FUNCTION__);
73 xcb_free_cursor(_ecore_xcb_conn, cursor);
77 ecore_x_cursor_color_supported_get(void)
79 LOGFN(__FILE__, __LINE__, __FUNCTION__);
81 return _ecore_xcb_cursor;
85 ecore_x_cursor_new(Ecore_X_Window win, int *pixels, int w, int h, int hot_x, int hot_y)
87 Ecore_X_Cursor cursor = 0;
90 LOGFN(__FILE__, __LINE__, __FUNCTION__);
92 if (_ecore_xcb_cursor) // argb
94 if ((img = _ecore_xcb_cursor_image_create(w, h, pixels)))
96 #ifdef ECORE_XCB_CURSOR
98 _ecore_xcb_cursor_image_load_argb_cursor(win, w, h,
102 _ecore_xcb_cursor_image_load_cursor(win, w, h,
103 hot_x, hot_y, pixels, img);
107 DBG("Failed to create new cursor image");
111 if ((img = _ecore_xcb_cursor_image_create(w, h, pixels)))
114 _ecore_xcb_cursor_image_load_cursor(win, w, h,
115 hot_x, hot_y, pixels, img);
118 DBG("Failed to create new cursor image");
125 mask = XCB_CW_CURSOR;
127 xcb_change_window_attributes(_ecore_xcb_conn, win, mask, &list);
134 ecore_x_cursor_size_set(int size)
136 LOGFN(__FILE__, __LINE__, __FUNCTION__);
138 // NB: size_set only needed for non-argb cursors
139 _ecore_xcb_cursor_size = size;
143 ecore_x_cursor_size_get(void)
145 LOGFN(__FILE__, __LINE__, __FUNCTION__);
147 return _ecore_xcb_cursor_size;
150 /* local functions */
152 _ecore_xcb_cursor_image_create(int w, int h, int *pixels)
154 // NB: May be able to use shm here, but the image NEEDS to be in
156 if (_ecore_xcb_cursor)
158 #ifdef ECORE_XCB_CURSOR
159 return xcb_image_create_native(_ecore_xcb_conn, w, h,
160 XCB_IMAGE_FORMAT_Z_PIXMAP,
161 32, pixels, (w * h * sizeof(int)), // 32
164 return xcb_image_create_native(_ecore_xcb_conn, w, h,
165 XCB_IMAGE_FORMAT_Z_PIXMAP,
166 1, pixels, (w * h * sizeof(int)), // 32
172 return xcb_image_create_native(_ecore_xcb_conn, w, h,
173 XCB_IMAGE_FORMAT_Z_PIXMAP, 1,
178 static Ecore_X_Cursor
179 _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)
181 xcb_pixmap_t pixmap, mask;
182 Ecore_X_Cursor cursor;
185 uint8_t fr = 0x00, fg = 0x00, fb = 0x00;
186 uint8_t br = 0xff, bg = 0xff, bb = 0xff;
187 uint32_t brightest = 0, darkest = 255 * 3;
189 const uint32_t dither[2][2] =
195 pixmap = xcb_generate_id(_ecore_xcb_conn);
196 xcb_create_pixmap(_ecore_xcb_conn, 1, pixmap, win, w, h);
198 mask = xcb_generate_id(_ecore_xcb_conn);
199 xcb_create_pixmap(_ecore_xcb_conn, 1, mask, win, w, h);
201 img->data = malloc(img->size);
203 pix = (uint32_t *)pixels;
204 for (y = 0; y < h; y++)
206 for (x = 0; x < w; x++)
210 a = (pix[0] >> 24) & 0xff;
211 r = (pix[0] >> 16) & 0xff;
212 g = (pix[0] >> 8) & 0xff;
216 if ((uint32_t)(r + g + b) > brightest)
218 brightest = r + g + b;
224 if ((uint32_t)(r + g + b) < darkest)
236 pix = (uint32_t *)pixels;
237 for (y = 0; y < h; y++)
239 for (x = 0; x < w; x++)
245 r = (pix[0] >> 16) & 0xff;
246 g = (pix[0] >> 8) & 0xff;
249 ((r - fr) * (r - fr)) +
250 ((g - fg) * (g - fg)) +
251 ((b - fb) * (b - fb));
253 ((r - br) * (r - br)) +
254 ((g - bg) * (g - bg)) +
255 ((b - bb) * (b - bb));
258 v = (((d2 * 255) / (d1 + d2)) * 5) / 256;
259 if (v > dither[x & 0x1][y & 0x1])
267 xcb_image_put_pixel(img, x, y, v);
273 gc = ecore_x_gc_new(pixmap, 0, NULL);
274 xcb_put_image(_ecore_xcb_conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
275 pixmap, gc, w, h, 0, 0, 0, img->depth, img->size, img->data);
278 pix = (uint32_t *)pixels;
279 for (y = 0; y < h; y++)
281 for (x = 0; x < w; x++)
285 v = (((pix[0] >> 24) & 0xff) * 5) / 256;
286 if (v > dither[x & 0x1][y & 0x1])
291 xcb_image_put_pixel(img, x, y, v);
297 gc = ecore_x_gc_new(mask, 0, NULL);
298 xcb_put_image(_ecore_xcb_conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
299 mask, gc, w, h, 0, 0, 0, img->depth, img->size, img->data);
302 cursor = xcb_generate_id(_ecore_xcb_conn);
303 xcb_create_cursor(_ecore_xcb_conn, cursor, pixmap, mask,
304 fr << 8 | fr, fg << 8 | fg, fb << 8 | fb,
305 br << 8 | br, bg << 8 | bg, bb << 8 | bb,
308 xcb_free_pixmap(_ecore_xcb_conn, pixmap);
309 xcb_free_pixmap(_ecore_xcb_conn, mask);
314 #ifdef ECORE_XCB_CURSOR
315 static Ecore_X_Cursor
316 _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)
319 xcb_render_picture_t pict;
320 Ecore_X_Cursor cursor;
323 if (!_ecore_xcb_cursor_format)
324 _ecore_xcb_cursor_format = _ecore_xcb_cursor_find_image_format();
326 pixmap = xcb_generate_id(_ecore_xcb_conn);
327 xcb_create_pixmap(_ecore_xcb_conn, 32, pixmap, win, w, h);
330 gc = ecore_x_gc_new(pixmap, 0, NULL);
331 xcb_put_image(_ecore_xcb_conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
332 pixmap, gc, w, h, 0, 0, 0,
333 img->depth, img->size, img->data);
336 pict = xcb_generate_id(_ecore_xcb_conn);
337 xcb_render_create_picture(_ecore_xcb_conn, pict, pixmap,
338 _ecore_xcb_cursor_format->id, 0, NULL);
339 xcb_free_pixmap(_ecore_xcb_conn, pixmap);
341 cursor = xcb_generate_id(_ecore_xcb_conn);
342 xcb_render_create_cursor(_ecore_xcb_conn, cursor, pict, hot_x, hot_y);
343 xcb_render_free_picture(_ecore_xcb_conn, pict);
348 static xcb_render_pictforminfo_t *
349 _ecore_xcb_cursor_find_image_format(void)
351 const xcb_render_query_pict_formats_reply_t *reply;
352 xcb_render_pictforminfo_t *ret = NULL;
354 reply = xcb_render_util_query_formats(_ecore_xcb_conn);
357 ret = xcb_render_util_find_standard_format(reply,
358 XCB_PICT_STANDARD_ARGB_32);