Tizen 2.1 base
[framework/uifw/ecore.git] / src / lib / ecore_x / xcb / ecore_xcb_xfixes.c
1 #include "ecore_xcb_private.h"
2 # ifdef ECORE_XCB_XFIXES
3 #  include <xcb/xfixes.h>
4 # endif
5
6 /* local function prototypes */
7 static xcb_rectangle_t   *_ecore_xcb_rect_to_xcb(Ecore_X_Rectangle *rects,
8                                                  int                num);
9 static Ecore_X_Rectangle *_ecore_xcb_rect_to_ecore(xcb_rectangle_t *rects,
10                                                    int              num);
11
12 /* local variables */
13 static Eina_Bool _xfixes_avail = EINA_FALSE;
14
15 /* external variables */
16 int _ecore_xcb_event_xfixes = -1;
17
18 void
19 _ecore_xcb_xfixes_init(void)
20 {
21    LOGFN(__FILE__, __LINE__, __FUNCTION__);
22
23 #ifdef ECORE_XCB_XFIXES
24    xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_xfixes_id);
25 #endif
26 }
27
28 void
29 _ecore_xcb_xfixes_finalize(void)
30 {
31 #ifdef ECORE_XCB_XFIXES
32    const xcb_query_extension_reply_t *ext_reply;
33 #endif
34
35    LOGFN(__FILE__, __LINE__, __FUNCTION__);
36
37 #ifdef ECORE_XCB_XFIXES
38    ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_xfixes_id);
39    if ((ext_reply) && (ext_reply->present))
40      {
41         xcb_xfixes_query_version_cookie_t cookie;
42         xcb_xfixes_query_version_reply_t *reply;
43
44         cookie =
45           xcb_xfixes_query_version_unchecked(_ecore_xcb_conn,
46                                              XCB_XFIXES_MAJOR_VERSION,
47                                              XCB_XFIXES_MINOR_VERSION);
48         reply = xcb_xfixes_query_version_reply(_ecore_xcb_conn, cookie, NULL);
49         if (reply)
50           {
51              /* NB: XFixes Extension >= 3 needed for shape stuff.
52               * for now, I am removing this check so that it matches the
53               * xlib code closer. If the extension version ends up being
54               * that important, then re-enable this */
55
56      /* if (reply->major_version >= 3) */
57                 _xfixes_avail = EINA_TRUE;
58                 free(reply);
59           }
60
61         if (_xfixes_avail)
62           _ecore_xcb_event_xfixes = ext_reply->first_event;
63      }
64 #endif
65 }
66
67 EAPI Eina_Bool
68 ecore_x_fixes_selection_notification_request(Ecore_X_Atom selection)
69 {
70 #ifdef ECORE_XCB_XFIXES
71    Ecore_X_Window root = 0;
72    xcb_void_cookie_t cookie;
73    xcb_generic_error_t *err;
74    int mask = 0;
75 #endif
76
77    CHECK_XCB_CONN;
78
79    if (!_xfixes_avail) return EINA_FALSE;
80
81 #ifdef ECORE_XCB_XFIXES
82    root = ((xcb_screen_t *)_ecore_xcb_screen)->root;
83
84    mask = (XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
85            XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY |
86            XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE);
87
88    cookie =
89      xcb_xfixes_select_selection_input_checked(_ecore_xcb_conn, root,
90                                                selection, mask);
91    err = xcb_request_check(_ecore_xcb_conn, cookie);
92    if (err)
93      {
94         free(err);
95         return EINA_FALSE;
96      }
97
98    return EINA_TRUE;
99 #endif
100    return EINA_FALSE;
101 }
102
103 Eina_Bool
104 _ecore_xcb_xfixes_avail_get(void)
105 {
106    return _xfixes_avail;
107 }
108
109 /**
110  * @defgroup Ecore_X_Fixes_Group X Fixes Extension Functions
111  *
112  * Functions related to the X Fixes extension.
113  */
114
115 /**
116  * Create a region from rectangles.
117  * @param rects The rectangles used to initialize the region.
118  * @param num   The number of rectangles.
119  * @return      The newly created region.
120  *
121  * Create a region initialized to the specified list of rectangles
122  * @p rects. The rectangles may be specified in any order, their union
123  * becomes the region.
124  * @ingroup Ecore_X_Fixes_Group
125  */
126 EAPI Ecore_X_Region
127 ecore_x_region_new(Ecore_X_Rectangle *rects,
128                    int                num)
129 {
130    Ecore_X_Region region = 0;
131 #ifdef ECORE_XCB_XFIXES
132    xcb_rectangle_t *xrects;
133 #endif
134
135    LOGFN(__FILE__, __LINE__, __FUNCTION__);
136    CHECK_XCB_CONN;
137
138    if (!_xfixes_avail) return 0;
139
140 #ifdef ECORE_XCB_XFIXES
141    xrects = _ecore_xcb_rect_to_xcb(rects, num);
142    region = xcb_generate_id(_ecore_xcb_conn);
143    xcb_xfixes_create_region(_ecore_xcb_conn, region, num, xrects);
144    free(xrects);
145 //   ecore_x_flush();
146 #endif
147
148    return region;
149 }
150
151 /**
152  * Create a region from a pixmap.
153  * @param bitmap The bitmap used to initialize the region.
154  * @return       The newly created region.
155  *
156  * Creates a region initialized to the set of 'one' pixels in @p bitmap
157  * (which must be of depth 1, else Match error).
158  * @ingroup Ecore_X_Fixes_Group
159  */
160 EAPI Ecore_X_Region
161 ecore_x_region_new_from_bitmap(Ecore_X_Pixmap bitmap)
162 {
163    Ecore_X_Region region = 0;
164
165    LOGFN(__FILE__, __LINE__, __FUNCTION__);
166    CHECK_XCB_CONN;
167
168    if (!_xfixes_avail) return 0;
169
170 #ifdef ECORE_XCB_XFIXES
171    region = xcb_generate_id(_ecore_xcb_conn);
172    xcb_xfixes_create_region_from_bitmap(_ecore_xcb_conn, region, bitmap);
173 //   ecore_x_flush();
174 #endif
175
176    return region;
177 }
178
179 /**
180  * Create a region from a window.
181  * @param win The window used to initialize the region.
182  * @param type   The type of the region.
183  * @return       The newly created region.
184  *
185  * Creates a region initialized to the specified @p window region. See
186  * the Shape extension for the definition of Bounding and Clip
187  * regions.
188  * @ingroup Ecore_X_Fixes_Group
189  */
190 EAPI Ecore_X_Region
191 ecore_x_region_new_from_window(Ecore_X_Window      win,
192                                Ecore_X_Region_Type type)
193 {
194    Ecore_X_Region region = 0;
195
196    LOGFN(__FILE__, __LINE__, __FUNCTION__);
197    CHECK_XCB_CONN;
198
199    if (!_xfixes_avail) return 0;
200
201 #ifdef ECORE_XCB_XFIXES
202    region = xcb_generate_id(_ecore_xcb_conn);
203    xcb_xfixes_create_region_from_window(_ecore_xcb_conn, region, win, type);
204 //   ecore_x_flush();
205 #endif
206
207    return region;
208 }
209
210 /**
211  * Create a region from a graphic context.
212  * @param gc The graphic context used to initialize the region.
213  * @return   The newly created region.
214  *
215  * Creates a region initialized from the clip list of @p gc.
216  * @ingroup Ecore_X_Fixes_Group
217  */
218 EAPI Ecore_X_Region
219 ecore_x_region_new_from_gc(Ecore_X_GC gc)
220 {
221    Ecore_X_Region region = 0;
222
223    LOGFN(__FILE__, __LINE__, __FUNCTION__);
224    CHECK_XCB_CONN;
225
226    if (!_xfixes_avail) return 0;
227
228 #ifdef ECORE_XCB_XFIXES
229    region = xcb_generate_id(_ecore_xcb_conn);
230    xcb_xfixes_create_region_from_gc(_ecore_xcb_conn, region, gc);
231 //   ecore_x_flush();
232 #endif
233
234    return region;
235 }
236
237 /**
238  * Create a region from a picture.
239  * @param picture The picture used to initialize the region.
240  * @return        The newly created region.
241  *
242  * Creates a region initialized from the clip list of @p picture.
243  * @ingroup Ecore_X_Fixes_Group
244  */
245 EAPI Ecore_X_Region
246 ecore_x_region_new_from_picture(Ecore_X_Picture picture)
247 {
248    Ecore_X_Region region = 0;
249
250    LOGFN(__FILE__, __LINE__, __FUNCTION__);
251    CHECK_XCB_CONN;
252
253    if (!_xfixes_avail) return 0;
254
255 #ifdef ECORE_XCB_XFIXES
256    region = xcb_generate_id(_ecore_xcb_conn);
257    xcb_xfixes_create_region_from_picture(_ecore_xcb_conn, region, picture);
258 //   ecore_x_flush();
259 #endif
260
261    return region;
262 }
263
264 /**
265  * Destroy a region.
266  * @param region The region to destroy.
267  *
268  * Destroy the specified @p region.
269  * @ingroup Ecore_X_Fixes_Group
270  */
271 EAPI void
272 ecore_x_region_free(Ecore_X_Region region)
273 {
274    LOGFN(__FILE__, __LINE__, __FUNCTION__);
275    CHECK_XCB_CONN;
276
277    if (!_xfixes_avail) return;
278
279 #ifdef ECORE_XCB_XFIXES
280    xcb_xfixes_destroy_region(_ecore_xcb_conn, region);
281 //   ecore_x_flush();
282 #endif
283 }
284
285 /**
286  * Set the content of a region.
287  * @param region The region to destroy.
288  * @param rects  The rectangles used to set the region.
289  * @param num    The number of rectangles.
290  *
291  * Replace the current contents of @p region with the region formed
292  * by the union of the rectangles @p rects.
293  * @ingroup Ecore_X_Fixes_Group
294  */
295 EAPI void
296 ecore_x_region_set(Ecore_X_Region     region,
297                    Ecore_X_Rectangle *rects,
298                    int                num)
299 {
300 #ifdef ECORE_XCB_XFIXES
301    xcb_rectangle_t *xrects;
302 #endif
303
304    LOGFN(__FILE__, __LINE__, __FUNCTION__);
305    CHECK_XCB_CONN;
306
307    if (!_xfixes_avail) return;
308
309 #ifdef ECORE_XCB_XFIXES
310    xrects = _ecore_xcb_rect_to_xcb(rects, num);
311    xcb_xfixes_set_region(_ecore_xcb_conn, region, num, xrects);
312    free(xrects);
313 //   ecore_x_flush();
314 #endif
315 }
316
317 /**
318  * Copy the content of a region.
319  * @param dest   The destination region.
320  * @param source The source region.
321  *
322  * Replace the contents of @p dest with the contents of @p source.
323  * @ingroup Ecore_X_Fixes_Group
324  */
325 EAPI void
326 ecore_x_region_copy(Ecore_X_Region dest,
327                     Ecore_X_Region source)
328 {
329    LOGFN(__FILE__, __LINE__, __FUNCTION__);
330    CHECK_XCB_CONN;
331
332    if (!_xfixes_avail) return;
333
334    // NB: Hmmmm...this may need converting to/fro xcb_rectangle_t
335 #ifdef ECORE_XCB_XFIXES
336    xcb_xfixes_copy_region(_ecore_xcb_conn, source, dest);
337 //   ecore_x_flush();
338 #endif
339 }
340
341 /**
342  * Make the union of two regions.
343  * @param dest    The destination region.
344  * @param source1 The first source region.
345  * @param source2 The second source region.
346  *
347  * Replace the contents of @p dest with the union of @p source1 and
348  * @p source2.
349  * @ingroup Ecore_X_Fixes_Group
350  */
351 EAPI void
352 ecore_x_region_combine(Ecore_X_Region dest,
353                        Ecore_X_Region source1,
354                        Ecore_X_Region source2)
355 {
356    LOGFN(__FILE__, __LINE__, __FUNCTION__);
357    CHECK_XCB_CONN;
358
359    if (!_xfixes_avail) return;
360
361 #ifdef ECORE_XCB_XFIXES
362    xcb_xfixes_union_region(_ecore_xcb_conn, source1, source2, dest);
363 //   ecore_x_flush();
364 #endif
365 }
366
367 /**
368  * Make the intersection of two regions.
369  * @param dest    The destination region.
370  * @param source1 The first source region.
371  * @param source2 The second source region.
372  *
373  * Replace the contents of @p dest with the intersection of @p source1 and
374  * @p source2.
375  * @ingroup Ecore_X_Fixes_Group
376  */
377 EAPI void
378 ecore_x_region_intersect(Ecore_X_Region dest,
379                          Ecore_X_Region source1,
380                          Ecore_X_Region source2)
381 {
382    LOGFN(__FILE__, __LINE__, __FUNCTION__);
383    CHECK_XCB_CONN;
384
385    if (!_xfixes_avail) return;
386
387 #ifdef ECORE_XCB_XFIXES
388    xcb_xfixes_intersect_region(_ecore_xcb_conn, source1, source2, dest);
389 //   ecore_x_flush();
390 #endif
391 }
392
393 /**
394  * Make the subtraction of two regions.
395  * @param dest    The destination region.
396  * @param source1 The first source region.
397  * @param source2 The second source region.
398  *
399  * Replace the contents of @p dest with the subtraction of @p source1 by
400  * @p source2.
401  * @ingroup Ecore_X_Fixes_Group
402  */
403 EAPI void
404 ecore_x_region_subtract(Ecore_X_Region dest,
405                         Ecore_X_Region source1,
406                         Ecore_X_Region source2)
407 {
408    LOGFN(__FILE__, __LINE__, __FUNCTION__);
409    CHECK_XCB_CONN;
410
411    if (!_xfixes_avail) return;
412
413 #ifdef ECORE_XCB_XFIXES
414    xcb_xfixes_subtract_region(_ecore_xcb_conn, source1, source2, dest);
415 //   ecore_x_flush();
416 #endif
417 }
418
419 /**
420  * Make the subtraction of regions by bounds.
421  * @param dest   The destination region.
422  * @param bounds The bounds.
423  * @param source The source region.
424  *
425  * The @p source region is subtracted from the region specified by
426  * @p bounds.  The result is placed in @p dest, replacing its
427  * contents.
428  * @ingroup Ecore_X_Fixes_Group
429  */
430 EAPI void
431 ecore_x_region_invert(Ecore_X_Region     dest,
432                       Ecore_X_Rectangle *bounds,
433                       Ecore_X_Region     source)
434 {
435 #ifdef ECORE_XCB_XFIXES
436    xcb_rectangle_t xrects;
437 #endif
438
439    LOGFN(__FILE__, __LINE__, __FUNCTION__);
440    CHECK_XCB_CONN;
441
442    if (!_xfixes_avail) return;
443
444 #ifdef ECORE_XCB_XFIXES
445    xrects.x = bounds->x;
446    xrects.y = bounds->y;
447    xrects.width = bounds->width;
448    xrects.height = bounds->height;
449
450    xcb_xfixes_invert_region(_ecore_xcb_conn, source, xrects, dest);
451 //   ecore_x_flush();
452 #endif
453 }
454
455 /**
456  * Translate a region.
457  * @param region The region to translate.
458  * @param dx     The horizontal translation.
459  * @param dy     The vertical translation.
460  *
461  * The @p region is translated by @p dx and @p dy in place.
462  * @ingroup Ecore_X_Fixes_Group
463  */
464 EAPI void
465 ecore_x_region_translate(Ecore_X_Region region,
466                          int            dx,
467                          int            dy)
468 {
469    LOGFN(__FILE__, __LINE__, __FUNCTION__);
470    CHECK_XCB_CONN;
471
472    if (!_xfixes_avail) return;
473
474 #ifdef ECORE_XCB_XFIXES
475    xcb_xfixes_translate_region(_ecore_xcb_conn, region, dx, dy);
476 //   ecore_x_flush();
477 #endif
478 }
479
480 /**
481  * Extent a region.
482  * @param dest   The destination region.
483  * @param source The source region.
484  *
485  * The extents of the @p source region are placed in @p dest.
486  * @ingroup Ecore_X_Fixes_Group
487  */
488 EAPI void
489 ecore_x_region_extents(Ecore_X_Region dest,
490                        Ecore_X_Region source)
491 {
492    LOGFN(__FILE__, __LINE__, __FUNCTION__);
493    CHECK_XCB_CONN;
494
495    if (!_xfixes_avail) return;
496
497 #ifdef ECORE_XCB_XFIXES
498    xcb_xfixes_region_extents(_ecore_xcb_conn, source, dest);
499 //   ecore_x_flush();
500 #endif
501 }
502
503 /**
504  * Return the rectangles that compose a region.
505  * @param  region The region (Unused).
506  * @param  num    The number of returned rectangles.
507  * @param  bounds The returned bounds of the region.
508  * @return        The returned rectangles.
509  *
510  * @ingroup Ecore_X_Fixes_Group
511  */
512 EAPI Ecore_X_Rectangle *
513 ecore_x_region_fetch(Ecore_X_Region     region,
514                      int               *num,
515                      Ecore_X_Rectangle *bounds)
516 {
517    Ecore_X_Rectangle extents = { 0, 0, 0, 0 };
518    Ecore_X_Rectangle *rects = NULL;
519 #ifdef ECORE_XCB_XFIXES
520    xcb_xfixes_fetch_region_cookie_t cookie;
521    xcb_xfixes_fetch_region_reply_t *reply;
522    xcb_rectangle_t *r;
523    int n = 0;
524 #endif
525
526    LOGFN(__FILE__, __LINE__, __FUNCTION__);
527    CHECK_XCB_CONN;
528
529    if (num) *num = 0;
530    if (bounds) *bounds = extents;
531    if (!_xfixes_avail) return NULL;
532
533 #ifdef ECORE_XCB_XFIXES
534    cookie = xcb_xfixes_fetch_region_unchecked(_ecore_xcb_conn, region);
535    reply = xcb_xfixes_fetch_region_reply(_ecore_xcb_conn, cookie, NULL);
536    if (!reply) return NULL;
537
538    r = xcb_xfixes_fetch_region_rectangles(reply);
539    n = xcb_xfixes_fetch_region_rectangles_length(reply);
540    rects = _ecore_xcb_rect_to_ecore(r, n);
541    if (num) *num = n;
542
543    /* rects = (Ecore_X_Rectangle *)malloc(n * sizeof(Ecore_X_Rectangle)); */
544    /* if (!rects)  */
545    /*   { */
546    /*      free(reply); */
547    /*      return NULL; */
548    /*   } */
549
550    /* for (i = 0; i < n; i++)  */
551    /*   { */
552    /*      rects[i].x = r[i].x; */
553    /*      rects[i].y = r[i].y; */
554    /*      rects[i].width = r[i].width; */
555    /*      rects[i].height = r[i].height; */
556    /*   } */
557
558    (*bounds).x = reply->extents.x;
559    (*bounds).y = reply->extents.y;
560    (*bounds).width = reply->extents.width;
561    (*bounds).height = reply->extents.height;
562
563    free(reply);
564 #endif
565
566    return rects;
567 }
568
569 /**
570  * Expand a region.
571  * @param dest   The destination region.
572  * @param source The source region.
573  * @param left   The number of pixels to add on the left.
574  * @param right  The number of pixels to add on the right.
575  * @param top    The number of pixels to add at the top.
576  * @param bottom The number of pixels to add at the bottom.
577  *
578  * Put in @p dest the area specified by expanding each rectangle in
579  * the @p source  region by the specified number of pixels to the
580  * @p left, @p right, @p top and @p bottom.
581  * @ingroup Ecore_X_Fixes_Group
582  */
583 EAPI void
584 ecore_x_region_expand(Ecore_X_Region dest,
585                       Ecore_X_Region source,
586                       unsigned int   left,
587                       unsigned int   right,
588                       unsigned int   top,
589                       unsigned int   bottom)
590 {
591    LOGFN(__FILE__, __LINE__, __FUNCTION__);
592    CHECK_XCB_CONN;
593
594    if (!_xfixes_avail) return;
595
596 #ifdef ECORE_XCB_XFIXES
597    xcb_xfixes_expand_region(_ecore_xcb_conn, source, dest, left, right, top, bottom);
598 //   ecore_x_flush();
599 #endif
600 }
601
602 /**
603  * Change clip-mask in a graphic context to the specified region.
604  * @param region   The region to change.
605  * @param gc       The clip-mask graphic context.
606  * @param x The horizontal translation.
607  * @param y The vertical translation.
608  *
609  * Changes clip-mask in @p gc to the specified @p region and
610  * sets the clip origin with the values of @p x_origin and @p y_origin.
611  * Output will be clippped to remain contained within the region. The
612  * clip origin is interpreted relative to the origin of whatever
613  * destination drawable is specified in a graphics request. The
614  * region is interpreted relative to the clip origin. Future changes
615  * to region have no effect on the gc clip-mask.
616  * @ingroup Ecore_X_Fixes_Group
617  */
618 EAPI void
619 ecore_x_region_gc_clip_set(Ecore_X_Region region,
620                            Ecore_X_GC     gc,
621                            int            x,
622                            int            y)
623 {
624    LOGFN(__FILE__, __LINE__, __FUNCTION__);
625    CHECK_XCB_CONN;
626
627    if (!_xfixes_avail) return;
628
629 #ifdef ECORE_XCB_XFIXES
630    xcb_xfixes_set_gc_clip_region(_ecore_xcb_conn, gc, region, x, y);
631 //   ecore_x_flush();
632 #endif
633 }
634
635 /**
636  * Change the shape extension of a window.
637  * @param region   The region.
638  * @param dest     The window whose shape is changed.
639  * @param type     The kind of shape.
640  * @param x The horizontal offset.
641  * @param y The vertical offset.
642  *
643  * Set the specified Shape extension region of @p window to @p region,
644  * offset by @p x_offset and @p y_offset. Future changes to region
645  * have no effect on the window shape.
646  * @ingroup Ecore_X_Fixes_Group
647  */
648 EAPI void
649 ecore_x_region_window_shape_set(Ecore_X_Region     region,
650                                 Ecore_X_Window     dest,
651                                 Ecore_X_Shape_Type type,
652                                 int                x,
653                                 int                y)
654 {
655    LOGFN(__FILE__, __LINE__, __FUNCTION__);
656    CHECK_XCB_CONN;
657
658    if (!_xfixes_avail) return;
659
660 #ifdef ECORE_XCB_XFIXES
661    xcb_xfixes_set_window_shape_region(_ecore_xcb_conn, dest, type, x, y, region);
662 //   ecore_x_flush();
663 #endif
664 }
665
666 /**
667  * Change clip-mask in picture to the specified region.
668  * @param region   The region.
669  * @param picture  The picture.
670  * @param x The X coordinate of the origin.
671  * @param y The Y coordinate of the origin.
672  *
673  * Changes clip-mask in picture to the specified @p region
674  * and sets the clip origin.  Input and output will be clipped to
675  * remain contained within the region.  The clip origin is interpreted
676  * relative to the origin of the drawable associated with @p picture.  The
677  * region is interpreted relative to the clip origin.  Future changes
678  * to region have no effect on the picture clip-mask.
679  * @ingroup Ecore_X_Fixes_Group
680  */
681 EAPI void
682 ecore_x_region_picture_clip_set(Ecore_X_Region  region,
683                                 Ecore_X_Picture picture,
684                                 int             x,
685                                 int             y)
686 {
687    LOGFN(__FILE__, __LINE__, __FUNCTION__);
688    CHECK_XCB_CONN;
689
690    if (!_xfixes_avail) return;
691
692 #ifdef ECORE_XCB_XFIXES
693    xcb_xfixes_set_picture_clip_region(_ecore_xcb_conn, picture, region, x, y);
694 //   ecore_x_flush();
695 #endif
696 }
697
698 /* local function prototypes */
699 static xcb_rectangle_t *
700 _ecore_xcb_rect_to_xcb(Ecore_X_Rectangle *rects,
701                        int                num)
702 {
703    xcb_rectangle_t *xrect;
704    int i = 0;
705
706    if (!num) return NULL;
707
708    xrect = malloc(sizeof(xcb_rectangle_t) * num);
709    if (!xrect) return NULL;
710
711    for (i = 0; i < num; i++)
712      {
713         xrect[i].x = rects[i].x;
714         xrect[i].y = rects[i].y;
715         xrect[i].width = rects[i].width;
716         xrect[i].height = rects[i].height;
717      }
718
719    return xrect;
720 }
721
722 static Ecore_X_Rectangle *
723 _ecore_xcb_rect_to_ecore(xcb_rectangle_t *rects,
724                          int              num)
725 {
726    Ecore_X_Rectangle *erect;
727    int i = 0;
728
729    if (!num) return NULL;
730
731    erect = malloc(sizeof(Ecore_X_Rectangle) * num);
732    if (!erect) return NULL;
733
734    for (i = 0; i < num; i++)
735      {
736         erect[i].x = rects[i].x;
737         erect[i].y = rects[i].y;
738         erect[i].width = rects[i].width;
739         erect[i].height = rects[i].height;
740      }
741
742    return erect;
743 }
744