diff options
author | David Walter Seikel | 2012-01-04 18:41:13 +1000 |
---|---|---|
committer | David Walter Seikel | 2012-01-04 18:41:13 +1000 |
commit | dd7595a3475407a7fa96a97393bae8c5220e8762 (patch) | |
tree | e341e911d7eb911a51684a7412ef7f7c7605d28e /libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c | |
parent | Add the skeleton. (diff) | |
download | SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.zip SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.gz SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.bz2 SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.xz |
Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje.
Note that embryo wont be used, but I'm not sure yet if you can build edje without it.
Diffstat (limited to 'libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c')
-rw-r--r-- | libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c b/libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c new file mode 100644 index 0000000..4f24d62 --- /dev/null +++ b/libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c | |||
@@ -0,0 +1,408 @@ | |||
1 | #include "ecore_xcb_private.h" | ||
2 | |||
3 | typedef struct _Shadow Shadow; | ||
4 | struct _Shadow | ||
5 | { | ||
6 | Shadow *parent, **children; | ||
7 | Ecore_X_Window win; | ||
8 | int children_num; | ||
9 | short x, y; | ||
10 | unsigned short w, h; | ||
11 | }; | ||
12 | |||
13 | static Eina_Bool _inside_rects(Shadow *s, | ||
14 | int x, | ||
15 | int y, | ||
16 | int bx, | ||
17 | int by, | ||
18 | Ecore_X_Rectangle *rects, | ||
19 | int num); | ||
20 | |||
21 | //static int shadow_count = 0; | ||
22 | static Shadow **shadow_base = NULL; | ||
23 | static int shadow_num = 0; | ||
24 | |||
25 | /* FIXME: round trips */ | ||
26 | static Shadow * | ||
27 | _ecore_x_window_tree_walk(Ecore_X_Window window) | ||
28 | { | ||
29 | Shadow *s, **sl; | ||
30 | xcb_get_window_attributes_reply_t *reply_attr; | ||
31 | xcb_get_geometry_reply_t *reply_geom; | ||
32 | xcb_query_tree_reply_t *reply_tree; | ||
33 | xcb_get_window_attributes_cookie_t cookie_attr; | ||
34 | xcb_get_geometry_cookie_t cookie_geom; | ||
35 | xcb_query_tree_cookie_t cookie_tree; | ||
36 | int i, j; | ||
37 | |||
38 | CHECK_XCB_CONN; | ||
39 | |||
40 | cookie_attr = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window); | ||
41 | reply_attr = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_attr, NULL); | ||
42 | if (!reply_attr) return NULL; | ||
43 | if (reply_attr->map_state != XCB_MAP_STATE_VIEWABLE) | ||
44 | { | ||
45 | free(reply_attr); | ||
46 | return NULL; | ||
47 | } | ||
48 | |||
49 | free(reply_attr); | ||
50 | |||
51 | cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window); | ||
52 | reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL); | ||
53 | if (!reply_geom) return NULL; | ||
54 | |||
55 | if (!(s = calloc(1, sizeof(Shadow)))) | ||
56 | { | ||
57 | free(reply_geom); | ||
58 | return NULL; | ||
59 | } | ||
60 | |||
61 | s->win = window; | ||
62 | s->x = reply_geom->x; | ||
63 | s->y = reply_geom->y; | ||
64 | s->w = reply_geom->width; | ||
65 | s->h = reply_geom->height; | ||
66 | |||
67 | free(reply_geom); | ||
68 | |||
69 | cookie_tree = xcb_query_tree_unchecked(_ecore_xcb_conn, window); | ||
70 | reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL); | ||
71 | if (reply_tree) | ||
72 | { | ||
73 | xcb_window_t *list; | ||
74 | int num; | ||
75 | |||
76 | num = xcb_query_tree_children_length(reply_tree); | ||
77 | list = xcb_query_tree_children(reply_tree); | ||
78 | |||
79 | s->children = calloc(1, sizeof(Shadow *) * num); | ||
80 | if (s->children) | ||
81 | { | ||
82 | s->children_num = num; | ||
83 | for (i = 0; i < num; i++) | ||
84 | { | ||
85 | s->children[i] = _ecore_x_window_tree_walk(list[i]); | ||
86 | if (s->children[i]) | ||
87 | s->children[i]->parent = s; | ||
88 | } | ||
89 | /* compress list down */ | ||
90 | j = 0; | ||
91 | for (i = 0; i < num; i++) | ||
92 | { | ||
93 | if (s->children[i]) | ||
94 | { | ||
95 | s->children[j] = s->children[i]; | ||
96 | j++; | ||
97 | } | ||
98 | } | ||
99 | if (j == 0) | ||
100 | { | ||
101 | free(s->children); | ||
102 | s->children = NULL; | ||
103 | s->children_num = 0; | ||
104 | } | ||
105 | else | ||
106 | { | ||
107 | s->children_num = j; | ||
108 | sl = realloc(s->children, sizeof(Shadow *) * j); | ||
109 | if (sl) s->children = sl; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | free(reply_tree); | ||
114 | } | ||
115 | |||
116 | return s; | ||
117 | } | ||
118 | |||
119 | static void | ||
120 | _ecore_x_window_tree_shadow_free1(Shadow *s) | ||
121 | { | ||
122 | int i = 0; | ||
123 | |||
124 | if (!s) return; | ||
125 | if (s->children) | ||
126 | { | ||
127 | for (i = 0; i < s->children_num; i++) | ||
128 | { | ||
129 | if (s->children[i]) | ||
130 | _ecore_x_window_tree_shadow_free1(s->children[i]); | ||
131 | } | ||
132 | free(s->children); | ||
133 | } | ||
134 | |||
135 | free(s); | ||
136 | } | ||
137 | |||
138 | static void | ||
139 | _ecore_x_window_tree_shadow_free(void) | ||
140 | { | ||
141 | int i = 0; | ||
142 | |||
143 | if (!shadow_base) return; | ||
144 | |||
145 | for (i = 0; i < shadow_num; i++) | ||
146 | { | ||
147 | if (!shadow_base[i]) continue; | ||
148 | _ecore_x_window_tree_shadow_free1(shadow_base[i]); | ||
149 | } | ||
150 | free(shadow_base); | ||
151 | shadow_base = NULL; | ||
152 | shadow_num = 0; | ||
153 | } | ||
154 | |||
155 | static void | ||
156 | _ecore_x_window_tree_shadow_populate(void) | ||
157 | { | ||
158 | Ecore_X_Window *roots = NULL; | ||
159 | int i = 0, num = 0; | ||
160 | |||
161 | if ((roots = ecore_x_window_root_list(&num))) | ||
162 | { | ||
163 | shadow_base = calloc(1, sizeof(Shadow *) * num); | ||
164 | if (shadow_base) | ||
165 | { | ||
166 | shadow_num = num; | ||
167 | for (i = 0; i < num; i++) | ||
168 | shadow_base[i] = _ecore_x_window_tree_walk(roots[i]); | ||
169 | } | ||
170 | |||
171 | free(roots); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | static void | ||
177 | _ecore_x_window_tree_shadow_start(void) | ||
178 | { | ||
179 | shadow_count++; | ||
180 | if (shadow_count > 1) return; | ||
181 | _ecore_x_window_tree_shadow_populate(); | ||
182 | } | ||
183 | |||
184 | static void | ||
185 | _ecore_x_window_tree_shadow_stop(void) | ||
186 | { | ||
187 | shadow_count--; | ||
188 | if (shadow_count != 0) return; | ||
189 | _ecore_x_window_tree_shadow_free(); | ||
190 | } | ||
191 | */ | ||
192 | |||
193 | Shadow * | ||
194 | _ecore_x_window_shadow_tree_find_shadow(Shadow *s, | ||
195 | Ecore_X_Window win) | ||
196 | { | ||
197 | Shadow *ss; | ||
198 | int i = 0; | ||
199 | |||
200 | if (s->win == win) return s; | ||
201 | |||
202 | if (s->children) | ||
203 | { | ||
204 | for (i = 0; i < s->children_num; i++) | ||
205 | { | ||
206 | if (!s->children[i]) continue; | ||
207 | |||
208 | if ((ss = | ||
209 | _ecore_x_window_shadow_tree_find_shadow(s->children[i], win))) | ||
210 | return ss; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | return NULL; | ||
215 | } | ||
216 | |||
217 | Shadow * | ||
218 | _ecore_x_window_shadow_tree_find(Ecore_X_Window base) | ||
219 | { | ||
220 | Shadow *s; | ||
221 | int i = 0; | ||
222 | |||
223 | for (i = 0; i < shadow_num; i++) | ||
224 | { | ||
225 | if (!shadow_base[i]) continue; | ||
226 | |||
227 | if ((s = | ||
228 | _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], base))) | ||
229 | return s; | ||
230 | } | ||
231 | return NULL; | ||
232 | } | ||
233 | |||
234 | static Ecore_X_Window | ||
235 | _ecore_x_window_shadow_tree_at_xy_get_shadow(Shadow *s, | ||
236 | int bx, | ||
237 | int by, | ||
238 | int x, | ||
239 | int y, | ||
240 | Ecore_X_Window *skip, | ||
241 | int skip_num) | ||
242 | { | ||
243 | Ecore_X_Window child; | ||
244 | Ecore_X_Rectangle *rects; | ||
245 | int i = 0, j = 0, wx = 0, wy = 0, num = 0; | ||
246 | |||
247 | wx = s->x + bx; | ||
248 | wy = s->y + by; | ||
249 | if (!((x >= wx) && (y >= wy) && (x < (wx + s->w)) && (y < (wy + s->h)))) | ||
250 | return 0; | ||
251 | |||
252 | rects = ecore_x_window_shape_rectangles_get(s->win, &num); | ||
253 | if (!_inside_rects(s, x, y, bx, by, rects, num)) return 0; | ||
254 | num = 0; | ||
255 | rects = ecore_x_window_shape_input_rectangles_get(s->win, &num); | ||
256 | if (!_inside_rects(s, x, y, bx, by, rects, num)) return 0; | ||
257 | |||
258 | if (s->children) | ||
259 | { | ||
260 | int skipit = 0; | ||
261 | |||
262 | for (i = s->children_num - 1; i >= 0; --i) | ||
263 | { | ||
264 | if (!s->children[i]) continue; | ||
265 | |||
266 | skipit = 0; | ||
267 | if (skip) | ||
268 | { | ||
269 | for (j = 0; j < skip_num; j++) | ||
270 | { | ||
271 | if (s->children[i]->win == skip[j]) | ||
272 | { | ||
273 | skipit = 1; | ||
274 | goto onward; | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | onward: | ||
279 | if (!skipit) | ||
280 | { | ||
281 | if ((child = | ||
282 | _ecore_x_window_shadow_tree_at_xy_get_shadow(s->children[i], wx, wy, x, y, skip, skip_num))) | ||
283 | return child; | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | |||
288 | return s->win; | ||
289 | } | ||
290 | |||
291 | static Ecore_X_Window | ||
292 | _ecore_x_window_shadow_tree_at_xy_get(Ecore_X_Window base, | ||
293 | int bx, | ||
294 | int by, | ||
295 | int x, | ||
296 | int y, | ||
297 | Ecore_X_Window *skip, | ||
298 | int skip_num) | ||
299 | { | ||
300 | Shadow *s; | ||
301 | |||
302 | if (!shadow_base) | ||
303 | { | ||
304 | _ecore_x_window_tree_shadow_populate(); | ||
305 | if (!shadow_base) return 0; | ||
306 | } | ||
307 | |||
308 | s = _ecore_x_window_shadow_tree_find(base); | ||
309 | if (!s) return 0; | ||
310 | |||
311 | return _ecore_x_window_shadow_tree_at_xy_get_shadow(s, bx, by, x, y, skip, skip_num); | ||
312 | } | ||
313 | |||
314 | static Eina_Bool | ||
315 | _inside_rects(Shadow *s, | ||
316 | int x, | ||
317 | int y, | ||
318 | int bx, | ||
319 | int by, | ||
320 | Ecore_X_Rectangle *rects, | ||
321 | int num) | ||
322 | { | ||
323 | Eina_Bool inside = EINA_FALSE; | ||
324 | int i = 0; | ||
325 | |||
326 | if (!rects) return EINA_FALSE; | ||
327 | for (i = 0; i < num; i++) | ||
328 | { | ||
329 | if ((x >= s->x + bx + rects[i].x) && | ||
330 | (y >= s->y + by + rects[i].y) && | ||
331 | (x < (int)(s->x + bx + rects[i].x + rects[i].width)) && | ||
332 | (y < (int)(s->y + by + rects[i].y + rects[i].height))) | ||
333 | { | ||
334 | inside = EINA_TRUE; | ||
335 | break; | ||
336 | } | ||
337 | } | ||
338 | free(rects); | ||
339 | return inside; | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * Retrieves the top, visible window at the given location, | ||
344 | * but skips the windows in the list. This uses a shadow tree built from the | ||
345 | * window tree that is only updated the first time | ||
346 | * ecore_x_window_shadow_tree_at_xy_with_skip_get() is called, or the next time | ||
347 | * it is called after a ecore_x_window_shadow_tree_flush() | ||
348 | * @param base The base window to start searching from (normally root). | ||
349 | * @param x The given X position. | ||
350 | * @param y The given Y position. | ||
351 | * @return The window at that position. | ||
352 | * @ingroup Ecore_X_Window_Geometry_Group | ||
353 | */ | ||
354 | EAPI Ecore_X_Window | ||
355 | ecore_x_window_shadow_tree_at_xy_with_skip_get(Ecore_X_Window base, | ||
356 | int x, | ||
357 | int y, | ||
358 | Ecore_X_Window *skip, | ||
359 | int skip_num) | ||
360 | { | ||
361 | return _ecore_x_window_shadow_tree_at_xy_get(base, 0, 0, x, y, skip, skip_num); | ||
362 | } | ||
363 | |||
364 | /** | ||
365 | * Retrieves the parent window a given window has. This uses the shadow window | ||
366 | * tree. | ||
367 | * @param root The root window of @p win - if 0, this will be automatically determined with extra processing overhead | ||
368 | * @param win The window to get the parent window of | ||
369 | * @return The parent window of @p win | ||
370 | * @ingroup Ecore_X_Window_Geometry_Group | ||
371 | */ | ||
372 | EAPI Ecore_X_Window | ||
373 | ecore_x_window_shadow_parent_get(Ecore_X_Window root __UNUSED__, | ||
374 | Ecore_X_Window win) | ||
375 | { | ||
376 | Shadow *s; | ||
377 | int i = 0; | ||
378 | |||
379 | if (!shadow_base) | ||
380 | { | ||
381 | _ecore_x_window_tree_shadow_populate(); | ||
382 | if (!shadow_base) return 0; | ||
383 | } | ||
384 | |||
385 | for (i = 0; i < shadow_num; i++) | ||
386 | { | ||
387 | if (!shadow_base[i]) continue; | ||
388 | |||
389 | s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], win); | ||
390 | if (s) | ||
391 | { | ||
392 | if (!s->parent) return 0; | ||
393 | return s->parent->win; | ||
394 | } | ||
395 | } | ||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | /** | ||
400 | * Flushes the window shadow tree so nothing is stored. | ||
401 | * @ingroup Ecore_X_Window_Geometry_Group | ||
402 | */ | ||
403 | EAPI void | ||
404 | ecore_x_window_shadow_tree_flush(void) | ||
405 | { | ||
406 | _ecore_x_window_tree_shadow_free(); | ||
407 | } | ||
408 | |||