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