update for beta release
[framework/uifw/e17.git] / src / modules / comp / e_mod_comp.c
1 #include "e.h"
2 #include "e_mod_main.h"
3 #include "e_mod_comp.h"
4 #include "e_mod_comp_update.h"
5
6 #define OVER_FLOW 2
7
8 //////////////////////////////////////////////////////////////////////////
9 //
10 // TODO (no specific order):
11 //   1. abstract evas object and compwin so we can duplicate the object N times
12 //      in N canvases - for winlist, everything, pager etc. too
13 //   2. implement "unmapped composite cache" -> N pixels worth of unmapped
14 //      windows to be fully composited. only the most active/recent.
15 //   3. for unmapped windows - when window goes out of unmapped comp cache
16 //      make a miniature copy (1/4 width+height?) and set property on window
17 //      with pixmap id
18 //   8. obey transparent property
19 //   9. shortcut lots of stuff to draw inside the compositor - shelf,
20 //      wallpaper, efm - hell even menus and anything else in e (this is what
21 //      e18 was mostly about)
22 //  10. fullscreen windows need to be able to bypass compositing *seems buggy*
23 //
24 //////////////////////////////////////////////////////////////////////////
25
26 struct _E_Comp
27 {
28    Ecore_X_Window  win;
29    Ecore_Evas     *ee;
30    Ecore_X_Window  ee_win;
31    Evas           *evas;
32    E_Manager      *man;
33    Eina_Inlist    *wins;
34    Eina_List      *wins_list;
35    Eina_List      *updates;
36    Ecore_Animator *render_animator;
37    Ecore_Job      *update_job;
38    Ecore_Timer    *new_up_timer;
39    Evas_Object    *fps_bg;
40    Evas_Object    *fps_fg;
41    int             animating;
42    int             render_overflow;
43    double          frametimes[122];
44    int             frameskip;
45
46    E_Manager_Comp  comp;
47    Ecore_X_Window  cm_selection;
48
49    Eina_Bool       gl : 1;
50    Eina_Bool       grabbed : 1;
51    Eina_Bool       nocomp : 1;
52    Eina_Bool       wins_invalid : 1;
53 };
54
55 struct _E_Comp_Win
56 {
57    EINA_INLIST;
58
59    E_Comp              *c;  // parent compositor
60    Ecore_X_Window       win;  // raw window - for menus etc.
61    E_Border            *bd;  // if its a border - later
62    E_Popup             *pop;  // if its a popup - later
63    E_Menu              *menu;  // if it is a menu - later
64    int                  x, y, w, h;  // geometry
65    struct
66    {
67       int x, y, w, h; // hidden geometry (used when its unmapped and re-instated on map)
68    } hidden;
69    int                  pw, ph;  // pixmap w/h
70    int                  border;  // border width
71    Ecore_X_Pixmap       pixmap;  // the compositing pixmap
72    Ecore_X_Damage       damage;  // damage region
73    Ecore_X_Visual       vis;  // window visual
74    int                  depth;  // window depth
75    Evas_Object         *obj;  // composite object
76    Evas_Object         *shobj;  // shadow object
77    Eina_List           *obj_mirror;  // extra mirror objects
78    Ecore_X_Image       *xim;  // x image - software fallback
79    E_Update            *up;  // update handler
80    E_Object_Delfn      *dfn;  // delete function handle for objects being tracked
81    Ecore_X_Sync_Counter counter;  // sync counter for syncronised drawing
82    Ecore_Timer         *update_timeout;  // max time between damage and "done" event
83    Ecore_Timer         *ready_timeout;  // max time on show (new window draw) to wait for window contents to be ready if sync protocol not handled. this is fallback.
84    int                  dmg_updates;  // num of damage event updates since a redirect
85    Ecore_X_Rectangle   *rects;  // shape rects... if shaped :(
86    int                  rects_num;  // num rects above
87
88    Ecore_X_Pixmap       cache_pixmap;  // the cached pixmap (1/nth the dimensions)
89    int                  cache_w, cache_h;  // cached pixmap size
90    int                  update_count;  // how many updates have happened to this win
91    double               last_visible_time;  // last time window was visible
92    double               last_draw_time;  // last time window was damaged
93
94    int                  pending_count;  // pending event count
95    
96    unsigned int         opacity;  // opacity set with _NET_WM_WINDOW_OPACITY
97
98    char                *title, *name, *clas, *role;  // fetched for override-redirect windowa
99    Ecore_X_Window_Type  primary_type;  // fetched for override-redirect windowa
100
101    unsigned char        misses; // number of sync misses
102
103    Eina_Bool            delete_pending : 1;  // delete pendig
104    Eina_Bool            hidden_override : 1;  // hidden override
105    Eina_Bool            animating : 1;  // it's busy animating - defer hides/dels
106    Eina_Bool            force : 1;  // force del/hide even if animating
107    Eina_Bool            defer_hide : 1;  // flag to get hide to work on deferred hide
108    Eina_Bool            delete_me : 1;  // delete me!
109    Eina_Bool            visible : 1;  // is visible
110    Eina_Bool            input_only : 1;  // is input_only
111    
112    Eina_Bool            override : 1;  // is override-redirect
113    Eina_Bool            argb : 1;  // is argb
114    Eina_Bool            shaped : 1;  // is shaped
115    Eina_Bool            update : 1;  // has updates to fetch
116    Eina_Bool            redirected : 1;  // has updates to fetch
117    Eina_Bool            shape_changed : 1;  // shape changed
118    Eina_Bool            native : 1;  // native
119    Eina_Bool            drawme : 1;  // drawme flag fo syncing rendering
120    
121    Eina_Bool            invalid : 1;  // invalid depth used - just use as marker
122    Eina_Bool            nocomp : 1;  // nocomp applied
123    Eina_Bool            needpix : 1;  // need new pixmap
124    Eina_Bool            needxim : 1;  // need new xim
125    Eina_Bool            real_hid : 1;  // last hide was a real window unmap
126    Eina_Bool            inhash : 1;  // is in the windows hash
127    Eina_Bool            show_ready : 1;  // is this window ready for its first show
128    Eina_Bool            show_anim : 1; // ran show animation   
129 };
130
131 static Eina_List *handlers = NULL;
132 static Eina_List *compositors = NULL;
133 static Eina_Hash *windows = NULL;
134 static Eina_Hash *borders = NULL;
135 static Eina_Hash *damages = NULL;
136
137 //////////////////////////////////////////////////////////////////////////
138
139 #if 0
140 #define DBG(f, x ...) printf(f, ##x)
141 #else
142 #define DBG(f, x ...)
143 #endif
144
145 static void _e_mod_comp_win_ready_timeout_setup(E_Comp_Win *cw);
146 static void _e_mod_comp_render_queue(E_Comp *c);
147 static void _e_mod_comp_win_damage(E_Comp_Win *cw,
148                                    int         x,
149                                    int         y,
150                                    int         w,
151                                    int         h,
152                                    Eina_Bool   dmg);
153 static void _e_mod_comp_win_render_queue(E_Comp_Win *cw);
154 static void _e_mod_comp_win_del(E_Comp_Win *cw);
155 static void _e_mod_comp_win_real_hide(E_Comp_Win *cw);
156 static void _e_mod_comp_win_hide(E_Comp_Win *cw);
157 static void _e_mod_comp_win_configure(E_Comp_Win *cw,
158                                       int         x,
159                                       int         y,
160                                       int         w,
161                                       int         h,
162                                       int         border);
163
164 static void
165 _e_mod_comp_child_show(E_Comp_Win *cw)
166 {
167    evas_object_show(cw->shobj);
168    if (cw->bd)
169      {
170         Eina_List *l;
171         E_Border *tmp;
172
173         EINA_LIST_FOREACH(cw->bd->client.e.state.video_child, l, tmp)
174           {
175              E_Comp_Win *tcw;
176
177              tcw = eina_hash_find(borders, e_util_winid_str_get(tmp->client.win));
178              if (!tcw) continue ;
179
180              evas_object_show(tcw->shobj);
181           }
182      }
183 }
184
185 static void
186 _e_mod_comp_child_hide(E_Comp_Win *cw)
187 {
188    evas_object_hide(cw->shobj);
189    if (cw->bd)
190      {
191         Eina_List *l;
192         E_Border *tmp;
193
194         EINA_LIST_FOREACH(cw->bd->client.e.state.video_child, l, tmp)
195           {
196              E_Comp_Win *tcw;
197
198              tcw = eina_hash_find(borders, e_util_winid_str_get(tmp->client.win));
199              if (!tcw) continue ;
200
201              evas_object_hide(tcw->shobj);
202           }
203      }
204 }
205
206 static void
207 _e_mod_comp_cb_pending_after(void *data             __UNUSED__,
208                              E_Manager *man         __UNUSED__,
209                              E_Manager_Comp_Source *src)
210 {
211    E_Comp_Win *cw = (E_Comp_Win *)src;
212    cw->pending_count--;
213    if (!cw->delete_pending) return;
214    if (cw->pending_count == 0)
215      {
216         free(cw);
217      }
218 }
219
220 static E_Comp_Win *
221 _e_mod_comp_fullscreen_check(E_Comp *c)
222 {
223    E_Comp_Win *cw;
224
225    if (!c->wins) return NULL;
226    EINA_INLIST_REVERSE_FOREACH(c->wins, cw)
227      {
228         if ((!cw->visible) || (cw->input_only) || (cw->invalid))
229           continue;
230         if ((cw->x == 0) && (cw->y == 0) &&
231             ((cw->x + cw->w) >= c->man->w) &&
232             ((cw->y + cw->h) >= c->man->h) &&
233             (!cw->argb) && (!cw->shaped)
234             )
235           {
236              return cw;
237           }
238         return NULL;
239      }
240    return NULL;
241 }
242
243 static inline Eina_Bool
244 _e_mod_comp_shaped_check(int                      w,
245                          int                      h,
246                          const Ecore_X_Rectangle *rects,
247                          int                      num)
248 {
249    if ((!rects) || (num < 1)) return EINA_FALSE;
250    if (num > 1) return EINA_TRUE;
251    if ((rects[0].x == 0) && (rects[0].y == 0) &&
252        ((int)rects[0].width == w) && ((int)rects[0].height == h))
253      return EINA_FALSE;
254    return EINA_TRUE;
255 }
256
257 static inline Eina_Bool
258 _e_mod_comp_win_shaped_check(const E_Comp_Win        *cw,
259                              const Ecore_X_Rectangle *rects,
260                              int                      num)
261 {
262    return _e_mod_comp_shaped_check(cw->w, cw->h, rects, num);
263 }
264
265 static void
266 _e_mod_comp_win_shape_rectangles_apply(E_Comp_Win              *cw,
267                                        const Ecore_X_Rectangle *rects,
268                                        int                      num)
269 {
270    Eina_List *l;
271    Evas_Object *o;
272    int i;
273
274    DBG("SHAPE [0x%x] change, rects=%p (%d)\n", cw->win, rects, num);
275    if (!_e_mod_comp_win_shaped_check(cw, rects, num))
276      {
277         rects = NULL;
278      }
279    if (rects)
280      {
281         unsigned int *pix, *p;
282         unsigned char *spix, *sp;
283         int w, h, px, py;
284
285         evas_object_image_size_get(cw->obj, &w, &h);
286         if ((w > 0) && (h > 0))
287           {
288              if (cw->native)
289                {
290                   printf("BUGGER: shape with native surface? cw=%p\n", cw);
291                   return;
292                }
293
294              evas_object_image_native_surface_set(cw->obj, NULL);
295              evas_object_image_alpha_set(cw->obj, 1);
296              EINA_LIST_FOREACH(cw->obj_mirror, l, o)
297                {
298                   evas_object_image_native_surface_set(o, NULL);
299                   evas_object_image_alpha_set(o, 1);
300                }
301              pix = evas_object_image_data_get(cw->obj, 1);
302              if (pix)
303                {
304                   spix = calloc(w * h, sizeof(unsigned char));
305                   if (spix)
306                     {
307                        DBG("SHAPE [0x%x] rects %i\n", cw->win, num);
308                        for (i = 0; i < num; i++)
309                          {
310                             int rx, ry, rw, rh;
311
312                             rx = rects[i].x; ry = rects[i].y;
313                             rw = rects[i].width; rh = rects[i].height;
314                             E_RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, w, h);
315                             sp = spix + (w * ry) + rx;
316                             for (py = 0; py < rh; py++)
317                               {
318                                  for (px = 0; px < rw; px++)
319                                    {
320                                       *sp = 0xff; sp++;
321                                    }
322                                  sp += w - rw;
323                               }
324                          }
325                        sp = spix;
326                        p = pix;
327                        for (py = 0; py < h; py++)
328                          {
329                             for (px = 0; px < w; px++)
330                               {
331                                  unsigned int mask, imask;
332
333                                  mask = ((unsigned int)(*sp)) << 24;
334                                  imask = mask >> 8;
335                                  imask |= imask >> 8;
336                                  imask |= imask >> 8;
337                                  *p = mask | (*p & imask);
338 //                                 if (*sp) *p = 0xff000000 | *p;
339 //                                 else *p = 0x00000000;
340                                  sp++;
341                                  p++;
342                               }
343                          }
344                        free(spix);
345                     }
346                   evas_object_image_data_set(cw->obj, pix);
347                   evas_object_image_data_update_add(cw->obj, 0, 0, w, h);
348                   EINA_LIST_FOREACH(cw->obj_mirror, l, o)
349                     {
350                        evas_object_image_data_set(o, pix);
351                        evas_object_image_data_update_add(o, 0, 0, w, h);
352                     }
353                }
354           }
355      }
356    else
357      {
358         if (cw->shaped)
359           {
360              unsigned int *pix, *p;
361              int w, h, px, py;
362
363              evas_object_image_size_get(cw->obj, &w, &h);
364              if ((w > 0) && (h > 0))
365                {
366                   if (cw->native)
367                     {
368                        fprintf(stderr, "BUGGER: shape with native surface? cw=%p\n", cw);
369                        return;
370                     }
371
372                   evas_object_image_alpha_set(cw->obj, 0);
373                   EINA_LIST_FOREACH(cw->obj_mirror, l, o)
374                     {
375                        evas_object_image_alpha_set(o, 1);
376                     }
377                   pix = evas_object_image_data_get(cw->obj, 1);
378                   if (pix)
379                     {
380                        p = pix;
381                        for (py = 0; py < h; py++)
382                          {
383                             for (px = 0; px < w; px++)
384                               *p |= 0xff000000;
385                          }
386                     }
387                   evas_object_image_data_set(cw->obj, pix);
388                   evas_object_image_data_update_add(cw->obj, 0, 0, w, h);
389                   EINA_LIST_FOREACH(cw->obj_mirror, l, o)
390                     {
391                        evas_object_image_data_set(o, pix);
392                        evas_object_image_data_update_add(o, 0, 0, w, h);
393                     }
394                }
395           }
396         // dont need to fix alpha chanel as blending
397         // should be totally off here regardless of
398         // alpha channel content
399      }
400 }
401
402 static Eina_Bool
403 _e_mod_comp_cb_win_show_ready_timeout(void *data)
404 {
405    E_Comp_Win *cw = data;
406    cw->show_ready = 1;
407    if (cw->visible)
408      {
409           if (!cw->update)
410             {
411                if (cw->update_timeout)
412                  {
413                     ecore_timer_del(cw->update_timeout);
414                     cw->update_timeout = NULL;
415                  }
416                cw->update = 1;
417                cw->c->updates = eina_list_append(cw->c->updates, cw);
418             }
419           _e_mod_comp_win_render_queue(cw);
420      }
421    cw->ready_timeout = NULL;
422    return ECORE_CALLBACK_CANCEL;
423 }
424
425 static void
426 _e_mod_comp_win_ready_timeout_setup(E_Comp_Win *cw)
427 {
428    if (cw->ready_timeout)
429      {
430         ecore_timer_del(cw->ready_timeout);
431         cw->ready_timeout = NULL;
432      }
433    if (cw->show_ready) return;
434    if (cw->counter) return;
435 // FIXME: make show_ready option
436    if (0)
437      {
438         cw->show_ready = 1;
439      }
440    else
441      {
442         cw->ready_timeout = ecore_timer_add
443             (_comp_mod->conf->first_draw_delay, _e_mod_comp_cb_win_show_ready_timeout, cw);
444      }
445 }
446
447 static void
448 _e_mod_comp_win_update(E_Comp_Win *cw)
449 {
450    Eina_List *l;
451    Evas_Object *o;
452    E_Update_Rect *r;
453    int i;
454    int pshaped = cw->shaped;
455
456    DBG("UPDATE [0x%x] pm = %x\n", cw->win, cw->pixmap);
457    if (_comp_mod->conf->grab) ecore_x_grab();
458    cw->update = 0;
459
460    if (cw->argb)
461      {
462         if (cw->rects)
463           {
464              free(cw->rects);
465              cw->rects = NULL;
466              cw->rects_num = 0;
467           }
468      }
469    else
470      {
471         if (cw->shape_changed)
472           {
473              if (cw->rects)
474                {
475                   free(cw->rects);
476                   cw->rects = NULL;
477                   cw->rects_num = 0;
478                }
479              ecore_x_pixmap_geometry_get(cw->win, NULL, NULL, &(cw->w), &(cw->h));
480              cw->rects = ecore_x_window_shape_rectangles_get(cw->win, &(cw->rects_num));
481              if (cw->rects)
482                {
483                   for (i = 0; i < cw->rects_num; i++)
484                     {
485                        E_RECTS_CLIP_TO_RECT(cw->rects[i].x,
486                                             cw->rects[i].y,
487                                             cw->rects[i].width,
488                                             cw->rects[i].height,
489                                             0, 0, cw->w, cw->h);
490                     }
491                }
492              if (!_e_mod_comp_win_shaped_check(cw, cw->rects, cw->rects_num))
493                {
494                   free(cw->rects);
495                   cw->rects = NULL;
496                   cw->rects_num = 0;
497                }
498              if ((cw->rects) && (!cw->shaped))
499                {
500                   cw->shaped = 1;
501                }
502              else if ((!cw->rects) && (cw->shaped))
503                {
504                   cw->shaped = 0;
505                }
506           }
507      }
508
509    if ((!cw->pixmap) || (cw->needpix))
510      {
511         Ecore_X_Pixmap pm;
512
513         pm = ecore_x_composite_name_window_pixmap_get(cw->win);
514         if (pm)
515           {
516              Ecore_X_Pixmap oldpm;
517
518              cw->needpix = 0;
519              if (cw->xim) cw->needxim = 1;
520              oldpm = cw->pixmap;
521              cw->pixmap = pm;
522              if (cw->pixmap)
523                {
524                   ecore_x_pixmap_geometry_get(cw->pixmap, NULL, NULL, &(cw->pw), &(cw->ph));
525                   _e_mod_comp_win_ready_timeout_setup(cw);
526                   if ((cw->pw > 0) && (cw->ph > 0))
527                      evas_object_resize(cw->obj, cw->pw, cw->ph);
528                }
529              else
530                {
531                   cw->pw = 0;
532                   cw->ph = 0;
533                }
534              DBG("REND [0x%x] pixmap = [0x%x], %ix%i\n", cw->win, cw->pixmap, cw->pw, cw->ph);
535              if ((cw->pw <= 0) || (cw->ph <= 0))
536                {
537                   if (cw->native)
538                     {
539                        DBG("  [0x%x] free native\n", cw->win);
540                        evas_object_image_native_surface_set(cw->obj, NULL);
541                        cw->native = 0;
542                        EINA_LIST_FOREACH(cw->obj_mirror, l, o)
543                          {
544                             evas_object_image_native_surface_set(o, NULL);
545                          }
546                     }
547                   if (cw->pixmap)
548                     {
549                        DBG("  [0x%x] free pixmap\n", cw->win);
550                        ecore_x_pixmap_free(cw->pixmap);
551                        cw->pixmap = 0;
552 //                       cw->show_ready = 0; // hmm maybe not needed?
553                     }
554                   cw->pw = 0;
555                   cw->ph = 0;
556                }
557              ecore_x_e_comp_pixmap_set(cw->win, cw->pixmap);
558              cw->native = 0;
559              DBG("  [0x%x] up resize %ix%i\n", cw->win, cw->pw, cw->ph);
560              e_mod_comp_update_resize(cw->up, cw->pw, cw->ph);
561              e_mod_comp_update_add(cw->up, 0, 0, cw->pw, cw->ph);
562              if (oldpm)
563                {
564                   DBG("  [0x%x] free pm %x\n", cw->win, oldpm);
565                   if (cw->native)
566                     {
567                        cw->native = 0;
568                        if (!((cw->pw > 0) && (cw->ph > 0)))
569                          {
570                             evas_object_image_native_surface_set(cw->obj, NULL);
571                             EINA_LIST_FOREACH(cw->obj_mirror, l, o)
572                               {
573                                  evas_object_image_native_surface_set(o, NULL);
574                               }
575                          }
576                     }
577                   ecore_x_pixmap_free(oldpm);
578                }
579           }
580      }
581    if (!((cw->pw > 0) && (cw->ph > 0)))
582      {
583         if (_comp_mod->conf->grab) ecore_x_ungrab();
584         return;
585      }
586
587    evas_object_move(cw->shobj, cw->x, cw->y);
588    // was cw->w / cw->h
589    evas_object_resize(cw->shobj, cw->pw, cw->ph);
590
591    if ((cw->c->gl) && (_comp_mod->conf->texture_from_pixmap) &&
592        (!cw->shaped) && (!cw->rects))
593      {
594         DBG("DEBUG - pm now %x\n", ecore_x_composite_name_window_pixmap_get(cw->win));
595         evas_object_image_size_set(cw->obj, cw->pw, cw->ph);
596         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
597           {
598              evas_object_image_size_set(o, cw->pw, cw->ph);
599           }
600         if (!cw->native)
601           {
602              Evas_Native_Surface ns;
603
604              ns.version = EVAS_NATIVE_SURFACE_VERSION;
605              ns.type = EVAS_NATIVE_SURFACE_X11;
606              ns.data.x11.visual = cw->vis;
607              ns.data.x11.pixmap = cw->pixmap;
608              evas_object_image_native_surface_set(cw->obj, &ns);
609              DBG("NATIVE [0x%x] %x %ix%i\n", cw->win, cw->pixmap, cw->pw, cw->ph);
610              cw->native = 1;
611              EINA_LIST_FOREACH(cw->obj_mirror, l, o)
612                {
613                   evas_object_image_native_surface_set(o, &ns);
614                }
615           }
616         r = e_mod_comp_update_rects_get(cw->up);
617         if (r)
618           {
619              e_mod_comp_update_clear(cw->up);
620              for (i = 0; r[i].w > 0; i++)
621                {
622                   int x, y, w, h;
623
624                   x = r[i].x; y = r[i].y;
625                   w = r[i].w; h = r[i].h;
626                   DBG("UPDATE [0x%x] pm [0x%x] %i %i %ix%i\n", cw->win, cw->pixmap, x, y, w, h);
627                   evas_object_image_data_update_add(cw->obj, x, y, w, h);
628                   EINA_LIST_FOREACH(cw->obj_mirror, l, o)
629                     {
630                        evas_object_image_data_update_add(o, x, y, w, h);
631                     }
632                }
633              free(r);
634           }
635         else
636           {
637              DBG("UPDATE [0x%x] NO RECTS!!! %i %i - %i %i\n", cw->win, cw->up->w, cw->up->h, cw->up->tw, cw->up->th);
638 //             cw->update = 1;
639           }
640      }
641    else
642      {
643         if (cw->native)
644           {
645              evas_object_image_native_surface_set(cw->obj, NULL);
646              EINA_LIST_FOREACH(cw->obj_mirror, l, o)
647                {
648                   evas_object_image_native_surface_set(o, NULL);
649                }
650              cw->native = 0;
651           }
652         if (cw->needxim)
653           {
654              cw->needxim = 0;
655              if (cw->xim)
656                {
657                   evas_object_image_size_set(cw->obj, 1, 1);
658                   evas_object_image_data_set(cw->obj, NULL);
659                   EINA_LIST_FOREACH(cw->obj_mirror, l, o)
660                     {
661                        evas_object_image_size_set(o, 1, 1);
662                        evas_object_image_data_set(o, NULL);
663                     }
664                   ecore_x_image_free(cw->xim);
665                   cw->xim = NULL;
666                }
667           }
668         if (!cw->xim)
669           {
670              if ((cw->xim = ecore_x_image_new(cw->pw, cw->ph, cw->vis, cw->depth)))
671                e_mod_comp_update_add(cw->up, 0, 0, cw->pw, cw->ph);
672           }
673         r = e_mod_comp_update_rects_get(cw->up);
674         if (r)
675           {
676              if (cw->xim)
677                {
678                   unsigned int *pix;
679
680                   pix = ecore_x_image_data_get(cw->xim, NULL, NULL, NULL);
681                   evas_object_image_data_set(cw->obj, pix);
682                   evas_object_image_size_set(cw->obj, cw->pw, cw->ph);
683                   EINA_LIST_FOREACH(cw->obj_mirror, l, o)
684                     {
685                        evas_object_image_data_set(o, pix);
686                        evas_object_image_size_set(o, cw->pw, cw->ph);
687                     }
688
689                   e_mod_comp_update_clear(cw->up);
690                   for (i = 0; r[i].w > 0; i++)
691                     {
692                        int x, y, w, h;
693
694                        x = r[i].x; y = r[i].y;
695                        w = r[i].w; h = r[i].h;
696                        if (!ecore_x_image_get(cw->xim, cw->pixmap, x, y, x, y, w, h))
697                          {
698                             DBG("UPDATE [0x%x] %i %i %ix%i FAIL!!!!!!!!!!!!!!!!!\n", cw->win, x, y, w, h);
699                             e_mod_comp_update_add(cw->up, x, y, w, h);
700                             cw->update = 1;
701                          }
702                        else
703                          {
704 // why do we neeed these 2? this smells wrong
705                               pix = ecore_x_image_data_get(cw->xim, NULL, NULL, NULL);
706                               DBG("UPDATE [0x%x] %i %i %ix%i -- pix = %p\n", cw->win, x, y, w, h, pix);
707                               evas_object_image_data_set(cw->obj, pix);
708                               evas_object_image_data_update_add(cw->obj, x, y, w, h);
709                               EINA_LIST_FOREACH(cw->obj_mirror, l, o)
710                                 {
711                                    evas_object_image_data_set(o, pix);
712                                    evas_object_image_data_update_add(o, x, y, w, h);
713                                 }
714                          }
715                     }
716                }
717              free(r);
718              if (cw->shaped)
719                {
720                   _e_mod_comp_win_shape_rectangles_apply(cw, cw->rects, cw->rects_num);
721                }
722              else
723                {
724                   if (cw->shape_changed)
725                     _e_mod_comp_win_shape_rectangles_apply(cw, cw->rects, cw->rects_num);
726                }
727              cw->shape_changed = 0;
728           }
729         else
730           {
731              DBG("UPDATE [0x%x] NO RECTS!!! %i %i - %i %i\n", cw->win, cw->up->w, cw->up->h, cw->up->tw, cw->up->th);
732 // causes updates to be flagged when not needed - disabled
733 //             cw->update = 1;
734           }
735      }
736 // FIXME: below cw update check screws with show
737    if (/*(!cw->update) &&*/ (cw->visible) && (cw->dmg_updates >= 1) &&
738        (cw->show_ready) && (!cw->bd || cw->bd->visible))
739      {
740         if (!evas_object_visible_get(cw->shobj))
741           {
742              if (!cw->hidden_override)
743                {
744                   _e_mod_comp_child_show(cw);
745                   _e_mod_comp_win_render_queue(cw);
746                }
747
748              if (!cw->show_anim)
749                {
750                   edje_object_signal_emit(cw->shobj, "e,state,visible,on", "e");
751                   if (!cw->animating)
752                     {
753                        cw->c->animating++;
754                     }
755
756                   cw->animating = 1;
757              
758                   cw->pending_count++;
759                   e_manager_comp_event_src_visibility_send
760                     (cw->c->man, (E_Manager_Comp_Source *)cw,
761                      _e_mod_comp_cb_pending_after, cw->c);
762
763                   cw->show_anim = EINA_TRUE;
764                }
765           }
766      }
767    if ((cw->shobj) && (cw->obj))
768      {
769         if (pshaped != cw->shaped)
770           {
771              if (cw->shaped)
772                edje_object_signal_emit(cw->shobj, "e,state,shadow,off", "e");
773              else
774                edje_object_signal_emit(cw->shobj, "e,state,shadow,on", "e");
775           }
776      }
777
778    if (_comp_mod->conf->grab) ecore_x_ungrab();
779 }
780
781 static void
782 _e_mod_comp_pre_swap(void   *data,
783                      Evas *e __UNUSED__)
784 {
785    E_Comp *c = data;
786
787    if (_comp_mod->conf->grab)
788      {
789         if (c->grabbed)
790           {
791              ecore_x_ungrab();
792              c->grabbed = 0;
793           }
794      }
795 }
796
797 static Eina_Bool
798 _e_mod_comp_cb_delayed_update_timer(void *data)
799 {
800    E_Comp *c = data;
801    _e_mod_comp_render_queue(c);
802    c->new_up_timer = NULL;
803    return ECORE_CALLBACK_CANCEL;
804 }
805
806 static void
807 _e_mod_comp_fps_update(E_Comp *c)
808 {
809    if (_comp_mod->conf->fps_show)
810      {
811         if (!c->fps_bg)
812           {
813              c->fps_bg = evas_object_rectangle_add(c->evas);
814              evas_object_color_set(c->fps_bg, 0, 0, 0, 128);
815              evas_object_layer_set(c->fps_bg, EVAS_LAYER_MAX);
816              evas_object_show(c->fps_bg);
817
818              c->fps_fg = evas_object_text_add(c->evas);
819              evas_object_text_font_set(c->fps_fg, "Sans", 10);
820              evas_object_text_text_set(c->fps_fg, "???");
821              evas_object_color_set(c->fps_fg, 255, 255, 255, 255);
822              evas_object_layer_set(c->fps_fg, EVAS_LAYER_MAX);
823              evas_object_show(c->fps_fg);
824           }
825      }
826    else
827      {
828         if (c->fps_fg)
829           {
830              evas_object_del(c->fps_fg);
831              c->fps_fg = NULL;
832           }
833         if (c->fps_bg)
834           {
835              evas_object_del(c->fps_bg);
836              c->fps_bg = NULL;
837           }
838      }
839 }
840
841 static Eina_Bool
842 _e_mod_comp_cb_update(E_Comp *c)
843 {
844    Eina_List *l;
845    Evas_Object *o;
846    E_Comp_Win *cw;
847    Eina_List *new_updates = NULL; // for failed pixmap fetches - get them next frame
848    Eina_List *update_done = NULL;
849 //   static int doframeinfo = -1;
850
851    c->update_job = NULL;
852    DBG("UPDATE ALL\n");
853    if (c->nocomp) goto nocomp;
854    if (_comp_mod->conf->grab)
855      {
856         ecore_x_grab();
857         ecore_x_sync();
858         c->grabbed = 1;
859      }
860    EINA_LIST_FREE(c->updates, cw)
861      {
862         if (_comp_mod->conf->efl_sync)
863           {
864              if (((cw->counter) && (cw->drawme)) || (!cw->counter))
865                {
866                   _e_mod_comp_win_update(cw);
867                   if (cw->drawme)
868                     {
869                        update_done = eina_list_append(update_done, cw);
870                        cw->drawme = 0;
871                     }
872                }
873              else
874                cw->update = 0;
875           }
876         else
877           _e_mod_comp_win_update(cw);
878         if (cw->update)
879           {
880              new_updates = eina_list_append(new_updates, cw);
881           }
882      }
883    _e_mod_comp_fps_update(c);
884    if (_comp_mod->conf->fps_show)
885      {
886         char buf[128];
887         double fps = 0.0, t, dt;
888         int i;
889         Evas_Coord x = 0, y = 0, w = 0, h = 0;
890         E_Zone *z;
891
892         t = ecore_time_get();
893         if (_comp_mod->conf->fps_average_range < 1)
894           _comp_mod->conf->fps_average_range = 30;
895         else if (_comp_mod->conf->fps_average_range > 120)
896           _comp_mod->conf->fps_average_range = 120;
897         dt = t - c->frametimes[_comp_mod->conf->fps_average_range - 1];
898         if (dt > 0.0) fps = (double)_comp_mod->conf->fps_average_range / dt;
899         else fps = 0.0;
900         if (fps > 0.0) snprintf(buf, sizeof(buf), "FPS: %1.1f", fps);
901         else snprintf(buf, sizeof(buf), "N/A");
902         for (i = 121; i >= 1; i--) c->frametimes[i] = c->frametimes[i - 1];
903         c->frametimes[0] = t;
904         c->frameskip++;
905         if (c->frameskip >= _comp_mod->conf->fps_average_range)
906           {
907              c->frameskip = 0;
908              evas_object_text_text_set(c->fps_fg, buf);
909           }
910         evas_object_geometry_get(c->fps_fg, NULL, NULL, &w, &h);
911         w += 8;
912         h += 8;
913         z = e_util_zone_current_get(c->man);
914         if (z)
915           {
916              switch (_comp_mod->conf->fps_corner)
917                {
918                 case 3: // bottom-right
919                   x = z->x + z->w - w;
920                   y = z->y + z->h - h;
921                   break;
922
923                 case 2: // bottom-left
924                   x = z->x;
925                   y = z->y + z->h - h;
926                   break;
927
928                 case 1: // top-right
929                   x = z->x + z->w - w;
930                   y = z->y;
931                   break;
932
933                 default: // 0 // top-left
934                   x = z->x;
935                   y = z->y;
936                   break;
937                }
938           }
939         evas_object_move(c->fps_bg, x, y);
940         evas_object_resize(c->fps_bg, w, h);
941         evas_object_move(c->fps_fg, x + 4, y + 4);
942      }
943    if (_comp_mod->conf->lock_fps)
944      {
945         DBG("MANUAL RENDER...\n");
946 //        ecore_evas_manual_render(c->ee);
947      }
948    if (_comp_mod->conf->efl_sync)
949      {
950         EINA_LIST_FREE(update_done, cw)
951           {
952              ecore_x_sync_counter_inc(cw->counter, 1);
953           }
954      }
955    if (_comp_mod->conf->grab)
956      {
957         if (c->grabbed)
958           {
959              c->grabbed = 0;
960              ecore_x_ungrab();
961           }
962      }
963    if (new_updates)
964      {
965         DBG("JOB1...\n");
966         if (c->new_up_timer) ecore_timer_del(c->new_up_timer);
967         c->new_up_timer =
968           ecore_timer_add(0.001, _e_mod_comp_cb_delayed_update_timer, c);
969 //        _e_mod_comp_render_queue(c);
970      }
971    c->updates = new_updates;
972    if (!c->animating) c->render_overflow--;
973 /*
974    if (doframeinfo == -1)
975      {
976         doframeinfo = 0;
977         if (getenv("DFI")) doframeinfo = 1;
978      }
979    if (doframeinfo)
980      {
981         static double t0 = 0.0;
982         double td, t;
983
984         t = ecore_time_get();
985         td = t - t0;
986         if (td > 0.0)
987           {
988              int fps, i;
989
990              fps = 1.0 / td;
991              for (i = 0; i < fps; i+= 2) putchar('=');
992              printf(" : %3.3f\n", 1.0 / td);
993           }
994         t0 = t;
995      }
996  */
997 nocomp:
998    cw = _e_mod_comp_fullscreen_check(c);
999    if (cw)
1000      {
1001         if (_comp_mod->conf->nocomp_fs)
1002           {
1003              if (!c->nocomp)
1004                {
1005                   printf("NOCOMP!\n");
1006                   printf("kill comp %x\n", cw->win);
1007                   c->nocomp = 1;
1008                   c->render_overflow = OVER_FLOW;
1009                   ecore_x_window_hide(c->win);
1010                   cw->nocomp = 1;
1011                   if (cw->redirected)
1012                     {
1013                        printf("^^^^ undirect1 %x\n", cw->win);
1014                        ecore_x_composite_unredirect_window(cw->win, ECORE_X_COMPOSITE_UPDATE_MANUAL);
1015                        cw->redirected = 0;
1016                        cw->pw = 0;
1017                        cw->ph = 0;
1018                     }
1019                   if (cw->pixmap)
1020                     {
1021                        ecore_x_pixmap_free(cw->pixmap);
1022                        cw->pixmap = 0;
1023                        cw->pw = 0;
1024                        cw->ph = 0;
1025                        ecore_x_e_comp_pixmap_set(cw->win, cw->pixmap);
1026                        cw->show_ready = 0; // hmm maybe not needed?
1027                     }
1028                   if (cw->xim)
1029                     {
1030                        evas_object_image_size_set(cw->obj, 1, 1);
1031                        evas_object_image_data_set(cw->obj, NULL);
1032                        EINA_LIST_FOREACH(cw->obj_mirror, l, o)
1033                          {
1034                             evas_object_image_size_set(o, 1, 1);
1035                             evas_object_image_data_set(o, NULL);
1036                          }
1037                        ecore_x_image_free(cw->xim);
1038                        cw->xim = NULL;
1039                     }
1040                   if (cw->damage)
1041                     {
1042                        Ecore_X_Region parts;
1043
1044                        eina_hash_del(damages, e_util_winid_str_get(cw->damage), cw);
1045                        parts = ecore_x_region_new(NULL, 0);
1046                        ecore_x_damage_subtract(cw->damage, 0, parts);
1047                        ecore_x_region_free(parts);
1048                        ecore_x_damage_free(cw->damage);
1049                        cw->damage = 0;
1050                     }
1051                   if (cw->update_timeout)
1052                     {
1053                        ecore_timer_del(cw->update_timeout);
1054                        cw->update_timeout = NULL;
1055                     }
1056                   if (cw->update)
1057                     {
1058                        cw->update = 0;
1059                        cw->c->updates = eina_list_remove(cw->c->updates, cw);
1060                     }
1061                   if (cw->counter)
1062                     {
1063                        if (cw->bd)
1064                          {
1065                             ecore_x_e_comp_sync_cancel_send(cw->bd->client.win);
1066                          }
1067                        else
1068                          {
1069                             ecore_x_e_comp_sync_cancel_send(cw->win);
1070                          }
1071                        ecore_x_sync_counter_inc(cw->counter, 1);
1072                     }
1073 //                  ecore_x_window_hide(cw->win);
1074 //                  ecore_x_window_show(cw->win);
1075                   DBG("JOB2...\n");
1076                   _e_mod_comp_render_queue(c);
1077                }
1078           }
1079      }
1080    else
1081      {
1082         if (c->nocomp)
1083           {
1084              printf("COMP!\n");
1085              c->nocomp = 0;
1086              c->render_overflow = OVER_FLOW;
1087              ecore_x_window_show(c->win);
1088              EINA_INLIST_FOREACH(c->wins, cw)
1089                {
1090                   if (!cw->nocomp) continue;
1091                   cw->nocomp = 0;
1092                   printf("restore comp %x --- %x\n", cw->win, cw->pixmap);
1093                   if (cw->pixmap) ecore_x_pixmap_free(cw->pixmap);
1094                   cw->pixmap = 0;
1095                   cw->pw = 0;
1096                   cw->ph = 0;
1097                   cw->native = 0;
1098                   cw->show_ready = 0; // hmm maybe not needed?
1099                   if (!cw->damage)
1100                     {
1101                        cw->damage = ecore_x_damage_new
1102                            (cw->win, ECORE_X_DAMAGE_REPORT_DELTA_RECTANGLES);
1103                        eina_hash_add(damages, e_util_winid_str_get(cw->damage), cw);
1104                     }
1105                   if (!cw->redirected)
1106                     {
1107                        printf("^^^^ redirect2 %x\n", cw->win);
1108                        printf("  redr\n");
1109                        ecore_x_composite_redirect_window(cw->win, ECORE_X_COMPOSITE_UPDATE_MANUAL);
1110                        cw->pixmap = ecore_x_composite_name_window_pixmap_get(cw->win);
1111                        if (cw->pixmap)
1112                          {
1113                             ecore_x_pixmap_geometry_get(cw->pixmap, NULL, NULL, &(cw->pw), &(cw->ph));
1114                             _e_mod_comp_win_ready_timeout_setup(cw);
1115                          }
1116                        else
1117                          {
1118                             cw->pw = 0;
1119                             cw->ph = 0;
1120                          }
1121                        printf("  %x %ix%i\n", cw->pixmap, cw->pw, cw->ph);
1122                        if ((cw->pw <= 0) || (cw->ph <= 0))
1123                          {
1124                             ecore_x_pixmap_free(cw->pixmap);
1125                             cw->pixmap = 0;
1126 //                            cw->show_ready = 0; // hmm maybe not needed?
1127                          }
1128                        ecore_x_e_comp_pixmap_set(cw->win, cw->pixmap);
1129                        cw->redirected = 1;
1130                        cw->dmg_updates = 0;
1131                        DBG("  [0x%x] up resize2 %ix%i\n", cw->win, cw->pw, cw->ph);
1132                        e_mod_comp_update_resize(cw->up, cw->pw, cw->ph);
1133                        e_mod_comp_update_add(cw->up, 0, 0, cw->pw, cw->ph);
1134                     }
1135 //                  _e_mod_comp_win_damage(cw, 0, 0, cw->w, cw->h, 0);
1136                   if (cw->visible)
1137                     {
1138                        if (!cw->hidden_override) _e_mod_comp_child_show(cw);
1139                        cw->pending_count++;
1140                        e_manager_comp_event_src_visibility_send
1141                          (cw->c->man, (E_Manager_Comp_Source *)cw,
1142                          _e_mod_comp_cb_pending_after, cw->c);
1143      // no need for effect
1144                     }
1145                   _e_mod_comp_win_render_queue(cw);
1146                   if (cw->counter)
1147                     {
1148                        if (cw->bd)
1149                          {
1150                             ecore_x_e_comp_sync_begin_send(cw->bd->client.win);
1151                          }
1152                        else
1153                          {
1154                             ecore_x_e_comp_sync_begin_send(cw->win);
1155                          }
1156                     }
1157                }
1158           }
1159      }
1160
1161    DBG("UPDATE ALL DONE: overflow = %i\n", c->render_overflow);
1162    if (c->render_overflow <= 0)
1163      {
1164         c->render_overflow = 0;
1165         if (c->render_animator) c->render_animator = NULL;
1166         return ECORE_CALLBACK_CANCEL;
1167      }
1168    return ECORE_CALLBACK_RENEW;
1169 }
1170
1171 static void
1172 _e_mod_comp_cb_job(void *data)
1173 {
1174    DBG("UPDATE ALL JOB...\n");
1175    _e_mod_comp_cb_update(data);
1176 }
1177
1178 static Eina_Bool
1179 _e_mod_comp_cb_animator(void *data)
1180 {
1181    return _e_mod_comp_cb_update(data);
1182 }
1183
1184 static void
1185 _e_mod_comp_render_queue(E_Comp *c)
1186 {
1187    /* FIXME workaround */
1188    if (!c) return;
1189
1190    if (_comp_mod->conf->lock_fps)
1191      {
1192         if (c->render_animator)
1193           {
1194              c->render_overflow = OVER_FLOW;
1195              return;
1196           }
1197         c->render_animator = ecore_animator_add(_e_mod_comp_cb_animator, c);
1198      }
1199    else
1200      {
1201         if (c->update_job)
1202           {
1203              DBG("UPDATE JOB DEL...\n");
1204              ecore_job_del(c->update_job);
1205              c->update_job = NULL;
1206              c->render_overflow = 0;
1207           }
1208         DBG("UPDATE JOB ADD...\n");
1209         c->update_job = ecore_job_add(_e_mod_comp_cb_job, c);
1210      }
1211 }
1212
1213 static void
1214 _e_mod_comp_win_render_queue(E_Comp_Win *cw)
1215 {
1216    DBG("JOB3...\n");
1217    _e_mod_comp_render_queue(cw->c);
1218 }
1219
1220 static E_Comp *
1221 _e_mod_comp_find(Ecore_X_Window root)
1222 {
1223    Eina_List *l;
1224    E_Comp *c;
1225
1226    // fixme: use hash if compositors list > 4
1227    EINA_LIST_FOREACH(compositors, l, c)
1228      {
1229         if (c->man->root == root) return c;
1230      }
1231    return NULL;
1232 }
1233
1234 static E_Comp_Win *
1235 _e_mod_comp_win_find(Ecore_X_Window win)
1236 {
1237    return eina_hash_find(windows, e_util_winid_str_get(win));
1238 }
1239
1240 static E_Comp_Win *
1241 _e_mod_comp_border_client_find(Ecore_X_Window win)
1242 {
1243    return eina_hash_find(borders, e_util_winid_str_get(win));
1244 }
1245
1246 static E_Comp_Win *
1247 _e_mod_comp_win_damage_find(Ecore_X_Damage damage)
1248 {
1249    return eina_hash_find(damages, e_util_winid_str_get(damage));
1250 }
1251
1252 static Eina_Bool
1253 _e_mod_comp_win_is_borderless(E_Comp_Win *cw)
1254 {
1255    if (!cw->bd) return 1;
1256    if ((cw->bd->client.border.name) &&
1257        (!strcmp(cw->bd->client.border.name, "borderless")))
1258      return 1;
1259    return 0;
1260 }
1261
1262 static Eina_Bool
1263 _e_mod_comp_win_do_shadow(E_Comp_Win *cw)
1264 {
1265    if (cw->shaped) return 0;
1266    if (cw->argb)
1267      {
1268         if (_e_mod_comp_win_is_borderless(cw)) return 0;
1269      }
1270    return 1;
1271 }
1272
1273 static Eina_Bool
1274 _e_mod_comp_win_damage_timeout(void *data)
1275 {
1276    E_Comp_Win *cw = data;
1277
1278    if (!cw->update)
1279      {
1280         if (cw->update_timeout)
1281           {
1282              ecore_timer_del(cw->update_timeout);
1283              cw->update_timeout = NULL;
1284           }
1285         cw->update = 1;
1286         cw->c->updates = eina_list_append(cw->c->updates, cw);
1287      }
1288    cw->drawme = 1;
1289    _e_mod_comp_win_render_queue(cw);
1290    cw->update_timeout = NULL;
1291    return ECORE_CALLBACK_CANCEL;
1292 }
1293
1294 static void
1295 _e_mod_comp_object_del(void *data,
1296                        void *obj)
1297 {
1298    E_Comp_Win *cw = data;
1299
1300    if (!cw) return;
1301
1302    _e_mod_comp_win_render_queue(cw);
1303    if (obj == cw->bd)
1304      {
1305         if (cw->counter)
1306           {
1307              if (cw->bd)
1308                {
1309                   ecore_x_e_comp_sync_cancel_send(cw->bd->client.win);
1310                }
1311              else
1312                {
1313                   ecore_x_e_comp_sync_cancel_send(cw->win);
1314                }
1315              ecore_x_sync_counter_inc(cw->counter, 1);
1316           }
1317         if (cw->bd) eina_hash_del(borders, e_util_winid_str_get(cw->bd->client.win), cw);
1318         cw->bd = NULL;
1319         evas_object_data_del(cw->shobj, "border");
1320 // hmm - lockup?
1321 //        cw->counter = 0;
1322      }
1323    else if (obj == cw->pop)
1324      {
1325         cw->pop = NULL;
1326         evas_object_data_del(cw->shobj, "popup");
1327      }
1328    else if (obj == cw->menu)
1329      {
1330         cw->menu = NULL;
1331         evas_object_data_del(cw->shobj, "menu");
1332      }
1333    if (cw->dfn)
1334      {
1335         e_object_delfn_del(obj, cw->dfn);
1336         cw->dfn = NULL;
1337      }
1338 }
1339
1340 static void
1341 _e_mod_comp_done_defer(E_Comp_Win *cw)
1342 {
1343    if (cw->animating)
1344      {
1345         cw->c->animating--;
1346      }
1347    cw->animating = 0;
1348    _e_mod_comp_win_render_queue(cw);
1349    cw->force = 1;
1350    if (cw->defer_hide) _e_mod_comp_win_hide(cw);
1351    cw->force = 1;
1352    if (cw->delete_me) _e_mod_comp_win_del(cw);
1353    else cw->force = 0;
1354 }
1355
1356 static void
1357 _e_mod_comp_show_done(void                *data,
1358                       Evas_Object *obj     __UNUSED__,
1359                       const char *emission __UNUSED__,
1360                       const char *source   __UNUSED__)
1361 {
1362    E_Comp_Win *cw = data;
1363    _e_mod_comp_done_defer(cw);
1364 }
1365
1366 static void
1367 _e_mod_comp_hide_done(void                *data,
1368                       Evas_Object *obj     __UNUSED__,
1369                       const char *emission __UNUSED__,
1370                       const char *source   __UNUSED__)
1371 {
1372    E_Comp_Win *cw = data;
1373    _e_mod_comp_done_defer(cw);
1374 }
1375
1376 static void
1377 _e_mod_comp_win_sync_setup(E_Comp_Win    *cw,
1378                            Ecore_X_Window win)
1379 {
1380    if (!_comp_mod->conf->efl_sync) return;
1381
1382    if (cw->bd)
1383      {
1384         if (_e_mod_comp_win_is_borderless(cw) ||
1385             (_comp_mod->conf->loose_sync))
1386           cw->counter = ecore_x_e_comp_sync_counter_get(win);
1387         else
1388           {
1389              ecore_x_e_comp_sync_cancel_send(win);
1390           }
1391      }
1392    else
1393      cw->counter = ecore_x_e_comp_sync_counter_get(win);
1394    if (cw->counter)
1395      {
1396         ecore_x_e_comp_sync_begin_send(win);
1397         ecore_x_sync_counter_inc(cw->counter, 1);
1398      }
1399 }
1400
1401 static void
1402 _e_mod_comp_win_shadow_setup(E_Comp_Win *cw)
1403 {
1404    Evas_Object *o;
1405    int ok = 0;
1406    char buf[PATH_MAX];
1407    Eina_List *list = NULL, *l;
1408    Match *m;
1409    const char *title = NULL, *name = NULL, *clas = NULL, *role = NULL;
1410    Ecore_X_Window_Type primary_type = ECORE_X_WINDOW_TYPE_UNKNOWN;
1411
1412    evas_object_image_smooth_scale_set(cw->obj, _comp_mod->conf->smooth_windows);
1413    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
1414      {
1415         evas_object_image_smooth_scale_set(o, _comp_mod->conf->smooth_windows);
1416      }
1417    if (cw->bd)
1418      {
1419         list = _comp_mod->conf->match.borders;
1420         title = cw->bd->client.icccm.title;
1421         if (cw->bd->client.netwm.name) title = cw->bd->client.netwm.name;
1422         name = cw->bd->client.icccm.name;
1423         clas = cw->bd->client.icccm.class;
1424         role = cw->bd->client.icccm.window_role;
1425         primary_type = cw->bd->client.netwm.type;
1426      }
1427    else if (cw->pop)
1428      {
1429         // FIXME: i only added "shelf" as a name for popups that are shelves
1430         // ... need more nmes like for pager popup, evertything, exebuf
1431         // etc. etc.
1432               list = _comp_mod->conf->match.popups;
1433               name = cw->pop->name;
1434      }
1435    else if (cw->menu)
1436      {
1437         // FIXME: e has no way to tell e menus apart... need naming
1438           list = _comp_mod->conf->match.menus;
1439      }
1440    else
1441      {
1442         list = _comp_mod->conf->match.overrides;
1443         title = cw->title;
1444         name = cw->name;
1445         clas = cw->clas;
1446         role = cw->role;
1447         primary_type = cw->primary_type;
1448      }
1449
1450    EINA_LIST_FOREACH(list, l, m)
1451      {
1452         if (((m->title) && (!title)) ||
1453             ((title) && (m->title) && (!e_util_glob_match(title, m->title))))
1454           continue;
1455         if (((m->name) && (!name)) ||
1456             ((name) && (m->name) && (!e_util_glob_match(name, m->name))))
1457           continue;
1458         if (((m->clas) && (!clas)) ||
1459             ((clas) && (m->clas) && (!e_util_glob_match(clas, m->clas))))
1460           continue;
1461         if (((m->role) && (!role)) ||
1462             ((role) && (m->role) && (!e_util_glob_match(role, m->role))))
1463           continue;
1464         if ((primary_type != ECORE_X_WINDOW_TYPE_UNKNOWN) &&
1465             (m->primary_type != ECORE_X_WINDOW_TYPE_UNKNOWN) &&
1466             ((int)primary_type != m->primary_type))
1467           continue;
1468         if (cw->bd)
1469           {
1470              if (m->borderless != 0)
1471                {
1472                   int borderless = 0;
1473
1474                   if ((cw->bd->client.mwm.borderless) || (cw->bd->borderless))
1475                     borderless = 1;
1476                   if (!(((m->borderless == -1) && (!borderless)) ||
1477                         ((m->borderless == 1) && (borderless))))
1478                     continue;
1479                }
1480              if (m->dialog != 0)
1481                {
1482                   int dialog = 0;
1483
1484                   if (((cw->bd->client.icccm.transient_for != 0) ||
1485                        (cw->bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)))
1486                     dialog = 1;
1487                   if (!(((m->dialog == -1) && (!dialog)) ||
1488                         ((m->dialog == 1) && (dialog))))
1489                     continue;
1490                }
1491              if (m->accepts_focus != 0)
1492                {
1493                   int accepts_focus = 0;
1494
1495                   if (cw->bd->client.icccm.accepts_focus)
1496                     accepts_focus = 1;
1497                   if (!(((m->accepts_focus == -1) && (!accepts_focus)) ||
1498                         ((m->accepts_focus == 1) && (accepts_focus))))
1499                     continue;
1500                }
1501              if (m->vkbd != 0)
1502                {
1503                   int vkbd = 0;
1504
1505                   if (cw->bd->client.vkbd.vkbd)
1506                     vkbd = 1;
1507                   if (!(((m->vkbd == -1) && (!vkbd)) ||
1508                         ((m->vkbd == 1) && (vkbd))))
1509                     continue;
1510                }
1511              if (m->quickpanel != 0)
1512                {
1513                   int quickpanel = 0;
1514
1515                   if (cw->bd->client.illume.quickpanel.quickpanel)
1516                     quickpanel = 1;
1517                   if (!(((m->quickpanel == -1) && (!quickpanel)) ||
1518                         ((m->quickpanel == 1) && (quickpanel))))
1519                     continue;
1520                }
1521              if (m->argb != 0)
1522                {
1523                   if (!(((m->argb == -1) && (!cw->argb)) ||
1524                         ((m->argb == 1) && (cw->argb))))
1525                     continue;
1526                }
1527              if (m->fullscreen != 0)
1528                {
1529                   int fullscreen = 0;
1530
1531                   if (cw->bd->client.netwm.state.fullscreen)
1532                     fullscreen = 1;
1533                   if (!(((m->fullscreen == -1) && (!fullscreen)) ||
1534                         ((m->fullscreen == 1) && (fullscreen))))
1535                     continue;
1536                }
1537              if (m->modal != 0)
1538                {
1539                   int modal = 0;
1540
1541                   if (cw->bd->client.netwm.state.modal)
1542                     modal = 1;
1543                   if (!(((m->modal == -1) && (!modal)) ||
1544                         ((m->modal == 1) && (modal))))
1545                     continue;
1546                }
1547           }
1548         if (m->shadow_style)
1549           {
1550              snprintf(buf, sizeof(buf), "e/comp/%s",
1551                       m->shadow_style);
1552              ok = e_theme_edje_object_set(cw->shobj, "base/theme/borders",
1553                                           buf);
1554              if (ok) break;
1555           }
1556      }
1557    if (!ok)
1558      {
1559         if (cw->bd && cw->bd->client.e.state.video)
1560           ok = e_theme_edje_object_set(cw->shobj,
1561                                        "base/theme/borders",
1562                                        "e/comp/none");
1563      }
1564    // use different shadow objects/group per window type?
1565    if (!ok)
1566      {
1567         if (_comp_mod->conf->shadow_file)
1568           ok = edje_object_file_set(cw->shobj, _comp_mod->conf->shadow_file,
1569                                     "shadow");
1570      }
1571    if (!ok)
1572      {
1573         if (_comp_mod->conf->shadow_style)
1574           {
1575              snprintf(buf, sizeof(buf), "e/comp/%s",
1576                       _comp_mod->conf->shadow_style);
1577              ok = e_theme_edje_object_set(cw->shobj, "base/theme/borders",
1578                                           buf);
1579           }
1580         if (!ok)
1581           ok = e_theme_edje_object_set(cw->shobj, "base/theme/borders",
1582                                        "e/comp/default");
1583      }
1584    if (!ok) // fallback to local shadow.edj - will go when default theme supports this
1585      {
1586         snprintf(buf, sizeof(buf), "%s/shadow.edj",
1587                  e_module_dir_get(_comp_mod->module));
1588         ok = edje_object_file_set(cw->shobj, buf, "shadow");
1589      }
1590    edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->obj);
1591    if (!_comp_mod->conf->use_shadow
1592        || (cw->bd && cw->bd->client.e.state.video))
1593      {
1594         edje_object_signal_emit(cw->shobj, "e,state,shadow,off", "e");
1595      }
1596    else
1597      {
1598         if (_e_mod_comp_win_do_shadow(cw))
1599           edje_object_signal_emit(cw->shobj, "e,state,shadow,on", "e");
1600         else
1601           edje_object_signal_emit(cw->shobj, "e,state,shadow,off", "e");
1602      }
1603
1604    if (cw->bd)
1605      {
1606         if (cw->bd->focused)
1607           edje_object_signal_emit(cw->shobj, "e,state,focus,on", "e");
1608         if (cw->bd->client.icccm.urgent)
1609           edje_object_signal_emit(cw->shobj, "e,state,urgent,on", "e");
1610      }
1611 }
1612
1613 static void
1614 _e_mod_comp_cb_win_mirror_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1615 {
1616    E_Comp_Win *cw;
1617
1618    if (!(cw = data)) return;
1619    cw->obj_mirror = eina_list_remove(cw->obj_mirror, obj);
1620 }
1621
1622 static Evas_Object *
1623 _e_mod_comp_win_mirror_add(E_Comp_Win *cw)
1624 {
1625    Evas_Object *o;
1626
1627    if (!cw->c) return NULL;
1628
1629    o = evas_object_image_filled_add(cw->c->evas);
1630    evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
1631    cw->obj_mirror = eina_list_append(cw->obj_mirror, o);
1632    evas_object_image_smooth_scale_set(o, _comp_mod->conf->smooth_windows);
1633
1634    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1635                                   _e_mod_comp_cb_win_mirror_del, cw);
1636
1637    if ((cw->pixmap) && (cw->pw > 0) && (cw->ph > 0))
1638      {
1639         unsigned int *pix;
1640         Eina_Bool alpha;
1641         int w, h;
1642
1643         alpha = evas_object_image_alpha_get(cw->obj);
1644         evas_object_image_size_get(cw->obj, &w, &h);
1645
1646         evas_object_image_alpha_set(o, alpha);
1647
1648         if (cw->shaped)
1649           {
1650              pix = evas_object_image_data_get(cw->obj, 0);
1651              evas_object_image_data_set(o, pix);
1652              evas_object_image_size_set(o, w, h);
1653              evas_object_image_data_set(o, pix);
1654              evas_object_image_data_update_add(o, 0, 0, w, h);
1655           }
1656         else
1657           {
1658              if (cw->native)
1659                {
1660                   Evas_Native_Surface ns;
1661
1662                   ns.version = EVAS_NATIVE_SURFACE_VERSION;
1663                   ns.type = EVAS_NATIVE_SURFACE_X11;
1664                   ns.data.x11.visual = cw->vis;
1665                   ns.data.x11.pixmap = cw->pixmap;
1666                   evas_object_image_size_set(o, w, h);
1667                   evas_object_image_native_surface_set(o, &ns);
1668                   evas_object_image_data_update_add(o, 0, 0, w, h);
1669                }
1670              else if (cw->xim)
1671                {
1672                   pix = ecore_x_image_data_get(cw->xim, NULL, NULL, NULL);
1673                   evas_object_image_data_set(o, pix);
1674                   evas_object_image_size_set(o, w, h);
1675                   evas_object_image_data_set(o, pix);
1676                   evas_object_image_data_update_add(o, 0, 0, w, h);
1677                }
1678           }
1679         evas_object_image_size_set(o, w, h);
1680         evas_object_image_data_update_add(o, 0, 0, w, h);
1681      }
1682    evas_object_stack_above(o, cw->shobj);
1683    return o;
1684 }
1685
1686 static E_Comp_Win *
1687 _e_mod_comp_win_add(E_Comp        *c,
1688                     Ecore_X_Window win)
1689 {
1690    Ecore_X_Window_Attributes att;
1691    E_Comp_Win *cw;
1692
1693    cw = calloc(1, sizeof(E_Comp_Win));
1694    if (!cw) return NULL;
1695    cw->win = win;
1696    cw->c = c;
1697    cw->opacity = 255.0;
1698    cw->bd = e_border_find_by_window(cw->win);
1699    if (_comp_mod->conf->grab) ecore_x_grab();
1700    if (cw->bd)
1701      {
1702         eina_hash_add(borders, e_util_winid_str_get(cw->bd->client.win), cw);
1703         cw->dfn = e_object_delfn_add(E_OBJECT(cw->bd), _e_mod_comp_object_del, cw);
1704
1705         // setup on show
1706         // _e_mod_comp_win_sync_setup(cw, cw->bd->client.win);
1707      }
1708    else if ((cw->pop = e_popup_find_by_window(cw->win)))
1709      {
1710         cw->dfn = e_object_delfn_add(E_OBJECT(cw->pop),
1711                                      _e_mod_comp_object_del, cw);
1712         cw->show_ready = 1;
1713      }
1714    else if ((cw->menu = e_menu_find_by_window(cw->win)))
1715      {
1716         cw->dfn = e_object_delfn_add(E_OBJECT(cw->menu),
1717                                      _e_mod_comp_object_del, cw);
1718         cw->show_ready = 1;
1719      }
1720    else
1721      {
1722         char *netwm_title = NULL;
1723
1724         cw->title = ecore_x_icccm_title_get(cw->win);
1725         if (ecore_x_netwm_name_get(cw->win, &netwm_title))
1726           {
1727              if (cw->title) free(cw->title);
1728              cw->title = netwm_title;
1729           }
1730         ecore_x_icccm_name_class_get(cw->win, &cw->name, &cw->clas);
1731         cw->role = ecore_x_icccm_window_role_get(cw->win);
1732         if (!ecore_x_netwm_window_type_get(cw->win, &cw->primary_type))
1733           cw->primary_type = ECORE_X_WINDOW_TYPE_UNKNOWN;
1734         // setup on show
1735         // _e_mod_comp_win_sync_setup(cw, cw->win);
1736      }
1737
1738    if (!cw->counter)
1739      {
1740         // FIXME: config - disable ready timeout for non-counter wins
1741         //        cw->show_ready = 1;
1742      }
1743    // fixme: could use bd/pop/menu for this too
1744    memset((&att), 0, sizeof(Ecore_X_Window_Attributes));
1745    if (!ecore_x_window_attributes_get(cw->win, &att))
1746      {
1747         free(cw);
1748         if (_comp_mod->conf->grab) ecore_x_ungrab();
1749         return NULL;
1750      }
1751    if ((!att.input_only) &&
1752        ((att.depth != 24) && (att.depth != 32)))
1753      {
1754         printf("WARNING: window 0x%x not 24/32bpp -> %ibpp\n", cw->win, att.depth);
1755         cw->invalid = 1;
1756      }
1757    cw->input_only = att.input_only;
1758    cw->override = att.override;
1759    cw->vis = att.visual;
1760    cw->depth = att.depth;
1761    cw->argb = ecore_x_window_argb_get(cw->win);
1762    eina_hash_add(windows, e_util_winid_str_get(cw->win), cw);
1763    cw->inhash = 1;
1764    if ((!cw->input_only) && (!cw->invalid))
1765      {
1766         Ecore_X_Rectangle *rects;
1767         int num;
1768
1769         cw->damage = ecore_x_damage_new
1770             (cw->win, ECORE_X_DAMAGE_REPORT_DELTA_RECTANGLES);
1771         eina_hash_add(damages, e_util_winid_str_get(cw->damage), cw);
1772         cw->shobj = edje_object_add(c->evas);
1773         cw->obj = evas_object_image_filled_add(c->evas);
1774         evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
1775         if (cw->argb) evas_object_image_alpha_set(cw->obj, 1);
1776         else evas_object_image_alpha_set(cw->obj, 0);
1777
1778         if (cw->override && !(att.event_mask.mine & ECORE_X_EVENT_MASK_WINDOW_PROPERTY))
1779           ecore_x_event_mask_set(cw->win, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
1780
1781         _e_mod_comp_win_shadow_setup(cw);
1782
1783         edje_object_signal_callback_add(cw->shobj, "e,action,show,done", "e",
1784                                         _e_mod_comp_show_done, cw);
1785         edje_object_signal_callback_add(cw->shobj, "e,action,hide,done", "e",
1786                                         _e_mod_comp_hide_done, cw);
1787         evas_object_show(cw->obj);
1788         ecore_x_window_shape_events_select(cw->win, 1);
1789         rects = ecore_x_window_shape_rectangles_get(cw->win, &num);
1790         if (rects)
1791           {
1792              int i;
1793
1794              for (i = 0; i < num; i++)
1795                E_RECTS_CLIP_TO_RECT(rects[i].x, rects[i].y,
1796                                     rects[i].width, rects[i].height,
1797                                     0, 0, att.w, att.h);
1798
1799              if (_e_mod_comp_shaped_check(att.w, att.h, rects, num))
1800                cw->shape_changed = 1;
1801
1802              free(rects);
1803           }
1804
1805         if (cw->bd) evas_object_data_set(cw->shobj, "border", cw->bd);
1806         else if (cw->pop)
1807           evas_object_data_set(cw->shobj, "popup", cw->pop);
1808         else if (cw->menu)
1809           evas_object_data_set(cw->shobj, "menu", cw->menu);
1810
1811         evas_object_pass_events_set(cw->obj, 1);
1812
1813         cw->pending_count++;
1814         e_manager_comp_event_src_add_send
1815           (cw->c->man, (E_Manager_Comp_Source *)cw,
1816           _e_mod_comp_cb_pending_after, cw->c);
1817      }
1818    else
1819      {
1820         cw->shobj = evas_object_rectangle_add(c->evas);
1821         evas_object_color_set(cw->shobj, 0, 0, 0, 0);
1822      }
1823    evas_object_pass_events_set(cw->shobj, 1);
1824    evas_object_data_set(cw->shobj, "win",
1825                         (void *)((unsigned long)cw->win));
1826    evas_object_data_set(cw->shobj, "src", cw);
1827
1828    c->wins_invalid = 1;
1829    c->wins = eina_inlist_append(c->wins, EINA_INLIST_GET(cw));
1830    cw->up = e_mod_comp_update_new();
1831    e_mod_comp_update_tile_size_set(cw->up, 32, 32);
1832    // for software:
1833    e_mod_comp_update_policy_set
1834      (cw->up, E_UPDATE_POLICY_HALF_WIDTH_OR_MORE_ROUND_UP_TO_FULL_WIDTH);
1835    if (((!cw->input_only) && (!cw->invalid)) && (cw->override))
1836      {
1837           cw->redirected = 1;
1838           // we redirect all subwindows anyway
1839           // ecore_x_composite_redirect_window(cw->win, ECORE_X_COMPOSITE_UPDATE_MANUAL);
1840           cw->dmg_updates = 0;
1841      }
1842    DBG("  [0x%x] add\n", cw->win);
1843    if (_comp_mod->conf->grab) ecore_x_ungrab();
1844    return cw;
1845 }
1846
1847 static void
1848 _e_mod_comp_win_del(E_Comp_Win *cw)
1849 {
1850    int pending_count;
1851
1852    if (cw->animating)
1853      {
1854         cw->c->animating--;
1855      }
1856    cw->animating = 0;
1857    if ((!cw->input_only) && (!cw->invalid))
1858      {
1859         cw->pending_count++;
1860         e_manager_comp_event_src_del_send
1861           (cw->c->man, (E_Manager_Comp_Source *)cw,
1862           _e_mod_comp_cb_pending_after, cw->c);
1863      }
1864
1865    e_mod_comp_update_free(cw->up);
1866    DBG("  [0x%x] del\n", cw->win);
1867    if (cw->rects)
1868      {
1869         free(cw->rects);
1870         cw->rects = NULL;
1871      }
1872    if (cw->update_timeout)
1873      {
1874         ecore_timer_del(cw->update_timeout);
1875         cw->update_timeout = NULL;
1876      }
1877    if (cw->ready_timeout)
1878      {
1879         ecore_timer_del(cw->ready_timeout);
1880         cw->ready_timeout = NULL;
1881      }
1882    if (cw->dfn)
1883      {
1884         if (cw->bd)
1885           {
1886              eina_hash_del(borders, e_util_winid_str_get(cw->bd->client.win), cw);
1887              e_object_delfn_del(E_OBJECT(cw->bd), cw->dfn);
1888              cw->bd = NULL;
1889           }
1890         else if (cw->pop)
1891           {
1892              e_object_delfn_del(E_OBJECT(cw->pop), cw->dfn);
1893              cw->pop = NULL;
1894           }
1895         else if (cw->menu)
1896           {
1897              e_object_delfn_del(E_OBJECT(cw->menu), cw->dfn);
1898              cw->menu = NULL;
1899           }
1900         cw->dfn = NULL;
1901      }
1902    if (cw->pixmap)
1903      {
1904         ecore_x_pixmap_free(cw->pixmap);
1905         cw->pixmap = 0;
1906         cw->pw = 0;
1907         cw->ph = 0;
1908         ecore_x_e_comp_pixmap_set(cw->win, cw->pixmap);
1909         cw->show_ready = 0; // hmm maybe not needed?
1910      }
1911    if (cw->redirected)
1912      {
1913 // we redirect all subwindows anyway
1914 //        ecore_x_composite_unredirect_window(cw->win, ECORE_X_COMPOSITE_UPDATE_MANUAL);
1915               cw->redirected = 0;
1916               cw->pw = 0;
1917               cw->ph = 0;
1918      }
1919    if (cw->update)
1920      {
1921         cw->update = 0;
1922         cw->c->updates = eina_list_remove(cw->c->updates, cw);
1923      }
1924    if (cw->obj_mirror)
1925      {
1926         Evas_Object *o;
1927         EINA_LIST_FREE(cw->obj_mirror, o)
1928           {
1929              if (cw->xim) evas_object_image_data_set(o, NULL);
1930              evas_object_event_callback_del(o, EVAS_CALLBACK_DEL,
1931                                             _e_mod_comp_cb_win_mirror_del);
1932
1933              evas_object_del(o);
1934           }
1935      }
1936    if (cw->xim)
1937      {
1938         evas_object_image_data_set(cw->obj, NULL);
1939         ecore_x_image_free(cw->xim);
1940         cw->xim = NULL;
1941      }
1942    if (cw->obj)
1943      {
1944         evas_object_del(cw->obj);
1945         cw->obj = NULL;
1946      }
1947    if (cw->shobj)
1948      {
1949         evas_object_del(cw->shobj);
1950         cw->shobj = NULL;
1951      }
1952    if (cw->inhash)
1953      eina_hash_del(windows, e_util_winid_str_get(cw->win), cw);
1954    if (cw->damage)
1955      {
1956         Ecore_X_Region parts;
1957
1958         eina_hash_del(damages, e_util_winid_str_get(cw->damage), cw);
1959         parts = ecore_x_region_new(NULL, 0);
1960         ecore_x_damage_subtract(cw->damage, 0, parts);
1961         ecore_x_region_free(parts);
1962         ecore_x_damage_free(cw->damage);
1963         cw->damage = 0;
1964      }
1965    if (cw->title) free(cw->title);
1966    if (cw->name) free(cw->name);
1967    if (cw->clas) free(cw->clas);
1968    if (cw->role) free(cw->role);
1969    cw->c->wins_invalid = 1;
1970    cw->c->wins = eina_inlist_remove(cw->c->wins, EINA_INLIST_GET(cw));
1971    pending_count = cw->pending_count;
1972    memset(cw, 0, sizeof(E_Comp_Win));
1973    cw->pending_count = pending_count;
1974    cw->delete_pending = 1;
1975    if (cw->pending_count > 0) return;
1976    free(cw);
1977 }
1978
1979 static void
1980 _e_mod_comp_win_show(E_Comp_Win *cw)
1981 {
1982    Eina_List *l;
1983    Evas_Object *o;
1984
1985    if (cw->visible) return;
1986    cw->visible = 1;
1987    DBG("  [0x%x] sho ++ [redir=%i, pm=%x, dmg_up=%i]\n",
1988        cw->win, cw->redirected, cw->pixmap, cw->dmg_updates);
1989    _e_mod_comp_win_configure(cw, cw->hidden.x, cw->hidden.y, cw->w, cw->h, cw->border);
1990    if ((cw->input_only) || (cw->invalid)) return;
1991
1992    cw->show_anim = EINA_FALSE;
1993    
1994 // setup on show
1995    if (cw->bd)
1996      _e_mod_comp_win_sync_setup(cw, cw->bd->client.win);
1997    else
1998      _e_mod_comp_win_sync_setup(cw, cw->win);
1999
2000    if (cw->real_hid)
2001      {
2002         DBG("  [0x%x] real hid - fix\n", cw->win);
2003         cw->real_hid = 0;
2004         if (cw->native)
2005           {
2006              evas_object_image_native_surface_set(cw->obj, NULL);
2007              cw->native = 0;
2008              EINA_LIST_FOREACH(cw->obj_mirror, l, o)
2009                {
2010                   evas_object_image_native_surface_set(o, NULL);
2011                }
2012           }
2013         if (cw->pixmap)
2014           {
2015              ecore_x_pixmap_free(cw->pixmap);
2016              cw->pixmap = 0;
2017              cw->pw = 0;
2018              cw->ph = 0;
2019              ecore_x_e_comp_pixmap_set(cw->win, cw->pixmap);
2020           }
2021         if (cw->xim)
2022           {
2023              evas_object_image_size_set(cw->obj, 1, 1);
2024              evas_object_image_data_set(cw->obj, NULL);
2025              ecore_x_image_free(cw->xim);
2026              cw->xim = NULL;
2027              EINA_LIST_FOREACH(cw->obj_mirror, l, o)
2028                {
2029                   evas_object_image_size_set(o, 1, 1);
2030                   evas_object_image_data_set(o, NULL);
2031                }
2032           }
2033         if (cw->redirected)
2034           {
2035              cw->redirected = 0;
2036              cw->pw = 0;
2037              cw->ph = 0;
2038           }
2039         if (cw->pop)
2040           cw->dmg_updates = 1;
2041         else
2042           cw->dmg_updates = 0;
2043      }
2044    else
2045      cw->dmg_updates = 1;
2046    if ((!cw->redirected) || (!cw->pixmap))
2047      {
2048 // we redirect all subwindows anyway
2049 //        ecore_x_composite_redirect_window(cw->win, ECORE_X_COMPOSITE_UPDATE_MANUAL);
2050               cw->pixmap = ecore_x_composite_name_window_pixmap_get(cw->win);
2051               if (cw->pixmap)
2052                 {
2053                    ecore_x_pixmap_geometry_get(cw->pixmap, NULL, NULL, &(cw->pw), &(cw->ph));
2054                    _e_mod_comp_win_ready_timeout_setup(cw);
2055                 }
2056               else
2057                 {
2058                    cw->pw = 0;
2059                    cw->ph = 0;
2060                 }
2061               if ((cw->pw <= 0) || (cw->ph <= 0))
2062                 {
2063                    if (cw->pixmap)
2064                      {
2065                         ecore_x_pixmap_free(cw->pixmap);
2066                         cw->pixmap = 0;
2067                      }
2068 //             cw->show_ready = 0; // hmm maybe not needed?
2069                 }
2070               cw->redirected = 1;
2071               DBG("  [0x%x] up resize %ix%i\n", cw->win, cw->pw, cw->ph);
2072               e_mod_comp_update_resize(cw->up, cw->pw, cw->ph);
2073               e_mod_comp_update_add(cw->up, 0, 0, cw->pw, cw->ph);
2074               evas_object_image_size_set(cw->obj, cw->pw, cw->ph);
2075               EINA_LIST_FOREACH(cw->obj_mirror, l, o)
2076                 {
2077                    evas_object_image_size_set(o, cw->pw, cw->ph);
2078                 }
2079               ecore_x_e_comp_pixmap_set(cw->win, cw->pixmap);
2080      }
2081    if ((cw->dmg_updates >= 1) && (cw->show_ready))
2082      {
2083         cw->defer_hide = 0;
2084         if (!cw->hidden_override) _e_mod_comp_child_show(cw);
2085         edje_object_signal_emit(cw->shobj, "e,state,visible,on", "e");
2086         if (!cw->animating)
2087           {
2088              cw->c->animating++;
2089           }
2090         cw->animating = 1;
2091         _e_mod_comp_win_render_queue(cw);
2092
2093         cw->pending_count++;
2094         e_manager_comp_event_src_visibility_send
2095           (cw->c->man, (E_Manager_Comp_Source *)cw,
2096           _e_mod_comp_cb_pending_after, cw->c);
2097      }
2098    _e_mod_comp_win_render_queue(cw);
2099 }
2100
2101 static void
2102 _e_mod_comp_win_real_hide(E_Comp_Win *cw)
2103 {
2104    if (cw->bd)
2105      {
2106         _e_mod_comp_win_hide(cw);
2107         return;
2108      }
2109    cw->real_hid = 1;
2110    _e_mod_comp_win_hide(cw);
2111 }
2112
2113 static void
2114 _e_mod_comp_win_hide(E_Comp_Win *cw)
2115 {
2116    Eina_List *l;
2117    Evas_Object *o;
2118
2119    if ((!cw->visible) && (!cw->defer_hide)) return;
2120    cw->visible = 0;
2121    if ((cw->input_only) || (cw->invalid)) return;
2122    DBG("  [0x%x] hid --\n", cw->win);
2123    if (!cw->force)
2124      {
2125         cw->defer_hide = 1;
2126         edje_object_signal_emit(cw->shobj, "e,state,visible,off", "e");
2127         if (!cw->animating)
2128           {
2129              cw->c->animating++;
2130           }
2131         cw->animating = 1;
2132         _e_mod_comp_win_render_queue(cw);
2133
2134         cw->pending_count++;
2135         e_manager_comp_event_src_visibility_send
2136           (cw->c->man, (E_Manager_Comp_Source *)cw,
2137           _e_mod_comp_cb_pending_after, cw->c);
2138         return;
2139      }
2140    cw->defer_hide = 0;
2141    cw->force = 0;
2142    _e_mod_comp_child_hide(cw);
2143
2144    if (cw->update_timeout)
2145      {
2146         ecore_timer_del(cw->update_timeout);
2147         cw->update_timeout = NULL;
2148      }
2149    if (_comp_mod->conf->keep_unmapped)
2150      {
2151         if (_comp_mod->conf->send_flush)
2152           {
2153              if (cw->bd) ecore_x_e_comp_flush_send(cw->bd->client.win);
2154              else ecore_x_e_comp_flush_send(cw->win);
2155           }
2156         if (_comp_mod->conf->send_dump)
2157           {
2158              if (cw->bd) ecore_x_e_comp_dump_send(cw->bd->client.win);
2159              else ecore_x_e_comp_dump_send(cw->win);
2160           }
2161         return;
2162      }
2163    if (cw->ready_timeout)
2164      {
2165         ecore_timer_del(cw->ready_timeout);
2166         cw->ready_timeout = NULL;
2167      }
2168
2169    if (cw->native)
2170      {
2171         evas_object_image_native_surface_set(cw->obj, NULL);
2172         cw->native = 0;
2173         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
2174           {
2175              evas_object_image_native_surface_set(o, NULL);
2176           }
2177      }
2178    if (cw->pixmap)
2179      {
2180         ecore_x_pixmap_free(cw->pixmap);
2181         cw->pixmap = 0;
2182         cw->pw = 0;
2183         cw->ph = 0;
2184         ecore_x_e_comp_pixmap_set(cw->win, cw->pixmap);
2185 //        cw->show_ready = 0; // hmm maybe not needed?
2186      }
2187    if (cw->xim)
2188      {
2189         evas_object_image_size_set(cw->obj, 1, 1);
2190         evas_object_image_data_set(cw->obj, NULL);
2191         ecore_x_image_free(cw->xim);
2192         cw->xim = NULL;
2193         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
2194           {
2195              evas_object_image_size_set(o, 1, 1);
2196              evas_object_image_data_set(o, NULL);
2197           }
2198      }
2199    if (cw->redirected)
2200      {
2201 // we redirect all subwindows anyway
2202 //        ecore_x_composite_unredirect_window(cw->win, ECORE_X_COMPOSITE_UPDATE_MANUAL);
2203               cw->redirected = 0;
2204               cw->pw = 0;
2205               cw->ph = 0;
2206      }
2207    _e_mod_comp_win_render_queue(cw);
2208    if (_comp_mod->conf->send_flush)
2209      {
2210         if (cw->bd) ecore_x_e_comp_flush_send(cw->bd->client.win);
2211         else ecore_x_e_comp_flush_send(cw->win);
2212      }
2213    if (_comp_mod->conf->send_dump)
2214      {
2215         if (cw->bd) ecore_x_e_comp_dump_send(cw->bd->client.win);
2216         else ecore_x_e_comp_dump_send(cw->win);
2217      }
2218 }
2219
2220 static void
2221 _e_mod_comp_win_raise_above(E_Comp_Win *cw,
2222                             E_Comp_Win *cw2)
2223 {
2224    DBG("  [0x%x] abv [0x%x]\n", cw->win, cw2->win);
2225    cw->c->wins_invalid = 1;
2226    cw->c->wins = eina_inlist_remove(cw->c->wins, EINA_INLIST_GET(cw));
2227    cw->c->wins = eina_inlist_append_relative(cw->c->wins,
2228                                              EINA_INLIST_GET(cw),
2229                                              EINA_INLIST_GET(cw2));
2230    evas_object_stack_above(cw->shobj, cw2->shobj);
2231    if (cw->bd)
2232      {
2233         Eina_List *l;
2234         E_Border *tmp;
2235
2236         EINA_LIST_FOREACH(cw->bd->client.e.state.video_child, l, tmp)
2237           {
2238              E_Comp_Win *tcw;
2239
2240              tcw = eina_hash_find(borders, e_util_winid_str_get(tmp->client.win));
2241              if (!tcw) continue ;
2242
2243              evas_object_stack_below(tcw->shobj, cw->shobj);
2244           }
2245      }
2246
2247    _e_mod_comp_win_render_queue(cw);
2248    cw->pending_count++;
2249    e_manager_comp_event_src_config_send
2250      (cw->c->man, (E_Manager_Comp_Source *)cw,
2251      _e_mod_comp_cb_pending_after, cw->c);
2252 }
2253
2254 static void
2255 _e_mod_comp_win_raise(E_Comp_Win *cw)
2256 {
2257    DBG("  [0x%x] rai\n", cw->win);
2258    cw->c->wins_invalid = 1;
2259    cw->c->wins = eina_inlist_remove(cw->c->wins, EINA_INLIST_GET(cw));
2260    cw->c->wins = eina_inlist_append(cw->c->wins, EINA_INLIST_GET(cw));
2261    evas_object_raise(cw->shobj);
2262    if (cw->bd)
2263      {
2264         Eina_List *l;
2265         E_Border *tmp;
2266
2267         EINA_LIST_FOREACH(cw->bd->client.e.state.video_child, l, tmp)
2268           {
2269              E_Comp_Win *tcw;
2270
2271              tcw = eina_hash_find(borders, e_util_winid_str_get(tmp->client.win));
2272              if (!tcw) continue ;
2273
2274              evas_object_stack_below(tcw->shobj, cw->shobj);
2275           }
2276      }
2277
2278    _e_mod_comp_win_render_queue(cw);
2279    cw->pending_count++;
2280    e_manager_comp_event_src_config_send
2281      (cw->c->man, (E_Manager_Comp_Source *)cw,
2282      _e_mod_comp_cb_pending_after, cw->c);
2283 }
2284
2285 static void
2286 _e_mod_comp_win_lower(E_Comp_Win *cw)
2287 {
2288    DBG("  [0x%x] low\n", cw->win);
2289    cw->c->wins_invalid = 1;
2290    cw->c->wins = eina_inlist_remove(cw->c->wins, EINA_INLIST_GET(cw));
2291    cw->c->wins = eina_inlist_prepend(cw->c->wins, EINA_INLIST_GET(cw));
2292    evas_object_lower(cw->shobj);
2293    if (cw->bd)
2294      {
2295         Eina_List *l;
2296         E_Border *tmp;
2297
2298         EINA_LIST_FOREACH(cw->bd->client.e.state.video_child, l, tmp)
2299           {
2300              E_Comp_Win *tcw;
2301
2302              tcw = eina_hash_find(borders, e_util_winid_str_get(tmp->client.win));
2303              if (!tcw) continue ;
2304
2305              evas_object_stack_below(tcw->shobj, cw->shobj);
2306           }
2307      }
2308
2309    _e_mod_comp_win_render_queue(cw);
2310    cw->pending_count++;
2311    e_manager_comp_event_src_config_send
2312      (cw->c->man, (E_Manager_Comp_Source *)cw,
2313      _e_mod_comp_cb_pending_after, cw->c);
2314 }
2315
2316 static void
2317 _e_mod_comp_win_configure(E_Comp_Win *cw,
2318                           int         x,
2319                           int         y,
2320                           int         w,
2321                           int         h,
2322                           int         border)
2323 {
2324    if (!cw->visible)
2325      {
2326         cw->hidden.x = x;
2327         cw->hidden.y = y;
2328         cw->border = border;
2329      }
2330    else
2331      {
2332         if (!((x == cw->x) && (y == cw->y)))
2333           {
2334              DBG("  [0x%x] mov %4i %4i\n", cw->win, x, y);
2335              cw->x = x;
2336              cw->y = y;
2337              evas_object_move(cw->shobj, cw->x, cw->y);
2338           }
2339         cw->hidden.x = x;
2340         cw->hidden.y = y;
2341      }
2342    cw->hidden.w = w;
2343    cw->hidden.h = h;
2344    if (cw->counter)
2345      {
2346         if (!((w == cw->w) && (h == cw->h)))
2347           {
2348 #if 1             
2349              cw->w = w;
2350              cw->h = h;
2351              cw->needpix = 1;
2352              // was cw->w / cw->h
2353              evas_object_resize(cw->shobj, cw->pw, cw->ph);
2354              _e_mod_comp_win_damage(cw, 0, 0, cw->w, cw->h, 0);
2355 #else             
2356              if (cw->bd)
2357                {
2358                   if ((cw->bd->shading) || (cw->bd->shaded))
2359                     {
2360                        cw->needpix = 1;
2361                        // was cw->w / cw->h
2362                        evas_object_resize(cw->shobj, cw->pw, cw->ph);
2363                        _e_mod_comp_win_damage(cw, 0, 0, cw->w, cw->h, 0);
2364                     }
2365                   else
2366                      cw->update = 0;
2367                }
2368              else
2369                {
2370                   cw->update = 0;
2371 //                  if (cw->ready_timeout) ecore_timer_del(cw->ready_timeout);
2372 //                  cw->ready_timeout = ecore_timer_add
2373 //                     (_comp_mod->conf->first_draw_delay, 
2374 //                         _e_mod_comp_cb_win_show_ready_timeout, cw);
2375                }
2376 #endif             
2377           }
2378         if (cw->border != border)
2379           {
2380              cw->border = border;
2381              cw->needpix = 1;
2382              // was cw->w / cw->h
2383              evas_object_resize(cw->shobj, cw->pw, cw->ph);
2384              _e_mod_comp_win_damage(cw, 0, 0, cw->w, cw->h, 0);
2385           }
2386         if ((cw->input_only) || (cw->invalid)) return;
2387      }
2388    else
2389      {
2390         if (!((w == cw->w) && (h == cw->h)))
2391           {
2392              DBG("  [0x%x] rsz %4ix%4i\n", cw->win, w, h);
2393              cw->w = w;
2394              cw->h = h;
2395              cw->needpix = 1;
2396              // was cw->w / cw->h
2397              evas_object_resize(cw->shobj, cw->pw, cw->ph);
2398              _e_mod_comp_win_damage(cw, 0, 0, cw->w, cw->h, 0);
2399           }
2400         if (cw->border != border)
2401           {
2402              cw->border = border;
2403              cw->needpix = 1;
2404              evas_object_resize(cw->shobj, cw->pw, cw->ph);
2405              _e_mod_comp_win_damage(cw, 0, 0, cw->w, cw->h, 0);
2406           }
2407         if ((cw->input_only) || (cw->invalid)) return;
2408         _e_mod_comp_win_render_queue(cw);
2409      }
2410    // add pending manager comp event count to match below config send
2411    cw->pending_count++;
2412    e_manager_comp_event_src_config_send(cw->c->man,
2413                                         (E_Manager_Comp_Source *)cw,
2414                                         _e_mod_comp_cb_pending_after, cw->c);
2415 }
2416
2417 static void
2418 _e_mod_comp_win_damage(E_Comp_Win *cw,
2419                        int         x,
2420                        int         y,
2421                        int         w,
2422                        int         h,
2423                        Eina_Bool   dmg)
2424 {
2425    if ((cw->input_only) || (cw->invalid)) return;
2426    DBG("  [0x%x] dmg [%x] %4i %4i %4ix%4i\n", cw->win, cw->damage, x, y, w, h);
2427    if ((dmg) && (cw->damage))
2428      {
2429         Ecore_X_Region parts;
2430
2431         parts = ecore_x_region_new(NULL, 0);
2432         ecore_x_damage_subtract(cw->damage, 0, parts);
2433         ecore_x_region_free(parts);
2434         cw->dmg_updates++;
2435      }
2436    e_mod_comp_update_add(cw->up, x, y, w, h);
2437    if (dmg)
2438      {
2439         if (cw->counter)
2440           {
2441              if (!cw->update_timeout)
2442                cw->update_timeout = ecore_timer_add
2443                    (ecore_animator_frametime_get() * 2,
2444                    _e_mod_comp_win_damage_timeout, cw);
2445              return;
2446           }
2447      }
2448    if (!cw->update)
2449      {
2450         cw->update = 1;
2451         cw->c->updates = eina_list_append(cw->c->updates, cw);
2452      }
2453    _e_mod_comp_win_render_queue(cw);
2454 }
2455
2456 static void
2457 _e_mod_comp_win_reshape(E_Comp_Win *cw)
2458 {
2459    if (cw->shape_changed) return;
2460    cw->shape_changed = 1;
2461    if (!cw->update)
2462      {
2463         cw->update = 1;
2464         cw->c->updates = eina_list_append(cw->c->updates, cw);
2465      }
2466    e_mod_comp_update_add(cw->up, 0, 0, cw->w, cw->h);
2467    _e_mod_comp_win_render_queue(cw);
2468 }
2469
2470 //////////////////////////////////////////////////////////////////////////
2471
2472 static Eina_Bool
2473 _e_mod_comp_create(void *data __UNUSED__,
2474                    int type   __UNUSED__,
2475                    void      *event)
2476 {
2477    Ecore_X_Event_Window_Create *ev = event;
2478    E_Comp_Win *cw;
2479    E_Comp *c = _e_mod_comp_find(ev->parent);
2480    if (!c) return ECORE_CALLBACK_PASS_ON;
2481    if (_e_mod_comp_win_find(ev->win)) return ECORE_CALLBACK_PASS_ON;
2482    if (c->win == ev->win) return ECORE_CALLBACK_PASS_ON;
2483    if (c->ee_win == ev->win) return ECORE_CALLBACK_PASS_ON;
2484    cw = _e_mod_comp_win_add(c, ev->win);
2485    if (cw) _e_mod_comp_win_configure(cw, ev->x, ev->y, ev->w, ev->h, ev->border);
2486    return ECORE_CALLBACK_PASS_ON;
2487 }
2488
2489 static Eina_Bool
2490 _e_mod_comp_destroy(void *data __UNUSED__,
2491                     int type   __UNUSED__,
2492                     void      *event)
2493 {
2494    Ecore_X_Event_Window_Destroy *ev = event;
2495    E_Comp_Win *cw = _e_mod_comp_win_find(ev->win);
2496    if (!cw) return ECORE_CALLBACK_PASS_ON;
2497    if (cw->animating) cw->delete_me = 1;
2498    else _e_mod_comp_win_del(cw);
2499    return ECORE_CALLBACK_PASS_ON;
2500 }
2501
2502 static Eina_Bool
2503 _e_mod_comp_show(void *data __UNUSED__,
2504                  int type   __UNUSED__,
2505                  void      *event)
2506 {
2507    Ecore_X_Event_Window_Show *ev = event;
2508    E_Comp_Win *cw = _e_mod_comp_win_find(ev->win);
2509    if (!cw) return ECORE_CALLBACK_PASS_ON;
2510    if (cw->visible) return ECORE_CALLBACK_PASS_ON;
2511    _e_mod_comp_win_show(cw);
2512    return ECORE_CALLBACK_PASS_ON;
2513 }
2514
2515 static Eina_Bool
2516 _e_mod_comp_hide(void *data __UNUSED__,
2517                  int type   __UNUSED__,
2518                  void      *event)
2519 {
2520    Ecore_X_Event_Window_Hide *ev = event;
2521    E_Comp_Win *cw = _e_mod_comp_win_find(ev->win);
2522    if (!cw) return ECORE_CALLBACK_PASS_ON;
2523    if (!cw->visible) return ECORE_CALLBACK_PASS_ON;
2524    _e_mod_comp_win_real_hide(cw);
2525    return ECORE_CALLBACK_PASS_ON;
2526 }
2527
2528 static Eina_Bool
2529 _e_mod_comp_reparent(void *data __UNUSED__,
2530                      int type   __UNUSED__,
2531                      void      *event)
2532 {
2533    Ecore_X_Event_Window_Reparent *ev = event;
2534    E_Comp_Win *cw = _e_mod_comp_win_find(ev->win);
2535    if (!cw) return ECORE_CALLBACK_PASS_ON;
2536    DBG("== repar [0x%x] to [0x%x]\n", ev->win, ev->parent);
2537    if (ev->parent != cw->c->man->root)
2538      _e_mod_comp_win_del(cw);
2539    return ECORE_CALLBACK_PASS_ON;
2540 }
2541
2542 static Eina_Bool
2543 _e_mod_comp_configure(void *data __UNUSED__,
2544                       int type   __UNUSED__,
2545                       void      *event)
2546 {
2547    Ecore_X_Event_Window_Configure *ev = event;
2548    E_Comp_Win *cw = _e_mod_comp_win_find(ev->win);
2549    if (!cw) return ECORE_CALLBACK_PASS_ON;
2550
2551    if (ev->abovewin == 0)
2552      {
2553         if (EINA_INLIST_GET(cw)->prev) _e_mod_comp_win_lower(cw);
2554      }
2555    else
2556      {
2557         E_Comp_Win *cw2 = _e_mod_comp_win_find(ev->abovewin);
2558
2559         if (cw2)
2560           {
2561              E_Comp_Win *cw3 = (E_Comp_Win *)(EINA_INLIST_GET(cw)->prev);
2562
2563              if (cw3 != cw2) _e_mod_comp_win_raise_above(cw, cw2);
2564           }
2565      }
2566
2567    if (!((cw->x == ev->x) && (cw->y == ev->y) &&
2568          (cw->w == ev->w) && (cw->h == ev->h) &&
2569          (cw->border == ev->border)))
2570      {
2571         _e_mod_comp_win_configure(cw, ev->x, ev->y, ev->w, ev->h, ev->border);
2572      }
2573    return ECORE_CALLBACK_PASS_ON;
2574 }
2575
2576 static Eina_Bool
2577 _e_mod_comp_stack(void *data __UNUSED__,
2578                   int type   __UNUSED__,
2579                   void      *event)
2580 {
2581    Ecore_X_Event_Window_Stack *ev = event;
2582    E_Comp_Win *cw = _e_mod_comp_win_find(ev->win);
2583    if (!cw) return ECORE_CALLBACK_PASS_ON;
2584    if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE) _e_mod_comp_win_raise(cw);
2585    else _e_mod_comp_win_lower(cw);
2586    return ECORE_CALLBACK_PASS_ON;
2587 }
2588
2589 static void
2590 _e_mod_comp_win_opacity_set(E_Comp_Win *cw)
2591 {
2592    unsigned int val;
2593
2594    if (ecore_x_window_prop_card32_get(cw->win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, &val, 1) > 0)
2595      {
2596         cw->opacity = (val >> 24);
2597         evas_object_color_set(cw->shobj, cw->opacity, cw->opacity, cw->opacity, cw->opacity);
2598      }
2599 }
2600
2601 static Eina_Bool
2602 _e_mod_comp_property(void *data  __UNUSED__,
2603                      int type    __UNUSED__,
2604                      void *event __UNUSED__)
2605 {
2606    Ecore_X_Event_Window_Property *ev = event;
2607
2608    if (ev->atom == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY)
2609      {
2610         E_Comp_Win *cw = _e_mod_comp_win_find(ev->win);
2611         if (!cw) return ECORE_CALLBACK_PASS_ON;
2612         _e_mod_comp_win_opacity_set(cw);
2613      }
2614    return ECORE_CALLBACK_PASS_ON;
2615 }
2616
2617 static Eina_Bool
2618 _e_mod_comp_message(void *data __UNUSED__,
2619                     int type   __UNUSED__,
2620                     void      *event)
2621 {
2622    Ecore_X_Event_Client_Message *ev = event;
2623    E_Comp_Win *cw = NULL;
2624    int version, w = 0, h = 0;
2625    Eina_Bool force = 0;
2626    
2627    if (ev->message_type == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY)
2628      {
2629         E_Comp_Win *cw = _e_mod_comp_win_find(ev->win);
2630         if (!cw) return ECORE_CALLBACK_PASS_ON;
2631         _e_mod_comp_win_opacity_set(cw);
2632         return ECORE_CALLBACK_PASS_ON;
2633      }
2634
2635    if ((ev->message_type != ECORE_X_ATOM_E_COMP_SYNC_DRAW_DONE) ||
2636        (ev->format != 32)) return ECORE_CALLBACK_PASS_ON;
2637    version = ev->data.l[1];
2638    cw = _e_mod_comp_border_client_find(ev->data.l[0]);
2639    if (cw)
2640      {
2641         if (!cw->bd) return ECORE_CALLBACK_PASS_ON;
2642         if (ev->data.l[0] != (int)cw->bd->client.win) return ECORE_CALLBACK_PASS_ON;
2643      }
2644    else
2645      {
2646         cw = _e_mod_comp_win_find(ev->data.l[0]);
2647         if (!cw) return ECORE_CALLBACK_PASS_ON;
2648         if (ev->data.l[0] != (int)cw->win) return ECORE_CALLBACK_PASS_ON;
2649      }
2650    if (version == 1) // v 0 was first, v1 added size params
2651      {
2652         w = ev->data.l[2];
2653         h = ev->data.l[3];
2654         if (cw->bd)
2655           {
2656              int clw, clh;
2657              
2658              if ((cw->bd->shading) || (cw->bd->shaded)) force = 1;
2659              clw = cw->hidden.w - 
2660                 cw->bd->client_inset.l - 
2661                 cw->bd->client_inset.r;
2662              clh = cw->hidden.h - 
2663                 cw->bd->client_inset.t - 
2664                 cw->bd->client_inset.b;
2665              DBG("  [0x%x] sync draw done @%4ix%4i, bd %4ix%4i\n", cw->win, 
2666                  w, h, cw->bd->client.w, cw->bd->client.h);
2667              if ((w != clw) ||  (h != clh))
2668                {
2669                   cw->misses++;
2670                   if (cw->misses > 1)
2671                     {
2672                        cw->misses = 0;
2673                        force = 1;
2674                     }
2675                   else return ECORE_CALLBACK_PASS_ON;
2676                }
2677              cw->misses = 0;
2678           }
2679         else
2680           {
2681              DBG("  [0x%x] sync draw done @%4ix%4i, cw %4ix%4i\n", cw->win, w, h, cw->hidden.w, cw->hidden.h);
2682              if ((w != cw->hidden.w) || (h != cw->hidden.h))
2683                {
2684                   if (cw->misses > 1)
2685                     {
2686                        cw->misses = 0;
2687                        force = 1;
2688                     }
2689                   else return ECORE_CALLBACK_PASS_ON;
2690                }
2691              cw->misses = 0;
2692           }
2693      }
2694    DBG("  [0x%x] sync draw done %4ix%4i\n", cw->win, cw->w, cw->h);
2695 //   if (cw->bd)
2696    {
2697       if (cw->counter)
2698         {
2699            DBG("  [0x%x] have counter\n", cw->win);
2700            cw->show_ready = 1;
2701            if (!cw->update)
2702              {
2703                 DBG("  [0x%x] set update\n", cw->win);
2704                 if (cw->update_timeout)
2705                   {
2706                      DBG("  [0x%x] del timeout\n", cw->win);
2707                      ecore_timer_del(cw->update_timeout);
2708                      cw->update_timeout = NULL;
2709                   }
2710                 cw->update = 1;
2711                 cw->c->updates = eina_list_append(cw->c->updates, cw);
2712              }
2713            if ((cw->w != cw->hidden.w) ||
2714                (cw->h != cw->hidden.h) ||
2715                (force))
2716              {
2717                 DBG("  [0x%x] rsz done msg %4ix%4i\n", cw->win, cw->hidden.w, cw->hidden.h);
2718                 cw->w = cw->hidden.w;
2719                 cw->h = cw->hidden.h;
2720                 cw->needpix = 1;
2721                 // was cw->w / cw->h
2722                 evas_object_resize(cw->shobj, cw->pw, cw->ph);
2723                 _e_mod_comp_win_damage(cw, 0, 0, cw->w, cw->h, 0);
2724              }
2725            cw->drawme = 1;
2726            _e_mod_comp_win_render_queue(cw);
2727         }
2728    }
2729    return ECORE_CALLBACK_PASS_ON;
2730 }
2731
2732 static Eina_Bool
2733 _e_mod_comp_shape(void *data __UNUSED__,
2734                   int type   __UNUSED__,
2735                   void      *event)
2736 {
2737    Ecore_X_Event_Window_Shape *ev = event;
2738    E_Comp_Win *cw = _e_mod_comp_win_find(ev->win);
2739    if (!cw) return ECORE_CALLBACK_PASS_ON;
2740    if (ev->type != ECORE_X_SHAPE_BOUNDING) return ECORE_CALLBACK_PASS_ON;
2741    _e_mod_comp_win_reshape(cw);
2742    return ECORE_CALLBACK_PASS_ON;
2743 }
2744
2745 static Eina_Bool
2746 _e_mod_comp_damage(void *data __UNUSED__,
2747                    int type   __UNUSED__,
2748                    void      *event)
2749 {
2750    Ecore_X_Event_Damage *ev = event;
2751    E_Comp_Win *cw = _e_mod_comp_win_damage_find(ev->damage);
2752    if (!cw) return ECORE_CALLBACK_PASS_ON;
2753    _e_mod_comp_win_damage(cw,
2754                           ev->area.x, ev->area.y,
2755                           ev->area.width, ev->area.height, 1);
2756    return ECORE_CALLBACK_PASS_ON;
2757 }
2758
2759 static Eina_Bool
2760 _e_mod_comp_damage_win(void *data __UNUSED__,
2761                        int type   __UNUSED__,
2762                        void      *event)
2763 {
2764    Ecore_X_Event_Window_Damage *ev = event;
2765    Eina_List *l;
2766    E_Comp *c;
2767
2768    // fixme: use hash if compositors list > 4
2769    EINA_LIST_FOREACH(compositors, l, c)
2770      {
2771         if (ev->win == c->ee_win)
2772           {
2773              // expose on comp win - init win or some other bypass win did it
2774              DBG("JOB4...\n");
2775              _e_mod_comp_render_queue(c);
2776              break;
2777           }
2778      }
2779    return ECORE_CALLBACK_PASS_ON;
2780 }
2781
2782 static Eina_Bool
2783 _e_mod_comp_randr(void *data       __UNUSED__,
2784                   int type         __UNUSED__,
2785                   __UNUSED__ void *event)
2786 {
2787    Eina_List *l;
2788    E_Comp *c;
2789
2790    EINA_LIST_FOREACH(compositors, l, c)
2791      {
2792         ecore_evas_resize(c->ee, c->man->w, c->man->h);
2793      }
2794    return ECORE_CALLBACK_PASS_ON;
2795 }
2796
2797 static Eina_Bool
2798 _e_mod_comp_bd_add(void *data __UNUSED__,
2799                    int type   __UNUSED__,
2800                    void      *event)
2801 {
2802    E_Event_Border_Add *ev = event;
2803    E_Comp_Win *cw = _e_mod_comp_win_find(ev->border->win);
2804    if (!cw) return ECORE_CALLBACK_PASS_ON;
2805    // fimxe: add/enable compositing here not in show event for borders
2806    return ECORE_CALLBACK_PASS_ON;
2807 }
2808
2809 static Eina_Bool
2810 _e_mod_comp_bd_del(void *data __UNUSED__,
2811                    int type   __UNUSED__,
2812                    void      *event)
2813 {
2814    E_Event_Border_Remove *ev = event;
2815    E_Comp_Win *cw = _e_mod_comp_win_find(ev->border->win);
2816    if (!cw) return ECORE_CALLBACK_PASS_ON;
2817    if (cw->bd == ev->border) _e_mod_comp_object_del(cw, ev->border);
2818    return ECORE_CALLBACK_PASS_ON;
2819 }
2820
2821 static Eina_Bool
2822 _e_mod_comp_bd_show(void *data __UNUSED__,
2823                     int type   __UNUSED__,
2824                     void      *event)
2825 {
2826    E_Event_Border_Show *ev = event;
2827    E_Comp_Win *cw = _e_mod_comp_win_find(ev->border->win);
2828    if (!cw) return ECORE_CALLBACK_PASS_ON;
2829    if (cw->visible) return ECORE_CALLBACK_PASS_ON;
2830    _e_mod_comp_win_show(cw);
2831    return ECORE_CALLBACK_PASS_ON;
2832 }
2833
2834 static Eina_Bool
2835 _e_mod_comp_bd_hide(void *data __UNUSED__,
2836                     int type   __UNUSED__,
2837                     void      *event)
2838 {
2839    E_Event_Border_Hide *ev = event;
2840    E_Comp_Win *cw = _e_mod_comp_win_find(ev->border->win);
2841    if (!cw) return ECORE_CALLBACK_PASS_ON;
2842    if (!cw->visible) return ECORE_CALLBACK_PASS_ON;
2843    _e_mod_comp_win_hide(cw);
2844    return ECORE_CALLBACK_PASS_ON;
2845 }
2846
2847 static Eina_Bool
2848 _e_mod_comp_bd_move(void *data __UNUSED__,
2849                     int type   __UNUSED__,
2850                     void      *event)
2851 {
2852    E_Event_Border_Move *ev = event;
2853    E_Comp_Win *cw = _e_mod_comp_win_find(ev->border->win);
2854    if (!cw) return ECORE_CALLBACK_PASS_ON;
2855    // fimxe: do move here for composited bd
2856    return ECORE_CALLBACK_PASS_ON;
2857 }
2858
2859 static Eina_Bool
2860 _e_mod_comp_bd_resize(void *data __UNUSED__,
2861                       int type   __UNUSED__,
2862                       void      *event)
2863 {
2864    E_Event_Border_Resize *ev = event;
2865    E_Comp_Win *cw = _e_mod_comp_win_find(ev->border->win);
2866    if (!cw) return ECORE_CALLBACK_PASS_ON;
2867    // fimxe: do resize here instead of conf notify
2868    return ECORE_CALLBACK_PASS_ON;
2869 }
2870
2871 static Eina_Bool
2872 _e_mod_comp_bd_iconify(void *data __UNUSED__,
2873                        int type   __UNUSED__,
2874                        void      *event)
2875 {
2876    E_Event_Border_Iconify *ev = event;
2877    E_Comp_Win *cw = _e_mod_comp_win_find(ev->border->win);
2878    if (!cw) return ECORE_CALLBACK_PASS_ON;
2879    // fimxe: special iconfiy anim
2880    return ECORE_CALLBACK_PASS_ON;
2881 }
2882
2883 static Eina_Bool
2884 _e_mod_comp_bd_uniconify(void *data __UNUSED__,
2885                          int type   __UNUSED__,
2886                          void      *event)
2887 {
2888    E_Event_Border_Uniconify *ev = event;
2889    E_Comp_Win *cw = _e_mod_comp_win_find(ev->border->win);
2890    if (!cw) return ECORE_CALLBACK_PASS_ON;
2891    // fimxe: special uniconfiy anim
2892    return ECORE_CALLBACK_PASS_ON;
2893 }
2894
2895 static Eina_Bool
2896 _e_mod_comp_bd_urgent_change(void *data __UNUSED__,
2897                              int type   __UNUSED__,
2898                              void      *event)
2899 {
2900    E_Event_Border_Urgent_Change *ev = event;
2901    E_Comp_Win *cw = _e_mod_comp_win_find(ev->border->win);
2902    if (!cw) return ECORE_CALLBACK_PASS_ON;
2903    if (cw->bd->client.icccm.urgent)
2904      edje_object_signal_emit(cw->shobj, "e,state,urgent,on", "e");
2905    else
2906      edje_object_signal_emit(cw->shobj, "e,state,urgent,off", "e");
2907    return ECORE_CALLBACK_PASS_ON;
2908 }
2909
2910 static Eina_Bool
2911 _e_mod_comp_bd_focus_in(void *data __UNUSED__,
2912                         int type   __UNUSED__,
2913                         void      *event)
2914 {
2915    E_Event_Border_Focus_In *ev = event;
2916    E_Comp_Win *cw = _e_mod_comp_win_find(ev->border->win);
2917    if (!cw) return ECORE_CALLBACK_PASS_ON;
2918    edje_object_signal_emit(cw->shobj, "e,state,focus,on", "e");
2919    return ECORE_CALLBACK_PASS_ON;
2920 }
2921
2922 static Eina_Bool
2923 _e_mod_comp_bd_focus_out(void *data __UNUSED__,
2924                          int type   __UNUSED__,
2925                          void      *event)
2926 {
2927    E_Event_Border_Focus_Out *ev = event;
2928    E_Comp_Win *cw = _e_mod_comp_win_find(ev->border->win);
2929    if (!cw) return ECORE_CALLBACK_PASS_ON;
2930    edje_object_signal_emit(cw->shobj, "e,state,focus,off", "e");
2931    return ECORE_CALLBACK_PASS_ON;
2932 }
2933
2934 static Eina_Bool
2935 _e_mod_comp_bd_property(void *data __UNUSED__,
2936                         int type   __UNUSED__,
2937                         void      *event)
2938 {
2939    E_Event_Border_Property *ev = event;
2940    E_Comp_Win *cw = _e_mod_comp_win_find(ev->border->win);
2941    if (!cw) return ECORE_CALLBACK_PASS_ON;
2942    // fimxe: other properties?
2943    return ECORE_CALLBACK_PASS_ON;
2944 }
2945
2946 //////////////////////////////////////////////////////////////////////////
2947 static void
2948 _e_mod_comp_fps_toggle(void)
2949 {
2950    if (_comp_mod)
2951      {
2952         Eina_List *l;
2953         E_Comp *c;
2954
2955         if (_comp_mod->conf->fps_show)
2956           {
2957              _comp_mod->conf->fps_show = 0;
2958              e_config_save_queue();
2959           }
2960         else
2961           {
2962              _comp_mod->conf->fps_show = 1;
2963              e_config_save_queue();
2964           }
2965         EINA_LIST_FOREACH(compositors, l, c) _e_mod_comp_cb_update(c);
2966      }
2967 }
2968
2969 static Eina_Bool
2970 _e_mod_comp_key_down(void *data __UNUSED__,
2971                      int type   __UNUSED__,
2972                      void      *event)
2973 {
2974    Ecore_Event_Key *ev = event;
2975
2976    if ((!strcmp(ev->keyname, "Home")) &&
2977        (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT) &&
2978        (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
2979        (ev->modifiers & ECORE_EVENT_MODIFIER_ALT))
2980      {
2981         if (_comp_mod)
2982           {
2983              _e_mod_config_free(_comp_mod->module);
2984              _e_mod_config_new(_comp_mod->module);
2985              e_config_save();
2986              e_module_disable(_comp_mod->module);
2987              e_config_save();
2988              e_sys_action_do(E_SYS_RESTART, NULL);
2989           }
2990      }
2991    else if ((!strcasecmp(ev->keyname, "f")) &&
2992             (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT) &&
2993             (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
2994             (ev->modifiers & ECORE_EVENT_MODIFIER_ALT))
2995      {
2996         _e_mod_comp_fps_toggle();
2997      }
2998    return ECORE_CALLBACK_PASS_ON;
2999 }
3000
3001 //////////////////////////////////////////////////////////////////////////
3002 static Evas *
3003 _e_mod_comp_evas_get_func(void          *data,
3004                           E_Manager *man __UNUSED__)
3005 {
3006    E_Comp *c = data;
3007    return c->evas;
3008 }
3009
3010 static void
3011 _e_mod_comp_update_func(void          *data,
3012                         E_Manager *man __UNUSED__)
3013 {
3014    E_Comp *c = data;
3015    _e_mod_comp_render_queue(c);
3016 }
3017
3018 static E_Manager_Comp_Source *
3019 _e_mod_comp_src_get_func(void           *data __UNUSED__,
3020                          E_Manager      *man __UNUSED__,
3021                          Ecore_X_Window  win)
3022 {
3023    return (E_Manager_Comp_Source *) _e_mod_comp_win_find(win);
3024 }
3025
3026 static const Eina_List *
3027 _e_mod_comp_src_list_get_func(void          *data,
3028                               E_Manager *man __UNUSED__)
3029 {
3030    E_Comp *c = data;
3031    E_Comp_Win *cw;
3032
3033    if (!c->wins) return NULL;
3034    if (c->wins_invalid)
3035      {
3036         c->wins_invalid = 0;
3037         if (c->wins_list) eina_list_free(c->wins_list);
3038         c->wins_list = NULL;
3039         EINA_INLIST_FOREACH(c->wins, cw)
3040           {
3041              if ((cw->shobj) && (cw->obj))
3042                c->wins_list = eina_list_append(c->wins_list, cw);
3043           }
3044      }
3045    return c->wins_list;
3046 }
3047
3048 static Evas_Object *
3049 _e_mod_comp_src_image_get_func(void *data             __UNUSED__,
3050                                E_Manager *man         __UNUSED__,
3051                                E_Manager_Comp_Source *src)
3052 {
3053 //   E_Comp *c = data;
3054      E_Comp_Win *cw = (E_Comp_Win *)src;
3055      if (!cw->c) return NULL;
3056      return cw->obj;
3057 }
3058
3059 static Evas_Object *
3060 _e_mod_comp_src_shadow_get_func(void *data             __UNUSED__,
3061                                 E_Manager *man         __UNUSED__,
3062                                 E_Manager_Comp_Source *src)
3063 {
3064 //   E_Comp *c = data;
3065      E_Comp_Win *cw = (E_Comp_Win *)src;
3066      if (!cw->c) return NULL;
3067      return cw->shobj;
3068 }
3069
3070 static Evas_Object *
3071 _e_mod_comp_src_image_mirror_add_func(void *data             __UNUSED__,
3072                                       E_Manager *man         __UNUSED__,
3073                                       E_Manager_Comp_Source *src)
3074 {
3075 //   E_Comp *c = data;
3076      E_Comp_Win *cw = (E_Comp_Win *)src;
3077      if (!cw->c) return NULL;
3078      return _e_mod_comp_win_mirror_add(cw);
3079 }
3080
3081 static Eina_Bool
3082 _e_mod_comp_src_visible_get_func(void *data             __UNUSED__,
3083                                  E_Manager *man         __UNUSED__,
3084                                  E_Manager_Comp_Source *src)
3085 {
3086 //   E_Comp *c = data;
3087      E_Comp_Win *cw = (E_Comp_Win *)src;
3088      if (!cw->c) return 0;
3089      return cw->visible;
3090 }
3091
3092 static void
3093 _e_mod_comp_src_hidden_set_func(void *data             __UNUSED__,
3094                                 E_Manager *man         __UNUSED__,
3095                                 E_Manager_Comp_Source *src,
3096                                 Eina_Bool              hidden)
3097 {
3098 //   E_Comp *c = data;
3099      E_Comp_Win *cw = (E_Comp_Win *)src;
3100      if (!cw->c) return;
3101      if (cw->hidden_override == hidden) return;
3102      cw->hidden_override = hidden;
3103      if (cw->bd) e_border_comp_hidden_set(cw->bd, cw->hidden_override);
3104      if (cw->visible)
3105        {
3106           if (cw->hidden_override)
3107             _e_mod_comp_child_hide(cw);
3108           else if (!cw->bd || cw->bd->visible)
3109             _e_mod_comp_child_show(cw);
3110        }
3111      else
3112        {
3113           if (cw->hidden_override) _e_mod_comp_child_hide(cw);
3114        }
3115 }
3116
3117 static Eina_Bool
3118 _e_mod_comp_src_hidden_get_func(void *data             __UNUSED__,
3119                                 E_Manager *man         __UNUSED__,
3120                                 E_Manager_Comp_Source *src)
3121 {
3122 //   E_Comp *c = data;
3123      E_Comp_Win *cw = (E_Comp_Win *)src;
3124      if (!cw->c) return 0;
3125      return cw->hidden_override;
3126 }
3127
3128 static E_Popup *
3129 _e_mod_comp_src_popup_get_func(void *data             __UNUSED__,
3130                              E_Manager *man         __UNUSED__,
3131                              E_Manager_Comp_Source *src)
3132 {
3133    //   E_Comp *c = data;
3134    E_Comp_Win *cw = (E_Comp_Win *)src;
3135    if (!cw->c) return 0;
3136    return cw->pop;
3137 }
3138
3139 static E_Border *
3140 _e_mod_comp_src_border_get_func(void *data             __UNUSED__,
3141                               E_Manager *man         __UNUSED__,
3142                               E_Manager_Comp_Source *src)
3143 {
3144    //   E_Comp *c = data;
3145    E_Comp_Win *cw = (E_Comp_Win *)src;
3146    if (!cw->c) return 0;
3147    return cw->bd;
3148 }
3149
3150 static Ecore_X_Window
3151 _e_mod_comp_src_window_get_func(void *data             __UNUSED__,
3152                                 E_Manager *man         __UNUSED__,
3153                                 E_Manager_Comp_Source *src)
3154 {
3155    //   E_Comp *c = data;
3156    E_Comp_Win *cw = (E_Comp_Win *)src;
3157    if (!cw->c) return 0;
3158    return cw->win;
3159 }
3160
3161 static E_Comp *
3162 _e_mod_comp_add(E_Manager *man)
3163 {
3164    E_Comp *c;
3165    Ecore_X_Window *wins;
3166    Ecore_X_Window_Attributes att;
3167    int i, num;
3168
3169    c = calloc(1, sizeof(E_Comp));
3170    if (!c) return NULL;
3171    
3172    ecore_x_e_comp_sync_supported_set(man->root, _comp_mod->conf->efl_sync);
3173
3174    c->man = man;
3175    c->win = ecore_x_composite_render_window_enable(man->root);
3176    if (!c->win)
3177      {
3178         e_util_dialog_internal
3179           (_("Compositor Error"),
3180           _("Your screen does not support the compositor<br>"
3181             "overlay window. This is needed for it to<br>"
3182             "function."));
3183         free(c);
3184         return NULL;
3185      }
3186
3187    memset((&att), 0, sizeof(Ecore_X_Window_Attributes));
3188    ecore_x_window_attributes_get(c->win, &att);
3189
3190    if ((att.depth != 24) && (att.depth != 32))
3191      {
3192         e_util_dialog_internal
3193           (_("Compositor Error"),
3194           _("Your screen is not in 24/32bit display mode.<br>"
3195             "This is required to be your default depth<br>"
3196             "setting for the compositor to work properly."));
3197         ecore_x_composite_render_window_disable(c->win);
3198         free(c);
3199         return NULL;
3200      }
3201
3202    /* FIXME check if already composited? */
3203    c->cm_selection = ecore_x_window_input_new(man->root, 0, 0, 1, 1);
3204    if (!c->cm_selection)
3205      {
3206         ecore_x_composite_render_window_disable(c->win);
3207         free(c);
3208         return NULL;
3209      }
3210    ecore_x_screen_is_composited_set(c->man->num, c->cm_selection);
3211
3212    if (c->man->num == 0) e_alert_composite_win = c->win;
3213
3214    if (_comp_mod->conf->engine == E_EVAS_ENGINE_GL_X11)
3215      {
3216         int opt[20];
3217         int opt_i = 0;
3218
3219         if (_comp_mod->conf->indirect)
3220           {
3221              opt[opt_i] = ECORE_EVAS_GL_X11_OPT_INDIRECT;
3222              opt_i++;
3223              opt[opt_i] = 1;
3224              opt_i++;
3225           }
3226         if (_comp_mod->conf->vsync)
3227           {
3228              opt[opt_i] = ECORE_EVAS_GL_X11_OPT_VSYNC;
3229              opt_i++;
3230              opt[opt_i] = 1;
3231              opt_i++;
3232           }
3233         if (opt_i > 0)
3234           {
3235              opt[opt_i] = ECORE_EVAS_GL_X11_OPT_NONE;
3236              c->ee = ecore_evas_gl_x11_options_new
3237                  (NULL, c->win, 0, 0, man->w, man->h, opt);
3238           }
3239         if (!c->ee)
3240           c->ee = ecore_evas_gl_x11_new(NULL, c->win, 0, 0, man->w, man->h);
3241         if (c->ee)
3242           {
3243              c->gl = 1;
3244              ecore_evas_gl_x11_pre_post_swap_callback_set
3245                (c->ee, c, _e_mod_comp_pre_swap, NULL);
3246           }
3247      }
3248    if (!c->ee)
3249      {
3250         if (_comp_mod->conf->engine == E_EVAS_ENGINE_GL_X11)
3251           {
3252              e_util_dialog_internal
3253                (_("Compositor Warning"),
3254                _("Your screen does not support OpenGL.<br>"
3255                  "Falling back to software engine."));
3256           }
3257
3258         c->ee = ecore_evas_software_x11_new(NULL, c->win, 0, 0, man->w, man->h);
3259      }
3260
3261    ecore_evas_comp_sync_set(c->ee, 0);
3262 //   ecore_evas_manual_render_set(c->ee, _comp_mod->conf->lock_fps);
3263    c->evas = ecore_evas_get(c->ee);
3264    ecore_evas_show(c->ee);
3265
3266    c->ee_win = ecore_evas_window_get(c->ee);
3267    ecore_x_screen_is_composited_set(c->man->num, c->ee_win);
3268    ecore_x_composite_redirect_subwindows
3269      (c->man->root, ECORE_X_COMPOSITE_UPDATE_MANUAL);
3270
3271    wins = ecore_x_window_children_get(c->man->root, &num);
3272    if (wins)
3273      {
3274         for (i = 0; i < num; i++)
3275           {
3276              E_Comp_Win *cw;
3277              int x, y, w, h, border;
3278              char *wname = NULL, *wclass = NULL;
3279
3280              ecore_x_icccm_name_class_get(wins[i], &wname, &wclass);
3281              if ((man->initwin == wins[i]) ||
3282                  ((wname) && (wclass) && (!strcmp(wname, "E")) &&
3283                   (!strcmp(wclass, "Init_Window"))))
3284                {
3285                   free(wname);
3286                   free(wclass);
3287                   ecore_x_window_reparent(wins[i], c->win, 0, 0);
3288                   ecore_x_sync();
3289                   continue;
3290                }
3291              if (wname) free(wname);
3292              if (wclass) free(wclass);
3293              wname = wclass = NULL;
3294              cw = _e_mod_comp_win_add(c, wins[i]);
3295              if (!cw) continue;
3296              ecore_x_window_geometry_get(cw->win, &x, &y, &w, &h);
3297              border = ecore_x_window_border_width_get(cw->win);
3298              if (wins[i] == c->win) continue;
3299              _e_mod_comp_win_configure(cw, x, y, w, h, border);
3300              if (ecore_x_window_visible_get(wins[i]))
3301                _e_mod_comp_win_show(cw);
3302           }
3303         free(wins);
3304      }
3305
3306    ecore_x_window_key_grab(c->man->root,
3307                            "Home",
3308                            ECORE_EVENT_MODIFIER_SHIFT |
3309                            ECORE_EVENT_MODIFIER_CTRL |
3310                            ECORE_EVENT_MODIFIER_ALT, 0);
3311    ecore_x_window_key_grab(c->man->root,
3312                            "F",
3313                            ECORE_EVENT_MODIFIER_SHIFT |
3314                            ECORE_EVENT_MODIFIER_CTRL |
3315                            ECORE_EVENT_MODIFIER_ALT, 0);
3316
3317    c->comp.data = c;
3318    c->comp.func.evas_get = _e_mod_comp_evas_get_func;
3319    c->comp.func.update = _e_mod_comp_update_func;
3320    c->comp.func.src_get = _e_mod_comp_src_get_func;
3321    c->comp.func.src_list_get = _e_mod_comp_src_list_get_func;
3322    c->comp.func.src_image_get = _e_mod_comp_src_image_get_func;
3323    c->comp.func.src_shadow_get = _e_mod_comp_src_shadow_get_func;
3324    c->comp.func.src_image_mirror_add = _e_mod_comp_src_image_mirror_add_func;
3325    c->comp.func.src_visible_get = _e_mod_comp_src_visible_get_func;
3326    c->comp.func.src_hidden_set = _e_mod_comp_src_hidden_set_func;
3327    c->comp.func.src_hidden_get = _e_mod_comp_src_hidden_get_func;
3328    c->comp.func.src_window_get = _e_mod_comp_src_window_get_func;
3329    c->comp.func.src_border_get = _e_mod_comp_src_border_get_func;
3330    c->comp.func.src_popup_get = _e_mod_comp_src_popup_get_func;
3331
3332    e_manager_comp_set(c->man, &(c->comp));
3333    return c;
3334 }
3335
3336 static void
3337 _e_mod_comp_del(E_Comp *c)
3338 {
3339    E_Comp_Win *cw;
3340
3341    if (c->fps_fg)
3342      {
3343         evas_object_del(c->fps_fg);
3344         c->fps_fg = NULL;
3345      }
3346    if (c->fps_bg)
3347      {
3348         evas_object_del(c->fps_bg);
3349         c->fps_bg = NULL;
3350      }
3351    e_manager_comp_set(c->man, NULL);
3352
3353    ecore_x_window_key_ungrab(c->man->root,
3354                              "F",
3355                              ECORE_EVENT_MODIFIER_SHIFT |
3356                              ECORE_EVENT_MODIFIER_CTRL |
3357                              ECORE_EVENT_MODIFIER_ALT, 0);
3358    ecore_x_window_key_ungrab(c->man->root,
3359                              "Home",
3360                              ECORE_EVENT_MODIFIER_SHIFT |
3361                              ECORE_EVENT_MODIFIER_CTRL |
3362                              ECORE_EVENT_MODIFIER_ALT, 0);
3363    if (c->grabbed)
3364      {
3365         c->grabbed = 0;
3366         ecore_x_ungrab();
3367      }
3368    ecore_x_screen_is_composited_set(c->man->num, 0);
3369    while (c->wins)
3370      {
3371         cw = (E_Comp_Win *)(c->wins);
3372         if (cw->counter)
3373           {
3374              ecore_x_sync_counter_free(cw->counter);
3375              cw->counter = 0;
3376           }
3377         cw->force = 1;
3378         _e_mod_comp_win_hide(cw);
3379         cw->force = 1;
3380         _e_mod_comp_win_del(cw);
3381      }
3382    ecore_evas_free(c->ee);
3383    ecore_x_composite_unredirect_subwindows
3384      (c->man->root, ECORE_X_COMPOSITE_UPDATE_MANUAL);
3385    ecore_x_composite_render_window_disable(c->win);
3386    if (c->man->num == 0) e_alert_composite_win = 0;
3387    if (c->render_animator) ecore_animator_del(c->render_animator);
3388    if (c->new_up_timer) ecore_timer_del(c->new_up_timer);
3389    if (c->update_job) ecore_job_del(c->update_job);
3390    if (c->wins_list) eina_list_free(c->wins_list);
3391
3392    ecore_x_window_free(c->cm_selection);
3393    ecore_x_screen_is_composited_set(c->man->num, 0);
3394    ecore_x_e_comp_sync_supported_set(c->man->root, 0);
3395
3396    free(c);
3397 }
3398
3399 //////////////////////////////////////////////////////////////////////////
3400
3401 Eina_Bool
3402 e_mod_comp_init(void)
3403 {
3404    Eina_List *l;
3405    E_Manager *man;
3406
3407    windows = eina_hash_string_superfast_new(NULL);
3408    borders = eina_hash_string_superfast_new(NULL);
3409    damages = eina_hash_string_superfast_new(NULL);
3410
3411    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CREATE, _e_mod_comp_create, NULL));
3412    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _e_mod_comp_destroy, NULL));
3413    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, _e_mod_comp_show, NULL));
3414    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, _e_mod_comp_hide, NULL));
3415    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_REPARENT, _e_mod_comp_reparent, NULL));
3416    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE, _e_mod_comp_configure, NULL));
3417    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_STACK, _e_mod_comp_stack, NULL));
3418    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, _e_mod_comp_property, NULL));
3419    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _e_mod_comp_message, NULL));
3420    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHAPE, _e_mod_comp_shape, NULL));
3421    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_DAMAGE_NOTIFY, _e_mod_comp_damage, NULL));
3422    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DAMAGE, _e_mod_comp_damage_win, NULL));
3423
3424    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_mod_comp_key_down, NULL));
3425
3426    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_CONTAINER_RESIZE, _e_mod_comp_randr, NULL));
3427
3428    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_ADD, _e_mod_comp_bd_add, NULL));
3429    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_REMOVE, _e_mod_comp_bd_del, NULL));
3430    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_SHOW, _e_mod_comp_bd_show, NULL));
3431    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_HIDE, _e_mod_comp_bd_hide, NULL));
3432    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_MOVE, _e_mod_comp_bd_move, NULL));
3433    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_RESIZE, _e_mod_comp_bd_resize, NULL));
3434    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_ICONIFY, _e_mod_comp_bd_iconify, NULL));
3435    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_UNICONIFY, _e_mod_comp_bd_uniconify, NULL));
3436    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_URGENT_CHANGE, _e_mod_comp_bd_urgent_change, NULL));
3437    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_FOCUS_IN, _e_mod_comp_bd_focus_in, NULL));
3438    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_FOCUS_OUT, _e_mod_comp_bd_focus_out, NULL));
3439    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_BORDER_PROPERTY, _e_mod_comp_bd_property, NULL));
3440
3441    if (!ecore_x_composite_query())
3442      {
3443         e_util_dialog_internal
3444           (_("Compositor Error"),
3445           _("Your X Display does not support the XComposite extension<br>"
3446             "or Ecore was built without XComposite support.<br>"
3447             "Note that for composite support you will also need<br>"
3448             "XRender and XFixes support in X11 and Ecore."));
3449         return 0;
3450      }
3451    if (!ecore_x_damage_query())
3452      {
3453         e_util_dialog_internal
3454           (_("Compositor Error"),
3455           _("Your screen does not support the XDamage extension<br>"
3456             "or Ecore was built without XDamage support."));
3457         return 0;
3458      }
3459    EINA_LIST_FOREACH(e_manager_list(), l, man)
3460      {
3461         E_Comp *c;
3462
3463         c = _e_mod_comp_add(man);
3464         if (c) compositors = eina_list_append(compositors, c);
3465      }
3466
3467    ecore_x_sync();
3468
3469    return 1;
3470 }
3471
3472 void
3473 e_mod_comp_shutdown(void)
3474 {
3475    E_Comp *c;
3476
3477    EINA_LIST_FREE(compositors, c) _e_mod_comp_del(c);
3478
3479    E_FREE_LIST(handlers, ecore_event_handler_del);
3480
3481    if (damages) eina_hash_free(damages);
3482    if (windows) eina_hash_free(windows);
3483    if (borders) eina_hash_free(borders);
3484    damages = NULL;
3485    windows = NULL;
3486    borders = NULL;
3487 }
3488
3489 void
3490 e_mod_comp_shadow_set(void)
3491 {
3492    Eina_List *l;
3493    E_Comp *c;
3494
3495    EINA_LIST_FOREACH(compositors, l, c)
3496      {
3497         E_Comp_Win *cw;
3498
3499 //        ecore_evas_manual_render_set(c->ee, _comp_mod->conf->lock_fps);
3500         _e_mod_comp_fps_update(c);
3501         EINA_INLIST_FOREACH(c->wins, cw)
3502           {
3503              if ((cw->shobj) && (cw->obj))
3504                {
3505                   _e_mod_comp_win_shadow_setup(cw);
3506
3507                   if (cw->visible)
3508                     {
3509                        edje_object_signal_emit(cw->shobj, "e,state,visible,on", "e");
3510                        if (!cw->animating)
3511                          {
3512                             cw->c->animating++;
3513                          }
3514                        _e_mod_comp_win_render_queue(cw);
3515                        cw->animating = 1;
3516
3517                        cw->pending_count++;
3518                        e_manager_comp_event_src_visibility_send
3519                          (cw->c->man, (E_Manager_Comp_Source *)cw,
3520                          _e_mod_comp_cb_pending_after, cw->c);
3521                     }
3522                }
3523           }
3524      }
3525 }
3526