a85b2b70590c85e24c901ead46c135b5bcdcb073
[framework/uifw/ecore.git] / src / lib / ecore_x / xcb / ecore_xcb_shape.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
7
8 /**
9  * @defgroup Ecore_X_Shape_Group X Shape extension
10  *
11  * Functions that use the shape extension of the X server to change shape of given windows.
12  */
13
14
15 #ifdef ECORE_XCB_SHAPE
16 static int _shape_available = 0;
17 static xcb_shape_query_version_cookie_t _ecore_xcb_shape_init_cookie;
18 #endif /* ECORE_XCB_SHAPE */
19
20
21 /* To avoid round trips, the initialization is separated in 2
22    functions: _ecore_xcb_shape_init and
23    _ecore_xcb_shape_init_finalize. The first one gets the cookies and
24    the second one gets the replies. */
25
26 void
27 _ecore_x_shape_init(const xcb_query_extension_reply_t *reply)
28 {
29 #ifdef ECORE_XCB_SHAPE
30    if (reply && (reply->present))
31       _ecore_xcb_shape_init_cookie = xcb_shape_query_version_unchecked(_ecore_xcb_conn);
32 #endif /* ECORE_XCB_SHAPE */
33 }
34
35 void
36 _ecore_x_shape_init_finalize(void)
37 {
38 #ifdef ECORE_XCB_SHAPE
39    xcb_shape_query_version_reply_t *reply;
40
41    reply = xcb_shape_query_version_reply(_ecore_xcb_conn,
42                                          _ecore_xcb_shape_init_cookie,
43                                          NULL);
44    if (reply)
45      {
46         _shape_available = 1;
47         free(reply);
48      }
49 #endif /* ECORE_XCB_SHAPE */
50 }
51
52
53 /**
54  * Sets the shape of the given window to the given pixmap.
55  * @param dest_win    The given window.
56  * @param source_mask A 2-bit depth pixmap that provides the new shape of the window.
57  *
58  * Sets the shape of the window @p dest_win to the pixmap @p source_mask.
59  * @ingroup Ecore_X_Shape_Group
60  */
61 EAPI void
62 ecore_x_window_shape_mask_set(Ecore_X_Window dest_win,
63                               Ecore_X_Pixmap source_mask)
64 {
65 #ifdef ECORE_XCB_SHAPE
66    xcb_shape_mask(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, dest_win, 0, 0, source_mask);
67 #endif /* ECORE_XCB_SHAPE */
68 }
69
70 EAPI void
71 ecore_x_window_shape_window_set(Ecore_X_Window dest_win,
72                                 Ecore_X_Window shape_win)
73 {
74 #ifdef ECORE_XCB_SHAPE
75    xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, dest_win, 0, 0, shape_win);
76 #endif /* ECORE_XCB_SHAPE */
77 }
78
79 EAPI void
80 ecore_x_window_shape_window_set_xy(Ecore_X_Window dest_win,
81                                    Ecore_X_Window shape_win,
82                                    int            x,
83                                    int            y)
84 {
85 #ifdef ECORE_XCB_SHAPE
86    xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, dest_win, x, y, shape_win);
87 #endif /* ECORE_XCB_SHAPE */
88 }
89
90
91 /**
92  * Sets the shape of the given window to a rectangle.
93  * @param dest_win The given window.
94  * @param x        The X coordinate of the top left corner of the rectangle.
95  * @param y        The Y coordinate of the top left corner of the rectangle.
96  * @param width    The width of the rectangle.
97  * @param height   The height of the rectangle.
98  *
99  * Sets the shape of the window @p dest_win to a rectangle defined  by
100  * @p x, @p y, @p width and @p height.
101  * @ingroup Ecore_X_Shape_Group
102  */
103 EAPI void
104 ecore_x_window_shape_rectangle_set(Ecore_X_Window dest_win,
105                                    int            x,
106                                    int            y,
107                                    int            width,
108                                    int            height)
109 {
110 #ifdef ECORE_XCB_SHAPE
111    xcb_rectangle_t rect;
112
113    rect.x = x;
114    rect.y = y;
115    rect.width = width;
116    rect.height = height;
117    xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, 1, &rect);
118 #endif /* ECORE_XCB_SHAPE */
119 }
120
121 EAPI void
122 ecore_x_window_shape_rectangles_set(Ecore_X_Window     dest_win,
123                                     Ecore_X_Rectangle *rects,
124                                     int                num)
125 {
126 #ifdef ECORE_XCB_SHAPE
127    if (num > 0)
128      xcb_shape_rectangles(_ecore_xcb_conn,
129                           XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING,
130                           0, dest_win, 0, 0, num, (xcb_rectangle_t *)rects);
131    else
132      xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, 0, NULL);
133 #endif /* ECORE_XCB_SHAPE */
134 }
135
136 EAPI void
137 ecore_x_window_shape_window_add(Ecore_X_Window dest_win,
138                                 Ecore_X_Window shape_win)
139 {
140 #ifdef ECORE_XCB_SHAPE
141    xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, dest_win, 0, 0, shape_win);
142 #endif /* ECORE_XCB_SHAPE */
143 }
144
145 EAPI void
146 ecore_x_window_shape_window_add_xy(Ecore_X_Window dest_win,
147                                    Ecore_X_Window shape_win,
148                                    int            x,
149                                    int            y)
150 {
151 #ifdef ECORE_XCB_SHAPE
152    xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, dest_win, x, y, shape_win);
153 #endif /* ECORE_XCB_SHAPE */
154 }
155
156 EAPI void
157 ecore_x_window_shape_rectangle_add(Ecore_X_Window dest_win,
158                                    int            x,
159                                    int            y,
160                                    int            width,
161                                    int            height)
162 {
163 #ifdef ECORE_XCB_SHAPE
164    xcb_rectangle_t rect;
165
166    rect.x = x;
167    rect.y = y;
168    rect.width = width;
169    rect.height = height;
170    xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, 1, &rect);
171 #endif /* ECORE_XCB_SHAPE */
172 }
173
174 EAPI void
175 ecore_x_window_shape_rectangle_clip(Ecore_X_Window dest_win,
176                                     int            x,
177                                     int            y,
178                                     int            width,
179                                     int            height)
180 {
181    xcb_rectangle_t rect;
182    
183    rect.x = x;
184    rect.y = y;
185    rect.width = width;
186    rect.height = height;
187    xcb_shape_rectangles(_ecore_xcb_conn,
188                         XCB_SHAPE_SO_INTERSECT, XCB_SHAPE_SK_BOUNDING,
189                         0, dest_win, 0, 0, 1, &rect);
190 }
191
192 EAPI void
193 ecore_x_window_shape_rectangles_add(Ecore_X_Window     dest_win,
194                                     Ecore_X_Rectangle *rects,
195                                     int                num)
196 {
197 #ifdef ECORE_XCB_SHAPE
198    if (num > 0)
199      xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, num, (const xcb_rectangle_t *)rects);
200    else
201      xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, 0, NULL);
202 #endif /* ECORE_XCB_SHAPE */
203 }
204
205
206 /**
207  * Sends the ShapeGetRectangles request.
208  * @param window Requested window.
209  * @ingroup Ecore_X_Shape_Group
210  */
211 EAPI void
212 ecore_x_window_shape_rectangles_get_prefetch(Ecore_X_Window window)
213 {
214 #ifdef ECORE_XCB_SHAPE
215    xcb_shape_get_rectangles_cookie_t cookie;
216
217    cookie = xcb_shape_get_rectangles_unchecked(_ecore_xcb_conn, window, XCB_SHAPE_SK_BOUNDING);
218    _ecore_xcb_cookie_cache(cookie.sequence);
219 #endif /* ECORE_XCB_SHAPE */
220 }
221
222
223 /**
224  * Gets the reply of the ShapeGetRectangles request sent by ecore_x_window_shape_rectangles_get_prefetch().
225  * @ingroup Ecore_X_Shape_Group
226  */
227 EAPI void
228 ecore_x_window_shape_rectangles_get_fetch(void)
229 {
230 #ifdef ECORE_XCB_SHAPE
231    xcb_shape_get_rectangles_cookie_t cookie;
232    xcb_shape_get_rectangles_reply_t *reply;
233
234    cookie.sequence = _ecore_xcb_cookie_get();
235    reply = xcb_shape_get_rectangles_reply(_ecore_xcb_conn, cookie, NULL);
236    _ecore_xcb_reply_cache(reply);
237 #endif /* ECORE_XCB_SHAPE */
238 }
239
240
241 /**
242  * To document.
243  * @param  window  Unused.
244  * @param  num_ret To document.
245  * @return         To document.
246  *
247  * To use this function, you must call before, and in order,
248  * ecore_x_window_shape_rectangles_get_prefetch(), which sends the ShapeGetRectangles request,
249  * then ecore_x_window_shape_rectangles_get_fetch(), which gets the reply.
250  * @ingroup Ecore_X_Shape_Group
251  */
252 EAPI Ecore_X_Rectangle *
253 ecore_x_window_shape_rectangles_get(Ecore_X_Window window __UNUSED__,
254                                     int           *num_ret)
255 {
256    Ecore_X_Rectangle *rects = NULL;
257    uint32_t           num = 0;
258 #ifdef ECORE_XCB_SHAPE
259    xcb_shape_get_rectangles_reply_t *reply;
260
261    reply = _ecore_xcb_reply_get();
262    if (!reply)
263      {
264        if (num_ret) *num_ret = 0;
265        return NULL;
266      }
267
268    num = reply->rectangles_len;
269    rects = malloc(sizeof(Ecore_X_Rectangle) * num);
270    if (rects)
271      memcpy (rects,
272              xcb_shape_get_rectangles_rectangles(reply),
273              num * sizeof (Ecore_X_Rectangle));
274    else
275      num = 0;
276 #endif /* ECORE_XCB_SHAPE */
277
278    if (num_ret) *num_ret = num;
279
280    return rects;
281 }
282
283 EAPI void
284 ecore_x_window_shape_events_select(Ecore_X_Window dest_win,
285                                    int            on)
286 {
287 #ifdef ECORE_XCB_SHAPE
288      xcb_shape_select_input(_ecore_xcb_conn, dest_win, on ? 1 : 0);
289 #endif /* ECORE_XCB_SHAPE */
290 }