1dcea4db765298673d36d3569eea6aaea7b06984
[framework/uifw/ecore.git] / src / lib / ecore_x / xcb / ecore_xcb_cursor.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #include "ecore_xcb_private.h"
6 #include <xcb/shm.h>
7 #include <xcb/xcb_image.h>
8
9
10 extern int _ecore_xcb_xcursor;
11
12
13 EAPI int
14 ecore_x_cursor_color_supported_get(void)
15 {
16    return _ecore_xcb_xcursor;
17 }
18
19 EAPI Ecore_X_Cursor
20 ecore_x_cursor_new(Ecore_X_Window window,
21                    int           *pixels,
22                    int            w,
23                    int            h,
24                    int            hot_x,
25                    int            hot_y)
26 {
27    Ecore_X_Cursor cursor = 0;
28
29 #ifdef ECORE_XCB_CURSOR
30    if (_ecore_x_xcursor)
31      {
32         Cursor c;
33         XcursorImage *xci;
34
35         xci = XcursorImageCreate(w, h);
36         if (xci)
37           {
38              int i;
39
40              xci->xhot = hot_x;
41              xci->yhot = hot_y;
42              xci->delay = 0;
43              for (i = 0; i < (w * h); i++)
44                {
45 //                int r, g, b, a;
46 //
47 //                a = (pixels[i] >> 24) & 0xff;
48 //                r = (((pixels[i] >> 16) & 0xff) * a) / 0xff;
49 //                g = (((pixels[i] >> 8 ) & 0xff) * a) / 0xff;
50 //                b = (((pixels[i]      ) & 0xff) * a) / 0xff;
51                   xci->pixels[i] = pixels[i];
52 //                  (a << 24) | (r << 16) | (g << 8) | (b);
53                }
54              c = XcursorImageLoadCursor(_ecore_x_disp, xci);
55              XcursorImageDestroy(xci);
56              return c;
57           }
58      }
59    else
60 #endif /* ECORE_XCB_CURSOR */
61      {
62         const uint32_t dither[2][2] =
63           {
64                {0, 2},
65                {3, 1}
66           };
67         Ecore_X_Drawable draw;
68         Ecore_X_Pixmap   pixmap;
69         Ecore_X_Pixmap   mask;
70         Ecore_X_GC       gc;
71         xcb_image_t     *image;
72         uint32_t        *pix;
73         uint8_t          fr;
74         uint8_t          fg;
75         uint8_t          fb;
76         uint8_t          br;
77         uint8_t          bg;
78         uint8_t          bb;
79         uint32_t         brightest = 0;
80         uint32_t         darkest = 255 * 3;
81         uint16_t         x;
82         uint16_t         y;
83
84         draw = window;
85         pixmap = xcb_generate_id(_ecore_xcb_conn);
86         xcb_create_pixmap(_ecore_xcb_conn,
87                           1, pixmap, draw,
88                           1, 1);
89         mask = xcb_generate_id(_ecore_xcb_conn);
90         xcb_create_pixmap(_ecore_xcb_conn,
91                           1, mask, draw,
92                           1, 1);
93
94         image = xcb_image_create_native(_ecore_xcb_conn, w, h,
95                                  XCB_IMAGE_FORMAT_Z_PIXMAP,
96                                  32, NULL, ~0, NULL);
97         image->data = malloc(image->size);
98
99         fr = 0x00; fg = 0x00; fb = 0x00;
100         br = 0xff; bg = 0xff; bb = 0xff;
101         pix = (uint32_t *)pixels;
102         for (y = 0; y < h; y++)
103           {
104              for (x = 0; x < w; x++)
105                {
106                   uint8_t r, g, b, a;
107
108                   a = (pix[0] >> 24) & 0xff;
109                   r = (pix[0] >> 16) & 0xff;
110                   g = (pix[0] >> 8 ) & 0xff;
111                   b = (pix[0]      ) & 0xff;
112                   if (a > 0)
113                     {
114                        if ((uint32_t)(r + g + b) > brightest)
115                          {
116                             brightest = r + g + b;
117                             br = r;
118                             bg = g;
119                             bb = b;
120                          }
121                        if ((uint32_t)(r + g + b) < darkest)
122                          {
123                             darkest = r + g + b;
124                             fr = r;
125                             fg = g;
126                             fb = b;
127                          }
128                     }
129                   pix++;
130                }
131           }
132
133         pix = (uint32_t *)pixels;
134         for (y = 0; y < h; y++)
135           {
136              for (x = 0; x < w; x++)
137                {
138                   uint32_t v;
139                   uint8_t  r, g, b;
140                   int32_t  d1, d2;
141
142                   r = (pix[0] >> 16) & 0xff;
143                   g = (pix[0] >> 8 ) & 0xff;
144                   b = (pix[0]      ) & 0xff;
145                   d1 =
146                     ((r - fr) * (r - fr)) +
147                     ((g - fg) * (g - fg)) +
148                     ((b - fb) * (b - fb));
149                   d2 =
150                     ((r - br) * (r - br)) +
151                     ((g - bg) * (g - bg)) +
152                     ((b - bb) * (b - bb));
153                   if (d1 + d2)
154                     {
155                        v = (((d2 * 255) / (d1 + d2)) * 5) / 256;
156                        if (v > dither[x & 0x1][y & 0x1]) v = 1;
157                        else v = 0;
158                     }
159                   else
160                     {
161                        v = 0;
162                     }
163                   xcb_image_put_pixel(image, x, y, v);
164                   pix++;
165                }
166           }
167         draw = pixmap;
168         gc = xcb_generate_id(_ecore_xcb_conn);
169         xcb_create_gc(_ecore_xcb_conn, gc, draw, 0, NULL);
170         xcb_image_put(_ecore_xcb_conn, draw, gc, image, 0, 0, 0);
171         xcb_free_gc(_ecore_xcb_conn, gc);
172
173         pix = (uint32_t *)pixels;
174         for (y = 0; y < h; y++)
175           {
176              for (x = 0; x < w; x++)
177                {
178                   uint32_t v;
179
180                   v = (((pix[0] >> 24) & 0xff) * 5) / 256;
181                   if (v > dither[x & 0x1][y & 0x1]) v = 1;
182                   else v = 0;
183                   xcb_image_put_pixel(image, x, y, v);
184                   pix++;
185                }
186           }
187         draw = mask;
188         gc = xcb_generate_id(_ecore_xcb_conn);
189         xcb_create_gc (_ecore_xcb_conn, gc, draw, 0, NULL);
190         xcb_image_put(_ecore_xcb_conn, draw, gc, image, 0, 0, 0);
191         xcb_free_gc(_ecore_xcb_conn, gc);
192
193         free(image->data);
194         image->data = NULL;
195         xcb_image_destroy(image);
196
197         cursor = xcb_generate_id(_ecore_xcb_conn);
198         xcb_create_cursor (_ecore_xcb_conn, cursor,
199                            pixmap, mask,
200                            fr << 8 | fr,
201                            fg << 8 | fg,
202                            fb << 8 | fb,
203                            br << 8 | br,
204                            bg << 8 | bg,
205                            bb << 8 | bb,
206                            hot_x,
207                            hot_y);
208         xcb_free_pixmap(_ecore_xcb_conn, pixmap);
209         xcb_free_pixmap(_ecore_xcb_conn, mask);
210
211         return cursor;
212      }
213    return 0;
214 }
215
216 EAPI void
217 ecore_x_cursor_free(Ecore_X_Cursor cursor)
218 {
219    xcb_free_cursor(_ecore_xcb_conn, cursor);
220 }
221
222 /*
223  * Returns the cursor for the given shape.
224  * Note that the return value must not be freed with
225  * ecore_x_cursor_free()!
226  */
227 EAPI Ecore_X_Cursor
228 ecore_x_cursor_shape_get(int shape)
229 {
230    Ecore_X_Cursor cursor;
231    xcb_font_t     font;
232
233    /* Shapes are defined in Ecore_X_Cursor.h */
234    font = xcb_generate_id(_ecore_xcb_conn);
235    xcb_open_font(_ecore_xcb_conn, font, strlen("cursor"), "cursor");
236
237    cursor = xcb_generate_id(_ecore_xcb_conn);
238    xcb_create_glyph_cursor (_ecore_xcb_conn,
239                             cursor,
240                             font,
241                             font,
242                             shape,
243                             shape + 1,
244                             0, 0, 0,
245                             65535, 65535, 65535);
246
247    xcb_close_font(_ecore_xcb_conn, font);
248
249    return cursor;
250 }
251
252 EAPI void
253 ecore_x_cursor_size_set(int size)
254 {
255 #ifdef ECORE_XCB_CURSOR
256    XcursorSetDefaultSize(_ecore_x_disp, size);
257 #else
258    size = 0;
259 #endif /* ECORE_XCB_CURSOR */
260 }
261
262 EAPI int
263 ecore_x_cursor_size_get(void)
264 {
265 #ifdef ECORE_XCB_CURSOR
266    return XcursorGetDefaultSize(_ecore_x_disp);
267 #else
268    return 0;
269 #endif /* ECORE_XCB_CURSOR */
270 }