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