1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif /* ifdef HAVE_CONFIG_H */
4 
5 #include <stdlib.h>
6 
7 #include "ecore_x_private.h"
8 #include "Ecore_X.h"
9 
10 #include <X11/Xregion.h>
11 
12 static int _fixes_available;
13 #ifdef ECORE_XFIXES
14 static int _fixes_major, _fixes_minor;
15 static int _cursor_visible = 1;
16 #endif /* ifdef ECORE_XFIXES */
17 
18 void
_ecore_x_fixes_init(void)19 _ecore_x_fixes_init(void)
20 {
21 #ifdef ECORE_XFIXES
22    _fixes_major = 3;
23    _fixes_minor = 0;
24 
25    LOGFN;
26 
27    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
28 
29    if (XFixesQueryVersion(_ecore_x_disp, &_fixes_major, &_fixes_minor))
30      {
31         _fixes_available = 1;
32 
33         ECORE_X_EVENT_FIXES_SELECTION_NOTIFY = ecore_event_type_new();
34      }
35    else
36      _fixes_available = 0;
37 
38 #else /* ifdef ECORE_XFIXES */
39    _fixes_available = 0;
40 #endif /* ifdef ECORE_XFIXES */
41 }
42 
43 #ifdef ECORE_XFIXES
44 /* I don't know what to call this function. */
45 static XRectangle *
_ecore_x_rectangle_ecore_to_x(Ecore_X_Rectangle * rects,int num)46 _ecore_x_rectangle_ecore_to_x(Ecore_X_Rectangle *rects,
47                               int num)
48 {
49    XRectangle *xrect;
50    int i;
51 
52    if (num == 0)
53      return NULL;
54 
55    xrect = malloc(sizeof(XRectangle) * num);
56    if (!xrect)
57      return NULL;
58 
59    for (i = 0; i < num; i++)
60      {
61         xrect[i].x = rects[i].x;
62         xrect[i].y = rects[i].y;
63         xrect[i].width = rects[i].width;
64         xrect[i].height = rects[i].height;
65      }
66    return xrect;
67 }
68 
69 static Ecore_X_Rectangle *
_ecore_x_rectangle_x_to_ecore(XRectangle * xrect,int num)70 _ecore_x_rectangle_x_to_ecore(XRectangle *xrect,
71                               int num)
72 {
73    Ecore_X_Rectangle *rects;
74    int i;
75 
76    if (num == 0)
77      return NULL;
78 
79    rects = malloc(sizeof(Ecore_X_Rectangle) * num);
80    if (!rects)
81      return NULL;
82 
83    for (i = 0; i < num; i++)
84      {
85         rects[i].x = xrect[i].x;
86         rects[i].y = xrect[i].y;
87         rects[i].width = xrect[i].width;
88         rects[i].height = xrect[i].height;
89      }
90    return rects;
91 }
92 
93 #endif /* ifdef ECORE_XFIXES */
94 
95 EAPI Eina_Bool
ecore_x_fixes_selection_notification_request(Ecore_X_Atom selection)96 ecore_x_fixes_selection_notification_request(Ecore_X_Atom selection)
97 {
98    EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
99 
100 #ifdef ECORE_XFIXES
101    if (_fixes_available)
102      {
103         XFixesSelectSelectionInput (_ecore_x_disp,
104                                     DefaultRootWindow(_ecore_x_disp),
105                                     selection,
106                                     XFixesSetSelectionOwnerNotifyMask |
107                                     XFixesSelectionWindowDestroyNotifyMask |
108                                     XFixesSelectionClientCloseNotifyMask);
109         return EINA_TRUE;
110      }
111 #endif
112    return EINA_FALSE;
113 }
114 
115 EAPI Eina_Bool
ecore_x_fixes_window_selection_notification_request(Ecore_X_Window window,Ecore_X_Atom selection)116 ecore_x_fixes_window_selection_notification_request(Ecore_X_Window window, Ecore_X_Atom selection)
117 {
118    EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
119 
120 #ifdef ECORE_XFIXES
121    if (_fixes_available)
122      {
123         XFixesSelectSelectionInput (_ecore_x_disp,
124                                     window,
125                                     selection,
126                                     XFixesSetSelectionOwnerNotifyMask |
127                                     XFixesSelectionWindowDestroyNotifyMask |
128                                     XFixesSelectionClientCloseNotifyMask);
129         return EINA_TRUE;
130      }
131 #endif
132    return EINA_FALSE;
133 }
134 
135 EAPI Ecore_X_Region
ecore_x_region_new(Ecore_X_Rectangle * rects,int num)136 ecore_x_region_new(Ecore_X_Rectangle *rects,
137                    int num)
138 {
139    EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, 0);
140 
141 #ifdef ECORE_XFIXES
142    Ecore_X_Region region;
143    XRectangle *xrect;
144 
145    LOGFN;
146    xrect = _ecore_x_rectangle_ecore_to_x(rects, num);
147    region = XFixesCreateRegion(_ecore_x_disp, xrect, num);
148    free(xrect);
149    return region;
150 #else /* ifdef ECORE_XFIXES */
151    return 0;
152 #endif /* ifdef ECORE_XFIXES */
153 }
154 
155 EAPI Ecore_X_Region
ecore_x_region_new_from_bitmap(Ecore_X_Pixmap bitmap)156 ecore_x_region_new_from_bitmap(Ecore_X_Pixmap bitmap)
157 {
158    EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, 0);
159 #ifdef ECORE_XFIXES
160    Ecore_X_Region region;
161 
162    LOGFN;
163    region = XFixesCreateRegionFromBitmap(_ecore_x_disp, bitmap);
164    if (_ecore_xlib_sync) ecore_x_sync();
165    return region;
166 #else /* ifdef ECORE_XFIXES */
167    return 0;
168 #endif /* ifdef ECORE_XFIXES */
169 }
170 
171 EAPI Ecore_X_Region
ecore_x_region_new_from_window(Ecore_X_Window win,Ecore_X_Region_Type type)172 ecore_x_region_new_from_window(Ecore_X_Window win,
173                                Ecore_X_Region_Type type)
174 {
175    EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, 0);
176 #ifdef ECORE_XFIXES
177    Ecore_X_Region region;
178 
179    LOGFN;
180    region = XFixesCreateRegionFromWindow(_ecore_x_disp, win, type);
181    if (_ecore_xlib_sync) ecore_x_sync();
182    return region;
183 #else /* ifdef ECORE_XFIXES */
184    return 0;
185 #endif /* ifdef ECORE_XFIXES */
186 }
187 
188 EAPI Ecore_X_Region
ecore_x_region_new_from_gc(Ecore_X_GC gc)189 ecore_x_region_new_from_gc(Ecore_X_GC gc)
190 {
191    EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, 0);
192 #ifdef ECORE_XFIXES
193    Ecore_X_Region region;
194 
195    LOGFN;
196    region = XFixesCreateRegionFromGC(_ecore_x_disp, gc);
197    if (_ecore_xlib_sync) ecore_x_sync();
198    return region;
199 #else /* ifdef ECORE_XFIXES */
200    return 0;
201 #endif /* ifdef ECORE_XFIXES */
202 }
203 
204 EAPI Ecore_X_Region
ecore_x_region_new_from_picture(Ecore_X_Picture picture)205 ecore_x_region_new_from_picture(Ecore_X_Picture picture)
206 {
207    EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, 0);
208 #ifdef ECORE_XFIXES
209    Ecore_X_Region region;
210 
211    LOGFN;
212    region = XFixesCreateRegionFromPicture(_ecore_x_disp, picture);
213    if (_ecore_xlib_sync) ecore_x_sync();
214    return region;
215 #else /* ifdef ECORE_XFIXES */
216    return 0;
217 #endif /* ifdef ECORE_XFIXES */
218 }
219 
220 EAPI void
ecore_x_region_free(Ecore_X_Region region)221 ecore_x_region_free(Ecore_X_Region region)
222 {
223    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
224 #ifdef ECORE_XFIXES
225    LOGFN;
226    XFixesDestroyRegion(_ecore_x_disp, region);
227 #endif /* ifdef ECORE_XFIXES */
228 }
229 
230 EAPI void
ecore_x_region_set(Ecore_X_Region region,Ecore_X_Rectangle * rects,int num)231 ecore_x_region_set(Ecore_X_Region region,
232                    Ecore_X_Rectangle *rects,
233                    int num)
234 {
235    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
236 #ifdef ECORE_XFIXES
237    XRectangle *xrect = _ecore_x_rectangle_ecore_to_x(rects, num);
238    LOGFN;
239    XFixesSetRegion(_ecore_x_disp, region, xrect, num);
240    if (_ecore_xlib_sync) ecore_x_sync();
241 #endif /* ifdef ECORE_XFIXES */
242 }
243 
244 EAPI void
ecore_x_region_copy(Ecore_X_Region dest,Ecore_X_Region source)245 ecore_x_region_copy(Ecore_X_Region dest,
246                     Ecore_X_Region source)
247 {
248    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
249 #ifdef ECORE_XFIXES
250    LOGFN;
251    XFixesCopyRegion(_ecore_x_disp, dest, source);
252    if (_ecore_xlib_sync) ecore_x_sync();
253 #endif /* ifdef ECORE_XFIXES */
254 }
255 
256 EAPI void
ecore_x_region_combine(Ecore_X_Region dest,Ecore_X_Region source1,Ecore_X_Region source2)257 ecore_x_region_combine(Ecore_X_Region dest,
258                        Ecore_X_Region source1,
259                        Ecore_X_Region source2)
260 {
261    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
262 #ifdef ECORE_XFIXES
263    LOGFN;
264    XFixesUnionRegion(_ecore_x_disp, dest, source1, source2);
265    if (_ecore_xlib_sync) ecore_x_sync();
266 #endif /* ifdef ECORE_XFIXES */
267 }
268 
269 EAPI void
ecore_x_region_intersect(Ecore_X_Region dest,Ecore_X_Region source1,Ecore_X_Region source2)270 ecore_x_region_intersect(Ecore_X_Region dest,
271                          Ecore_X_Region source1,
272                          Ecore_X_Region source2)
273 {
274    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
275 #ifdef ECORE_XFIXES
276    LOGFN;
277    XFixesIntersectRegion(_ecore_x_disp, dest, source1, source2);
278    if (_ecore_xlib_sync) ecore_x_sync();
279 #endif /* ifdef ECORE_XFIXES */
280 }
281 
282 EAPI void
ecore_x_region_subtract(Ecore_X_Region dest,Ecore_X_Region source1,Ecore_X_Region source2)283 ecore_x_region_subtract(Ecore_X_Region dest,
284                         Ecore_X_Region source1,
285                         Ecore_X_Region source2)
286 {
287    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
288 #ifdef ECORE_XFIXES
289    LOGFN;
290    XFixesSubtractRegion(_ecore_x_disp, dest, source1, source2);
291    if (_ecore_xlib_sync) ecore_x_sync();
292 #endif /* ifdef ECORE_XFIXES */
293 }
294 
295 EAPI void
ecore_x_region_invert(Ecore_X_Region dest,Ecore_X_Rectangle * bounds,Ecore_X_Region source)296 ecore_x_region_invert(Ecore_X_Region dest,
297                       Ecore_X_Rectangle *bounds,
298                       Ecore_X_Region source)
299 {
300    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
301 #ifdef ECORE_XFIXES
302    XRectangle *xbound;
303    int num = 1;
304 
305    LOGFN;
306    xbound = _ecore_x_rectangle_ecore_to_x(bounds, num);
307 
308    XFixesInvertRegion(_ecore_x_disp, dest, xbound, source);
309    if (_ecore_xlib_sync) ecore_x_sync();
310    free(xbound);
311 #endif /* ifdef ECORE_XFIXES */
312 }
313 
314 EAPI void
ecore_x_region_translate(Ecore_X_Region region,int dx,int dy)315 ecore_x_region_translate(Ecore_X_Region region,
316                          int dx,
317                          int dy)
318 {
319    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
320 #ifdef ECORE_XFIXES
321    LOGFN;
322    XFixesTranslateRegion(_ecore_x_disp, region, dx, dy);
323    if (_ecore_xlib_sync) ecore_x_sync();
324 #endif /* ifdef ECORE_XFIXES */
325 }
326 
327 EAPI void
ecore_x_region_extents(Ecore_X_Region dest,Ecore_X_Region source)328 ecore_x_region_extents(Ecore_X_Region dest,
329                        Ecore_X_Region source)
330 {
331    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
332 #ifdef ECORE_XFIXES
333    LOGFN;
334    XFixesRegionExtents(_ecore_x_disp, dest, source);
335    if (_ecore_xlib_sync) ecore_x_sync();
336 #endif /* ifdef ECORE_XFIXES */
337 }
338 
339 EAPI Ecore_X_Rectangle *
ecore_x_region_fetch(Ecore_X_Region region,int * num,Ecore_X_Rectangle * bounds)340 ecore_x_region_fetch(Ecore_X_Region region,
341                      int *num,
342                      Ecore_X_Rectangle *bounds)
343 {
344    EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, NULL);
345 #ifdef ECORE_XFIXES
346    Ecore_X_Rectangle *rects;
347    XRectangle *xrect, xbound;
348 
349    LOGFN;
350    xrect = XFixesFetchRegionAndBounds(_ecore_x_disp, region, num, &xbound);
351    if (_ecore_xlib_sync) ecore_x_sync();
352    rects = _ecore_x_rectangle_x_to_ecore(xrect, *num);
353    (*bounds).x = xbound.x;
354    (*bounds).y = xbound.y;
355    (*bounds).width = xbound.width;
356    (*bounds).height = xbound.height;
357    XFree(xrect);
358    return rects;
359 #else /* ifdef ECORE_XFIXES */
360    return NULL;
361 #endif /* ifdef ECORE_XFIXES */
362 }
363 
364 EAPI void
ecore_x_region_expand(Ecore_X_Region dest,Ecore_X_Region source,unsigned int left,unsigned int right,unsigned int top,unsigned int bottom)365 ecore_x_region_expand(Ecore_X_Region dest,
366                       Ecore_X_Region source,
367                       unsigned int left,
368                       unsigned int right,
369                       unsigned int top,
370                       unsigned int bottom)
371 {
372    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
373 #ifdef ECORE_XFIXES
374    LOGFN;
375    XFixesExpandRegion(_ecore_x_disp, dest, source, left, right, top, bottom);
376    if (_ecore_xlib_sync) ecore_x_sync();
377 #endif /* ifdef ECORE_XFIXES */
378 }
379 
380 EAPI void
ecore_x_region_gc_clip_set(Ecore_X_Region region,Ecore_X_GC gc,int x_origin,int y_origin)381 ecore_x_region_gc_clip_set(Ecore_X_Region region,
382                            Ecore_X_GC gc,
383                            int x_origin,
384                            int y_origin)
385 {
386    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
387 #ifdef ECORE_XFIXES
388    LOGFN;
389    XFixesSetGCClipRegion(_ecore_x_disp, gc, x_origin, y_origin, region);
390    if (_ecore_xlib_sync) ecore_x_sync();
391 #endif /* ifdef ECORE_XFIXES */
392 }
393 
394 EAPI void
ecore_x_region_window_shape_set(Ecore_X_Region region,Ecore_X_Window win,Ecore_X_Shape_Type type,int x_offset,int y_offset)395 ecore_x_region_window_shape_set(Ecore_X_Region region,
396                                 Ecore_X_Window win,
397                                 Ecore_X_Shape_Type type,
398                                 int x_offset,
399                                 int y_offset)
400 {
401    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
402 #ifdef ECORE_XFIXES
403    LOGFN;
404    XFixesSetWindowShapeRegion(_ecore_x_disp,
405                               win,
406                               type,
407                               x_offset,
408                               y_offset,
409                               region);
410    if (_ecore_xlib_sync) ecore_x_sync();
411 #endif /* ifdef ECORE_XFIXES */
412 }
413 
414 EAPI void
ecore_x_region_picture_clip_set(Ecore_X_Region region,Ecore_X_Picture picture,int x_origin,int y_origin)415 ecore_x_region_picture_clip_set(Ecore_X_Region region,
416                                 Ecore_X_Picture picture,
417                                 int x_origin,
418                                 int y_origin)
419 {
420    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
421 #ifdef ECORE_XFIXES
422    LOGFN;
423    XFixesSetPictureClipRegion(_ecore_x_disp,
424                               picture,
425                               x_origin,
426                               y_origin,
427                               region);
428    if (_ecore_xlib_sync) ecore_x_sync();
429 #endif /* ifdef ECORE_XFIXES */
430 }
431 
432 EAPI void
ecore_x_cursor_show(void)433 ecore_x_cursor_show(void)
434 {
435    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
436 #ifdef ECORE_XFIXES
437    if (!_cursor_visible)
438      {
439         XFixesShowCursor(_ecore_x_disp, DefaultRootWindow(_ecore_x_disp));
440         XFlush(_ecore_x_disp);
441         _cursor_visible = 1;
442      }
443 #endif  /* ifdef ECORE_XFIXES */
444 }
445 
446 EAPI void
ecore_x_cursor_hide(void)447 ecore_x_cursor_hide(void)
448 {
449    EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
450 #ifdef ECORE_XFIXES
451    if (_cursor_visible)
452      {
453         XFixesHideCursor(_ecore_x_disp, DefaultRootWindow(_ecore_x_disp));
454         XFlush(_ecore_x_disp);
455         _cursor_visible = 0;
456      }
457 #endif  /* ifdef ECORE_XFIXES */
458 }
459 
460 EAPI void
ecore_x_root_screen_barriers_set(Ecore_X_Rectangle * screens,int num)461 ecore_x_root_screen_barriers_set(Ecore_X_Rectangle *screens, int num)
462 {
463 #ifdef ECORE_XFIXES
464    static PointerBarrier *bar = NULL;
465    static int bar_num = 0;
466    static int bar_alloc = 0;
467    Region reg, reg2, reg3;
468    int i, j;
469 
470    // clear out old root screen barriers....
471    if (bar)
472      {
473         for (i = 0; i < bar_num; i++)
474           {
475              XFixesDestroyPointerBarrier(_ecore_x_disp, bar[i]);
476           }
477         free(bar);
478      }
479    bar = NULL;
480    bar_num = 0;
481    bar_alloc = 0;
482    if ((!screens) || (num <= 0)) return;
483 
484    // set up new ones given the screen list given
485    for (i = 0; i < num; i++)
486      {
487         XRectangle xrect;
488 
489         reg = XCreateRegion();
490         reg2 = XCreateRegion();
491         xrect.x = screens[i].x - 1;
492         xrect.y = screens[i].y - 1;
493         xrect.width = screens[i].width + 2;
494         xrect.height = screens[i].height + 2;
495         XUnionRectWithRegion(&xrect, reg, reg2);
496         XDestroyRegion(reg);
497         reg = reg2;
498 
499         // reg == screen i + 1 pixel surrounding it
500         for (j = 0; j < num; j++)
501           {
502              // create a region representing screen j
503              reg2 = XCreateRegion();
504              reg3 = XCreateRegion();
505              xrect.x = screens[j].x;
506              xrect.y = screens[j].y;
507              xrect.width = screens[j].width;
508              xrect.height = screens[j].height;
509              XUnionRectWithRegion(&xrect, reg2, reg3);
510              XDestroyRegion(reg2);
511              reg2 = reg3;
512              // reg2 == screen j
513 
514              reg3 = XCreateRegion();
515              XSubtractRegion(reg, reg2, reg3);
516              XDestroyRegion(reg);
517              XDestroyRegion(reg2);
518              reg = reg3;
519              // reg now has had screen j cut out of the boundary
520           }
521         // reg is the result of starting with screen i and then with a
522         // 1 pixel boundary around it havnig adjacent screens "cut out"
523         // of that boundary leaving only extra bounds where no screens
524         // are adjacent
525 
526         // walk rects and create barriers
527         for (j = 0; j < reg->numRects; j++)
528           {
529              int x1, y1, x2, y2;
530 
531              bar_num++;
532              if (bar_num > bar_alloc)
533                {
534                   bar_alloc += 32;
535                   PointerBarrier *t = realloc(bar, bar_alloc * sizeof(PointerBarrier));
536                   if (!t)
537                     {
538                        bar_num--;
539                        return;
540                     }
541                   bar = t;
542                }
543              x1 = reg->rects[j].x1;
544              y1 = reg->rects[j].y1;
545              x2 = reg->rects[j].x2 - 1;
546              y2 = reg->rects[j].y2 - 1;
547              bar[bar_num - 1] =
548                XFixesCreatePointerBarrier(_ecore_x_disp,
549                                           DefaultRootWindow(_ecore_x_disp),
550                                           x1, y1, x2, y2, 0, 0, NULL);
551           }
552         XDestroyRegion(reg);
553      }
554 #endif
555 }
556