d3c2fcd765b09ccea782e85b5aa79cacb9c696a8
[platform/upstream/efl.git] / src / modules / ecore_evas / engines / x / ecore_evas_x.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include <Eina.h>
9 #include <Ecore.h>
10 #include "ecore_private.h"
11 #include <Ecore_Input.h>
12 #include <Ecore_Input_Evas.h>
13
14 #include <Ecore_X.h>
15 #include <Ecore_X_Atoms.h>
16
17 #ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
18 # include <Evas_Engine_Software_X11.h>
19 #endif
20
21 #ifdef BUILD_ECORE_EVAS_OPENGL_X11
22 # include <Evas_Engine_GL_X11.h>
23 #endif
24
25 #include <Ecore_Evas.h>
26 #include "ecore_evas_private.h"
27 #include "ecore_evas_x11.h"
28
29 #ifdef EAPI
30 # undef EAPI
31 #endif
32
33 #ifdef _WIN32
34 # ifdef DLL_EXPORT
35 #  define EAPI __declspec(dllexport)
36 # else
37 #  define EAPI
38 # endif /* ! DLL_EXPORT */
39 #else
40 # ifdef __GNUC__
41 #  if __GNUC__ >= 4
42 #   define EAPI __attribute__ ((visibility("default")))
43 #  else
44 #   define EAPI
45 #  endif
46 # else
47 #  define EAPI
48 # endif
49 #endif /* ! _WIN32 */
50
51 #define EDBG(...)                                                       \
52   EINA_LOG(_ecore_evas_log_dom, EINA_LOG_LEVEL_DBG + 1, __VA_ARGS__);
53
54 static int _ecore_evas_init_count = 0;
55
56 static Ecore_Event_Handler *ecore_evas_event_handlers[13];
57
58 static int leader_ref = 0;
59 static Ecore_X_Window leader_win = 0;
60
61 static const char *interface_x11_name = "x11";
62 static const int   interface_x11_version = 1;
63
64 static const char *interface_software_x11_name = "software_x11";
65 static const int   interface_software_x11_version = 1;
66
67 #ifdef BUILD_ECORE_EVAS_OPENGL_X11
68 static const char *interface_gl_x11_name = "gl_x11";
69 #endif
70 static const int   interface_gl_x11_version = 1;
71
72 typedef struct _Ecore_Evas_Engine_Data_X11 Ecore_Evas_Engine_Data_X11;
73
74 struct _Ecore_Evas_Engine_Data_X11 {
75    Ecore_X_Window win_root;
76    Eina_List     *win_extra;
77    Ecore_X_Pixmap pmap;
78    Ecore_X_Pixmap mask;
79    Ecore_X_GC     gc;
80    Ecore_X_XRegion *damages;
81    Ecore_Timer     *outdelay;
82    Ecore_X_Event_Mouse_Out out_ev;
83    Ecore_X_Sync_Counter sync_counter;
84    Ecore_X_Window leader;
85    Ecore_X_Sync_Counter netwm_sync_counter;
86    int            configure_reqs;
87    int            netwm_sync_val_hi;
88    unsigned int   netwm_sync_val_lo;
89    int            sync_val; // bigger! this will screw up at 2 billion fram~
90    int            screen_num;
91    int            px, py, pw, ph;
92    unsigned char  direct_resize : 1;
93    unsigned char  using_bg_pixmap : 1;
94    unsigned char  managed : 1;
95    unsigned char  sync_began : 1;
96    unsigned char  sync_cancel : 1;
97    unsigned char  netwm_sync_set : 1;
98    unsigned char  configure_coming : 1;
99    struct {
100      unsigned char modal : 1;
101      unsigned char sticky : 1;
102      unsigned char maximized_v : 1;
103      unsigned char maximized_h : 1;
104      unsigned char shaded : 1;
105      unsigned char skip_taskbar : 1;
106      unsigned char skip_pager : 1;
107      unsigned char fullscreen : 1;
108      unsigned char above : 1;
109      unsigned char below : 1;
110    } state;
111    struct {
112      unsigned char available : 1; // need to setup available profiles in a w
113      unsigned char change : 1; // need to send change event to the WM
114      unsigned char done : 1; // need to send change done event to the WM
115    } profile;
116    struct {
117      unsigned char supported: 1;
118      unsigned char prepare : 1;
119      unsigned char request : 1;
120      unsigned char done : 1;
121      unsigned char configure_coming : 1;
122      Ecore_Job    *manual_mode_job;
123    } wm_rot;
124    Ecore_X_Window win_shaped_input;
125    struct
126      {
127         unsigned int front, back; // front and back pixmaps (double-buffer)
128         Evas_Coord w, h; // store pixmap size (saves X roundtrips)
129         int depth; // store depth to save us from fetching engine info pre_render
130         void *visual; // store visual used to create pixmap
131         unsigned long colormap; // store colormap used to create pixmap
132      } pixmap;
133    Eina_Bool destroyed : 1; // X window has been deleted and cannot be used
134 };
135
136 static Ecore_Evas_Interface_X11 * _ecore_evas_x_interface_x11_new(void);
137 #ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
138 static Ecore_Evas_Interface_Software_X11 *_ecore_evas_x_interface_software_x11_new(void);
139 #endif
140 #ifdef BUILD_ECORE_EVAS_OPENGL_X11
141 static Ecore_Evas_Interface_Gl_X11 *_ecore_evas_x_interface_gl_x11_new(void);
142 #endif
143 static void      _ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation, int resize);
144 static Eina_Bool _ecore_evas_x_wm_rot_manual_rotation_done_timeout(void *data);
145 static void      _ecore_evas_x_wm_rot_manual_rotation_done_timeout_update(Ecore_Evas *ee);
146 static void      _ecore_evas_x_aux_hints_set(Ecore_Evas *ee, const char *hints);
147
148 static void _resize_shape_do(Ecore_Evas *);
149 static void _shaped_do(Ecore_Evas *, int);
150 static void _alpha_do(Ecore_Evas *, int);
151 static void _transparent_do(Ecore_Evas *, int);
152 static void _avoid_damage_do(Ecore_Evas *, int);
153 static void _rotation_do(Ecore_Evas *, int, int);
154
155 static void
156 _ecore_evas_x_hints_update(Ecore_Evas *ee)
157 {
158    Ecore_X_Window_State_Hint initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
159
160    if (ee->prop.iconified)
161      initial_state = ECORE_X_WINDOW_STATE_HINT_ICONIC;
162
163    ecore_x_icccm_hints_set
164      (ee->prop.window,
165          !ee->prop.focus_skip /* accepts_focus */,
166          initial_state /* initial_state */,
167          0 /* icon_pixmap */,
168          0 /* icon_mask */,
169          0 /* icon_window */,
170          ee->prop.group_ee_win /* window_group */,
171          ee->prop.urgent /* is_urgent */);
172 }
173
174 static void
175 _ecore_evas_x_group_leader_set(Ecore_Evas *ee)
176 {
177    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
178    leader_ref++;
179    if (leader_ref == 1)
180      {
181         char *id = NULL;
182
183         leader_win =
184           ecore_x_window_override_new(edata->win_root, 1234, 5678, 1, 2);
185         ecore_x_window_defaults_set(leader_win);
186         if ((id = getenv("DESKTOP_STARTUP_ID")))
187           ecore_x_netwm_startup_id_set(leader_win,id);
188         ecore_x_icccm_client_leader_set(leader_win, leader_win);
189      }
190    edata->leader = leader_win;
191    ecore_x_icccm_client_leader_set(ee->prop.window, leader_win);
192 }
193
194 static void
195 _ecore_evas_x_group_leader_unset(Ecore_Evas *ee)
196 {
197    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
198    if (!edata->destroyed)
199      ecore_x_window_prop_property_del(ee->prop.window,
200                                       ECORE_X_ATOM_WM_CLIENT_LEADER);
201    if (edata->leader == leader_win)
202      {
203         leader_ref--;
204         if (leader_ref <= 0)
205           {
206              ecore_x_window_free(leader_win);
207              leader_win = 0;
208           }
209         edata->leader = 0;
210      }
211 }
212
213 static void
214 _ecore_evas_x_group_leader_update(Ecore_Evas *ee)
215 {
216    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
217    if (edata->leader)
218       ecore_x_icccm_client_leader_set(ee->prop.window, edata->leader);
219 }
220
221 static void
222 _ecore_evas_x_protocols_set(Ecore_Evas *ee)
223 {
224    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
225    Ecore_X_Atom protos[3];
226    unsigned int num = 0, tmp = 0;
227
228    if (ee->func.fn_delete_request)
229      protos[num++] = ECORE_X_ATOM_WM_DELETE_WINDOW;
230    protos[num++] = ECORE_X_ATOM_NET_WM_PING;
231    protos[num++] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
232    ecore_x_icccm_protocol_atoms_set(ee->prop.window, protos, num);
233
234    if (!edata->netwm_sync_counter)
235      edata->netwm_sync_counter = ecore_x_sync_counter_new(0);
236
237    tmp = edata->netwm_sync_counter;
238    ecore_x_window_prop_card32_set(ee->prop.window,
239                                   ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER,
240                                   &tmp, 1);
241
242    // set property on window to say "I talk the deiconify approve protcol"
243    tmp = 1;
244    ecore_x_window_prop_card32_set(ee->prop.window,
245                                   ECORE_X_ATOM_E_DEICONIFY_APPROVE,
246                                   &tmp, 1);
247 }
248
249 static void
250 _ecore_evas_x_sync_set(Ecore_Evas *ee)
251 {
252    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
253    Ecore_X_Sync_Counter sync_counter = edata->sync_counter;
254
255    if (((ee->should_be_visible) || (ee->visible)) &&
256        ((ecore_x_e_comp_sync_supported_get(edata->win_root)) &&
257            (!ee->no_comp_sync) && (_ecore_evas_app_comp_sync)))
258      {
259         if (!edata->sync_counter)
260            edata->sync_counter = ecore_x_sync_counter_new(0);
261      }
262    else
263      {
264         if (edata->sync_counter)
265           {
266            ecore_x_sync_counter_free(edata->sync_counter);
267              edata->sync_val = 0;
268           }
269         edata->sync_counter = 0;
270      }
271    if ((!edata->destroyed) && (sync_counter != edata->sync_counter))
272      ecore_x_e_comp_sync_counter_set(ee->prop.window, edata->sync_counter);
273 }
274
275 static void
276 _ecore_evas_x_sync_clear(Ecore_Evas *ee)
277 {
278    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
279
280    if (!edata->sync_counter) return;
281    ecore_x_sync_counter_free(edata->sync_counter);
282    edata->sync_val = 0;
283    edata->sync_counter = 0;
284 }
285
286 static void
287 _ecore_evas_x_wm_rotation_protocol_set(Ecore_Evas *ee)
288 {
289    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
290
291    if (ecore_x_e_window_rotation_supported_get(edata->win_root))
292      ee->prop.wm_rot.supported = 1;
293    else
294      ee->prop.wm_rot.supported = 0;
295 }
296
297 static void
298 _ecore_evas_x_window_profile_protocol_set(Ecore_Evas *ee)
299 {
300    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
301
302    /* check and set profile protocol hint */
303    if (ecore_x_e_window_profile_supported_get(edata->win_root))
304      {
305         unsigned int v = 1;
306         ecore_x_window_prop_card32_set
307           (ee->prop.window,
308           ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED,
309           &v, 1);
310
311         ee->profile_supported = 1;
312      }
313    else
314      ee->profile_supported = 0;
315 }
316
317 static void
318 _ecore_evas_x_window_profile_set(Ecore_Evas *ee)
319 {
320    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
321
322    if (((ee->should_be_visible) || (ee->visible)) &&
323        (ee->profile_supported))
324      {
325         if (edata->profile.available)
326           {
327              ecore_x_e_window_available_profiles_set
328                (ee->prop.window,
329                (const char **)ee->prop.profile.available_list,
330                (const int)ee->prop.profile.count);
331
332              edata->profile.available = 0;
333           }
334
335         if (edata->profile.change)
336           {
337              if (ee->prop.profile.name)
338                {
339                   /* We need to keep the profile as an x property to let the WM.
340                    * Then the WM reads it when creating the border window.
341                    */
342                   Ecore_X_Atom a = ecore_x_atom_get(ee->prop.profile.name);
343                   ecore_x_window_prop_atom_set
344                     (ee->prop.window,
345                     ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE,
346                     &a, 1);
347
348                   ecore_x_e_window_profile_change_send
349                     (edata->win_root,
350                     ee->prop.window,
351                     ee->prop.profile.name);
352                }
353              edata->profile.change = 0;
354           }
355      }
356 }
357
358 static void
359 _ecore_evas_x_wm_rot_manual_rotation_done_job(void *data)
360 {
361    Ecore_Evas *ee = (Ecore_Evas *)data;
362    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
363
364    edata->wm_rot.manual_mode_job = NULL;
365    ee->prop.wm_rot.manual_mode.wait_for_done = EINA_FALSE;
366
367    ecore_x_e_window_rotation_change_done_send
368      (edata->win_root, ee->prop.window, ee->rotation, ee->w, ee->h);
369
370    edata->wm_rot.done = 0;
371 }
372
373 static void
374 _ecore_evas_x_aux_hints_supported_update(Ecore_Evas *ee)
375 {
376    Ecore_X_Window root = ecore_x_window_root_first_get();
377    unsigned char *data = NULL;
378    unsigned int num = 0, i = 0;
379    int res = 0, n = 0;
380    char **str;
381    const char *hint;
382
383    EINA_LIST_FREE(ee->prop.aux_hint.supported_list, hint)
384      {
385         eina_stringshare_del(hint);
386      }
387
388    res = ecore_x_window_prop_property_get
389      (root, ECORE_X_ATOM_E_WINDOW_AUX_HINT_SUPPORTED_LIST,
390       ECORE_X_ATOM_STRING, 0, &data, &n);
391
392    if ((res == 8) && (n > 0))
393      {
394         str = eina_str_split_full((char *)data, ",", -1, &num);
395         for (i = 0; i < num; i++)
396           {
397              hint = eina_stringshare_add(str[i]);
398              ee->prop.aux_hint.supported_list = 
399                eina_list_append(ee->prop.aux_hint.supported_list, hint);
400           }
401
402         if (str)
403           {
404              free(str[0]);
405              free(str);
406           }
407      }
408
409    free(data);
410 }
411
412 static void
413 _ecore_evas_x_aux_hints_update(Ecore_Evas *ee)
414 {
415    Eina_Strbuf *buf = _ecore_evas_aux_hints_string_get(ee);
416    if (buf)
417      {
418         _ecore_evas_x_aux_hints_set(ee, eina_strbuf_string_get(buf));
419         eina_strbuf_free(buf);
420      }
421 }
422
423 # ifdef BUILD_ECORE_EVAS_OPENGL_X11
424 static Ecore_X_Window
425 _ecore_evas_x_gl_window_new(Ecore_Evas *ee, Ecore_X_Window parent, int x, int y, int w, int h, Eina_Bool override, int argb, const int *opt)
426 {
427    Evas_Engine_Info_GL_X11 *einfo;
428    Ecore_X_Window win;
429
430    einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas);
431    if (einfo)
432      {
433         int screen;
434
435         if (opt)
436           {
437              int op;
438
439              for (op = 0; opt[op]; op++)
440                {
441                   if (opt[op] == ECORE_EVAS_GL_X11_OPT_INDIRECT)
442                     {
443                        op++;
444                        einfo->indirect = opt[op];
445                     }
446                   else if (opt[op] == ECORE_EVAS_GL_X11_OPT_VSYNC)
447                     {
448                        op++;
449                        einfo->vsync = opt[op];
450                     }
451 #ifdef EVAS_ENGINE_GL_X11_SWAP_MODE_EXISTS                  
452                   else if (opt[op] == ECORE_EVAS_GL_X11_OPT_SWAP_MODE)
453                     {
454                        op++;
455                        if ((evas_version->major >= 1) &&
456                            (evas_version->minor >= 7) &&
457                            (evas_version->micro >= 99))
458                        einfo->swap_mode = opt[op];
459                     }
460 #endif
461                   else if (opt[op] == ECORE_EVAS_GL_X11_OPT_GL_DEPTH)
462                     {
463                        op++;
464                        einfo->depth_bits = opt[op];
465                     }
466                   else if (opt[op] == ECORE_EVAS_GL_X11_OPT_GL_STENCIL)
467                     {
468                        op++;
469                        einfo->stencil_bits = opt[op];
470                     }
471                   else if (opt[op] == ECORE_EVAS_GL_X11_OPT_GL_MSAA)
472                     {
473                        op++;
474                        einfo->msaa_bits = opt[op];
475                     }
476                }
477           }
478
479         /* FIXME: this is inefficient as its 1 or more round trips */
480         screen = ecore_x_screen_index_get(ecore_x_default_screen_get());
481         if (ecore_x_screen_count_get() > 1)
482           {
483              Ecore_X_Window *roots;
484              int num, i;
485
486              num = 0;
487              roots = ecore_x_window_root_list(&num);
488              if (roots)
489                {
490                   Ecore_X_Window root;
491
492                   root = ecore_x_window_root_get(parent);
493                   for (i = 0; i < num; i++)
494                     {
495                        if (root == roots[i])
496                          {
497                             screen = i;
498                             break;
499                          }
500                     }
501                   free(roots);
502                }
503           }
504
505         einfo->info.display = ecore_x_display_get();
506         einfo->info.screen = screen;
507
508         einfo->info.destination_alpha = argb;
509
510         einfo->info.visual = einfo->func.best_visual_get(einfo);
511         einfo->info.colormap = einfo->func.best_colormap_get(einfo);
512         einfo->info.depth = einfo->func.best_depth_get(einfo);
513
514         if ((!einfo->info.visual) ||
515             (!einfo->info.colormap) || (!einfo->info.depth))
516           {
517              WRN("OpenGL X11 init engine '%s' failed - no visual, colormap or depth.", ee->driver);
518              if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
519                {
520                   ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
521                   return 0;
522                }
523           }
524         win = ecore_x_window_full_new(parent, x, y, w, h,
525                                       einfo->info.visual,
526                                       einfo->info.colormap,
527                                       einfo->info.depth,
528                                       override);
529         ecore_x_window_pixel_gravity_set(win, ECORE_X_GRAVITY_FORGET);
530         ecore_x_vsync_animator_tick_source_set(win);
531
532         /* attr.backing_store = NotUseful; */
533         /* attr.override_redirect = override; */
534         /* attr.colormap = einfo->info.colormap; */
535         /* attr.border_pixel = 0; */
536         /* attr.background_pixmap = None; */
537         /* attr.event_mask = */
538         /*   KeyPressMask | KeyReleaseMask | */
539         /*   ExposureMask | ButtonPressMask | ButtonReleaseMask | */
540         /*   EnterWindowMask | LeaveWindowMask | */
541         /*   PointerMotionMask | StructureNotifyMask | VisibilityChangeMask | */
542         /*   FocusChangeMask | PropertyChangeMask | ColormapChangeMask; */
543         /* attr.bit_gravity = ForgetGravity; */
544
545         /* win = */
546         /*   XCreateWindow(einfo->info.display, parent, x, y, w, h, 0, */
547         /*                 einfo->info.depth, InputOutput, einfo->info.visual, */
548         /*                 CWBackingStore | CWColormap | CWBackPixmap | */
549         /*                 CWBorderPixel | CWBitGravity | CWEventMask | */
550         /*                 CWOverrideRedirect, &attr); */
551
552         einfo->info.drawable = win;
553
554         if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
555           {
556              WRN("evas_engine_info_set() for engine '%s' failed.", ee->driver);
557              ecore_x_window_free(win);
558              return 0;
559           }
560      }
561    else
562      win = 0;
563
564    return win;
565 }
566 #endif
567
568 static int
569 _render_updates_process(Ecore_Evas *ee, Eina_List *updates)
570 {
571    int rend = 0;
572    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
573
574    if (ee->prop.avoid_damage)
575      {
576         if (edata->using_bg_pixmap)
577           {
578              if (updates)
579                {
580                   Eina_List *l = NULL;
581                   Eina_Rectangle *r;
582
583                   EINA_LIST_FOREACH(updates, l, r)
584                     ecore_x_window_area_clear(ee->prop.window,
585                                               r->x, r->y, r->w, r->h);
586                   if (ee->shaped)
587                     {
588                        ecore_x_window_shape_mask_set(ee->prop.window,
589                                                      edata->mask);
590                     }
591                   if (ee->alpha)
592                     {
593 //                     ecore_x_window_shape_input_mask_set(ee->prop.window, edata->mask);
594                     }
595                   _ecore_evas_idle_timeout_update(ee);
596                   rend = 1;
597                }
598           }
599         else
600           {
601              if (updates)
602                {
603                   Eina_List *l = NULL;
604                   Eina_Rectangle *r;
605
606                   EINA_LIST_FOREACH(updates, l, r)
607                     {
608                        Ecore_X_Rectangle rect;
609                        Ecore_X_XRegion *tmpr;
610
611                        if (!edata->damages)
612                          edata->damages = ecore_x_xregion_new();
613                        tmpr = ecore_x_xregion_new();
614                        if (ee->rotation == 0)
615                          {
616                             rect.x = r->x;
617                             rect.y = r->y;
618                             rect.width = r->w;
619                             rect.height = r->h;
620                          }
621                        else if (ee->rotation == 90)
622                          {
623                             rect.x = r->y;
624                             rect.y = ee->h - r->x - r->w;
625                             rect.width = r->h;
626                             rect.height = r->w;
627                          }
628                        else if (ee->rotation == 180)
629                          {
630                             rect.x = ee->w - r->x - r->w;
631                             rect.y = ee->h - r->y - r->h;
632                             rect.width = r->w;
633                             rect.height = r->h;
634                          }
635                        else if (ee->rotation == 270)
636                          {
637                             rect.x = ee->w - r->y - r->h;
638                             rect.y = r->x;
639                             rect.width = r->h;
640                             rect.height = r->w;
641                          }
642                        ecore_x_xregion_union_rect(tmpr, edata->damages,
643                                                   &rect);
644                        ecore_x_xregion_free(edata->damages);
645                        edata->damages = tmpr;
646                     }
647                   if (edata->damages)
648                     {
649                        if (ee->shaped)
650                          {
651                             /* if we have a damage pixmap - we can avoid exposures by
652                              * disabling them just for setting the mask */
653                             ecore_x_event_mask_unset(ee->prop.window, ECORE_X_EVENT_MASK_WINDOW_DAMAGE);
654                             ecore_x_window_shape_mask_set(ee->prop.window,
655                                                           edata->mask);
656                             /* and re-enable them again */
657                             ecore_x_event_mask_set(ee->prop.window, ECORE_X_EVENT_MASK_WINDOW_DAMAGE);
658                          }
659                        ecore_x_xregion_set(edata->damages, edata->gc);
660                        ecore_x_pixmap_paste(edata->pmap, ee->prop.window,
661                                             edata->gc, 0, 0, ee->w, ee->h,
662                                             0, 0);
663                        ecore_x_xregion_free(edata->damages);
664                        edata->damages = NULL;
665                     }
666                   _ecore_evas_idle_timeout_update(ee);
667                   rend = 1;
668                }
669           }
670      }
671    else if (((ee->visible) && (ee->draw_ok)) ||
672             ((ee->should_be_visible) && (ee->prop.fullscreen)) ||
673             ((ee->should_be_visible) && (ee->prop.override)))
674      {
675         if (updates)
676           {
677              if (ee->shaped)
678                {
679                   ecore_x_window_shape_mask_set(ee->prop.window,
680                                                 edata->mask);
681                }
682              if (ee->alpha)
683                {
684 //                ecore_x_window_shape_input_mask_set(ee->prop.window, edata->mask);
685                }
686              _ecore_evas_idle_timeout_update(ee);
687              rend = 1;
688           }
689      }
690    else
691      evas_norender(ee->evas);
692
693    if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
694
695 /*
696    if (rend)
697      {
698         static int frames = 0;
699         static double t0 = 0.0;
700         double t, td;
701
702         t = ecore_time_get();
703         frames++;
704         if ((t - t0) > 1.0)
705           {
706              td = t - t0;
707              printf("FPS: %3.3f\n", (double)frames / td);
708              frames = 0;
709              t0 = t;
710           }
711      }
712  */
713    return rend;
714 }
715
716 static void
717 _ecore_evas_x_render_updates(void *data, Evas *e EINA_UNUSED, void *event_info)
718 {
719    Evas_Event_Render_Post *ev = event_info;
720    Ecore_Evas *ee = data;
721
722    if (!ev) return;
723
724    EDBG("ee=%p finished asynchronous render.", ee);
725
726    ee->in_async_render = EINA_FALSE;
727
728    _render_updates_process(ee, ev->updated_area);
729
730    if (ee->delayed.resize_shape)
731      {
732         _resize_shape_do(ee);
733         ee->delayed.resize_shape = EINA_FALSE;
734      }
735    if (ee->delayed.shaped_changed)
736      {
737         _shaped_do(ee, ee->delayed.shaped);
738         ee->delayed.shaped_changed = EINA_FALSE;
739      }
740    if (ee->delayed.alpha_changed)
741      {
742         _alpha_do(ee, ee->delayed.alpha);
743         ee->delayed.alpha_changed = EINA_FALSE;
744      }
745    if (ee->delayed.transparent_changed)
746      {
747         _transparent_do(ee, ee->delayed.transparent);
748         ee->delayed.transparent_changed = EINA_FALSE;
749      }
750    if (ee->delayed.avoid_damage != ee->prop.avoid_damage)
751      _avoid_damage_do(ee, ee->delayed.avoid_damage);
752    if (ee->delayed.rotation_changed)
753      {
754         _rotation_do(ee, ee->delayed.rotation, ee->delayed.rotation_resize);
755         ee->delayed.rotation_changed = EINA_FALSE;
756      }
757 }
758
759 static int
760 _ecore_evas_x_render(Ecore_Evas *ee)
761 {
762    int rend = 0;
763    Eina_List *ll;
764    Ecore_Evas *ee2;
765    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
766    static int render2 = -1;
767
768    if ((!ee->no_comp_sync) && (_ecore_evas_app_comp_sync) &&
769        (edata->sync_counter) && (!edata->sync_began) &&
770        (!edata->sync_cancel))
771      return 0;
772
773    if (ee->in_async_render)
774      {
775         EDBG("ee=%p is rendering asynchronously, skip.", ee);
776         return 0;
777      }
778
779    EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
780      {
781         if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
782         if (ee2->engine.func->fn_render)
783           rend |= ee2->engine.func->fn_render(ee2);
784         if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
785      }
786
787    if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
788    if (render2 == -1)
789      {
790         if (getenv("RENDER2")) render2 = 1;
791         else render2 = 0;
792      }
793    if (render2)
794      {
795         if (!ee->can_async_render)
796           {
797              Eina_List *updates = evas_render2_updates(ee->evas);
798              rend = _render_updates_process(ee, updates);
799              evas_render_updates_free(updates);
800           }
801         else
802           {
803              ee->in_async_render = EINA_TRUE;
804              if (evas_render2(ee->evas)) rend = 1;
805              else ee->in_async_render = EINA_FALSE;
806           }
807      }
808    else
809      {
810         if (!ee->can_async_render)
811           {
812              Eina_List *updates = evas_render_updates(ee->evas);
813              rend = _render_updates_process(ee, updates);
814              evas_render_updates_free(updates);
815           }
816         else if (evas_render_async(ee->evas))
817           {
818              EDBG("ee=%p started asynchronous render.", ee);
819              ee->in_async_render = EINA_TRUE;
820              rend = 1;
821           }
822         else if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
823      }
824    return rend;
825 }
826
827 static void
828 _resize_shape_do(Ecore_Evas *ee)
829 {
830 #ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
831    Evas_Engine_Info_Software_X11 *einfo;
832    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
833
834    einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
835    if (einfo)
836      {
837         unsigned int foreground;
838         Ecore_X_GC gc;
839
840         if (edata->mask) ecore_x_pixmap_free(edata->mask);
841         edata->mask = ecore_x_pixmap_new(ee->prop.window, ee->w, ee->h, 1);
842         foreground = 0;
843         gc = ecore_x_gc_new(edata->mask,
844                             ECORE_X_GC_VALUE_MASK_FOREGROUND,
845                             &foreground);
846         ecore_x_drawable_rectangle_fill(edata->mask, gc,
847                                         0, 0, ee->w, ee->h);
848         ecore_x_gc_free(gc);
849         einfo->info.mask = edata->mask;
850         if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
851           {
852              ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
853           }
854         evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
855      }
856 #endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */
857 }
858
859 static void
860 _ecore_evas_x_resize_shape(Ecore_Evas *ee)
861 {
862    if (!strcmp(ee->driver, "software_x11"))
863      {
864         if (ee->in_async_render)
865           {
866              ee->delayed.resize_shape = EINA_TRUE;
867              return;
868           }
869         _resize_shape_do(ee);
870      }
871 }
872
873 /* TODO: we need to make this work for all the states, not just sticky */
874 static Eina_Bool
875 _ecore_evas_x_event_property_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
876 {
877    Ecore_Evas *ee;
878    Ecore_X_Event_Window_Property *e;
879    Ecore_Evas_Engine_Data_X11 *edata;
880    int state_change = 0;
881
882    e = event;
883    ee = ecore_event_window_match(e->win);
884    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */
885    edata = ee->engine.data;
886    if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
887    if (e->atom == ECORE_X_ATOM_NET_WM_STATE)
888      {
889         unsigned int i, num;
890         Ecore_X_Window_State *state;
891         struct {
892            struct {
893               unsigned char modal : 1;
894               unsigned char sticky : 1;
895               unsigned char maximized_v : 1;
896               unsigned char maximized_h : 1;
897               unsigned char shaded : 1;
898               unsigned char skip_taskbar : 1;
899               unsigned char skip_pager : 1;
900               unsigned char fullscreen : 1;
901               unsigned char above : 1;
902               unsigned char below : 1;
903            } x;
904            struct {
905               Eina_Bool modal : 1;
906               Eina_Bool maximized : 1;
907               Eina_Bool sticky : 1;
908               Eina_Bool fullscreen : 1;
909               Eina_Bool focus_skip : 1;
910            } prop;
911         } prev;
912         
913         prev.x.modal = edata->state.modal;
914         prev.x.sticky = edata->state.sticky;
915         prev.x.maximized_v = edata->state.maximized_v;
916         prev.x.maximized_h = edata->state.maximized_h;
917         prev.x.shaded = edata->state.shaded;
918         prev.x.skip_taskbar = edata->state.skip_taskbar;
919         prev.x.skip_pager = edata->state.skip_pager;
920         prev.x.fullscreen = edata->state.fullscreen;
921         prev.x.above = edata->state.above;
922         prev.x.below = edata->state.below;
923         
924         prev.prop.modal = ee->prop.modal;
925         prev.prop.maximized = ee->prop.maximized;
926         prev.prop.sticky = ee->prop.sticky;
927         prev.prop.fullscreen = ee->prop.fullscreen;
928         prev.prop.focus_skip = ee->prop.focus_skip;
929
930         edata->state.modal        = 0;
931         edata->state.sticky       = 0;
932         edata->state.maximized_v  = 0;
933         edata->state.maximized_h  = 0;
934         edata->state.shaded       = 0;
935         edata->state.skip_taskbar = 0;
936         edata->state.skip_pager   = 0;
937         edata->state.fullscreen   = 0;
938         edata->state.above        = 0;
939         edata->state.below        = 0;
940
941         ee->prop.modal      = EINA_FALSE;
942         ee->prop.maximized  = EINA_FALSE;
943         ee->prop.sticky     = EINA_FALSE;
944         ee->prop.fullscreen = EINA_FALSE;
945 //        ee->prop.focus_skip = EINA_FALSE;
946         
947         ecore_x_netwm_window_state_get(e->win, &state, &num);
948         if (state)
949           {
950              for (i = 0; i < num; i++)
951                {
952                   switch (state[i])
953                     {
954                      case ECORE_X_WINDOW_STATE_MODAL:
955                        edata->state.modal = 1;
956                        ee->prop.modal = EINA_TRUE;
957                        break;
958                      case ECORE_X_WINDOW_STATE_STICKY:
959                        ee->prop.sticky = EINA_TRUE;
960                        edata->state.sticky = 1;
961                        break;
962                      case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
963                        edata->state.maximized_v = 1;
964                        ee->prop.maximized = EINA_TRUE;
965                        break;
966                      case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
967                        edata->state.maximized_h = 1;
968                        ee->prop.maximized = EINA_TRUE;
969                        break;
970                      case ECORE_X_WINDOW_STATE_SHADED:
971                        edata->state.shaded = 1;
972                        break;
973                      case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
974                        edata->state.skip_taskbar = 1;
975                        break;
976                      case ECORE_X_WINDOW_STATE_SKIP_PAGER:
977                        edata->state.skip_pager = 1;
978                        break;
979                      case ECORE_X_WINDOW_STATE_FULLSCREEN:
980                        ee->prop.fullscreen = 1;
981                        edata->state.fullscreen = 1;
982                        break;
983                      case ECORE_X_WINDOW_STATE_ABOVE:
984                        edata->state.above = 1;
985                        break;
986                      case ECORE_X_WINDOW_STATE_BELOW:
987                        edata->state.below = 1;
988                        break;
989                      default:
990                         break;
991                     }
992                }
993              free(state);
994           }
995         if (
996 //                 (prev.x.modal != edata->state.modal) ||
997             (prev.x.sticky != edata->state.sticky) ||
998             (prev.x.maximized_v != edata->state.maximized_v) ||
999             (prev.x.maximized_h != edata->state.maximized_h) ||
1000 //                 (prev.x.shaded != edata->state.shaded) ||
1001             (prev.x.skip_taskbar != edata->state.skip_taskbar) ||
1002             (prev.x.skip_pager != edata->state.skip_pager) ||
1003             (prev.x.fullscreen != edata->state.fullscreen) ||
1004 //                 (prev.x.above != edata->state.above) ||
1005 //                 (prev.x.below != edata->state.below) ||
1006 //                 (prev.prop.modal != ee->prop.modal) ||
1007             (prev.prop.maximized != ee->prop.maximized) ||
1008             (prev.prop.sticky != ee->prop.sticky) ||
1009             (prev.prop.fullscreen != ee->prop.fullscreen) ||
1010             (prev.prop.focus_skip != ee->prop.focus_skip))
1011           state_change = 1;
1012      }
1013    else if (e->atom == ECORE_X_ATOM_WM_STATE)
1014      {
1015         Ecore_X_Window_State_Hint state;
1016
1017         // handle WM_STATE changes
1018         state = ecore_x_icccm_state_get(e->win);
1019         switch (state)
1020           {
1021            case ECORE_X_WINDOW_STATE_HINT_WITHDRAWN:
1022              if ((!ee->prop.withdrawn) || (ee->prop.iconified))
1023                {
1024                   state_change = 1;
1025                   ee->prop.withdrawn = EINA_TRUE;
1026                   ee->prop.iconified = EINA_FALSE;
1027                }
1028              break;
1029            case ECORE_X_WINDOW_STATE_HINT_ICONIC:
1030              if ((!ee->prop.iconified) || (ee->prop.withdrawn))
1031                {
1032                   state_change = 1;
1033                   ee->prop.iconified = EINA_TRUE;
1034                   ee->prop.withdrawn = EINA_FALSE;
1035                }
1036              break;
1037            case ECORE_X_WINDOW_STATE_HINT_NORMAL:
1038              if ((ee->prop.iconified) || (ee->prop.withdrawn))
1039                {
1040                   state_change = 1;
1041                   ee->prop.iconified = EINA_FALSE;
1042                   ee->prop.withdrawn = EINA_FALSE;
1043                }
1044              break;
1045            default:
1046              break;
1047           }
1048      }
1049    if (state_change)
1050      {
1051         if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
1052      }
1053
1054    return ECORE_CALLBACK_PASS_ON;
1055 }
1056
1057 static Eina_Bool
1058 _ecore_evas_x_event_visibility_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1059 {
1060    Ecore_Evas *ee;
1061    Ecore_X_Event_Window_Visibility_Change *e;
1062    Ecore_Evas_Engine_Data_X11 *edata;
1063
1064    e = event;
1065    ee = ecore_event_window_match(e->win);
1066    if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1067    edata = ee->engine.data;
1068    if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1069 //   printf("VIS CHANGE OBSCURED: %p %i\n", ee, e->fully_obscured);
1070    if (e->fully_obscured)
1071      {
1072         /* FIXME: round trip */
1073         if (!ecore_x_screen_is_composited(edata->screen_num))
1074           ee->draw_ok = 0;
1075      }
1076    else
1077      ee->draw_ok = 1;
1078    return ECORE_CALLBACK_PASS_ON;
1079 }
1080
1081 static Eina_Bool
1082 _ecore_evas_x_event_client_message(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1083 {
1084    Ecore_Evas *ee;
1085    Ecore_X_Event_Client_Message *e;
1086    Ecore_Evas_Engine_Data_X11 *edata;
1087
1088    e = event;
1089    if (e->format != 32) return ECORE_CALLBACK_PASS_ON;
1090    if (e->message_type == ECORE_X_ATOM_E_COMP_SYNC_BEGIN)
1091      {
1092         ee = ecore_event_window_match(e->data.l[0]);
1093         if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1094         edata = ee->engine.data;
1095         if (e->data.l[0] != (long)ee->prop.window)
1096           return ECORE_CALLBACK_PASS_ON;
1097         if (!edata->sync_began)
1098           {
1099              // qeue a damage + draw. work around an event re-ordering thing.
1100              evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
1101           }
1102         edata->sync_began = 1;
1103         edata->sync_cancel = 0;
1104      }
1105    else if (e->message_type == ECORE_X_ATOM_E_COMP_SYNC_END)
1106      {
1107         ee = ecore_event_window_match(e->data.l[0]);
1108         if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1109         edata = ee->engine.data;
1110         if (e->data.l[0] != (long)ee->prop.window)
1111           return ECORE_CALLBACK_PASS_ON;
1112         edata->sync_began = 0;
1113         edata->sync_cancel = 0;
1114      }
1115    else if (e->message_type == ECORE_X_ATOM_E_COMP_SYNC_CANCEL)
1116      {
1117         ee = ecore_event_window_match(e->data.l[0]);
1118         if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1119         edata = ee->engine.data;
1120         if (e->data.l[0] != (long)ee->prop.window)
1121           return ECORE_CALLBACK_PASS_ON;
1122         edata->sync_began = 0;
1123         edata->sync_cancel = 1;
1124      }
1125    else if ((e->message_type == ECORE_X_ATOM_WM_PROTOCOLS) &&
1126             (e->data.l[0] == (int)ECORE_X_ATOM_NET_WM_SYNC_REQUEST))
1127      {
1128         ee = ecore_event_window_match(e->win);
1129         if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1130         edata = ee->engine.data;
1131         edata->netwm_sync_val_lo = (unsigned int)e->data.l[2];
1132         edata->netwm_sync_val_hi = (int)e->data.l[3];
1133         edata->netwm_sync_set = 1;
1134      }
1135    else if (e->message_type == ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE_REQUEST)
1136      {
1137         ee = ecore_event_window_match(e->win);
1138         if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1139         edata = ee->engine.data;
1140         if (ee->profile_supported)
1141           {
1142              char *p = ecore_x_atom_name_get(e->data.l[1]);
1143              if (p)
1144                {
1145                   _ecore_evas_window_profile_free(ee);
1146                   ee->prop.profile.name = (char *)eina_stringshare_add(p);
1147
1148                   /* window profiles of each sub_ecore_evas will be changed
1149                    * in fn_state_change callback.
1150                    */
1151                   if (ee->func.fn_state_change)
1152                     ee->func.fn_state_change(ee);
1153
1154                   edata->profile.done = 1;
1155                   free(p);
1156                }
1157           }
1158      }
1159    else if (e->message_type == ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL)
1160      {
1161         ///TODO after access structure determined
1162         // if (ee->func.fn_msg_handle)
1163         // ee->func.fn_msg_handle(ee, msg_domain, msg_id, data, size);
1164      }
1165    else if (e->message_type == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
1166      {
1167         ee = ecore_event_window_match(e->win);
1168         if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1169         if (e->data.l[1] != 0) //wm sends request message using value 0
1170           return ECORE_CALLBACK_PASS_ON;
1171
1172         if (ecore_evas_manual_render_get(ee))
1173           ecore_evas_manual_render(ee);
1174         //client sends reply message using value 1
1175         ecore_x_client_message32_send(e->win, ECORE_X_ATOM_E_DEICONIFY_APPROVE,
1176                                       ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
1177                                       e->win, 1,
1178                                       0, 0, 0);
1179      }
1180    else if (e->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE)
1181      {
1182         ee = ecore_event_window_match(e->data.l[0]);
1183         if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1184         edata = ee->engine.data;
1185         if (e->data.l[0] != (long)ee->prop.window)
1186           return ECORE_CALLBACK_PASS_ON;
1187         if (ee->prop.wm_rot.supported)
1188           {
1189              if (ee->prop.wm_rot.app_set)
1190                {
1191                   ee->prop.wm_rot.angle = (int)e->data.l[1];
1192                   ee->prop.wm_rot.win_resize = (int)e->data.l[2];
1193                   ee->prop.wm_rot.w = (int)e->data.l[3];
1194                   ee->prop.wm_rot.h = (int)e->data.l[4];
1195                   if ((ee->prop.wm_rot.win_resize) &&
1196                       ((ee->w != ee->prop.wm_rot.w) ||
1197                        (ee->h != ee->prop.wm_rot.h)))
1198                     edata->wm_rot.configure_coming = 1;
1199                   edata->wm_rot.prepare = 1;
1200                   edata->wm_rot.request = 0;
1201                   edata->wm_rot.done = 0;
1202                }
1203           }
1204      }
1205    else if (e->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST)
1206      {
1207         ee = ecore_event_window_match(e->data.l[0]);
1208         if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1209         edata = ee->engine.data;
1210         if (e->data.l[0] != (long)ee->prop.window)
1211           return ECORE_CALLBACK_PASS_ON;
1212         if (ee->prop.wm_rot.supported)
1213           {
1214              if (ee->prop.wm_rot.app_set)
1215                {
1216                   int angle = ee->prop.wm_rot.angle;
1217                   Eina_Bool resize = ee->prop.wm_rot.win_resize;
1218
1219                   edata->wm_rot.prepare = 0;
1220                   edata->wm_rot.request = 1;
1221                   edata->wm_rot.done = 0;
1222                   if (resize)
1223                     {
1224                        if ((ee->w == ee->prop.wm_rot.w) &&
1225                            (ee->h == ee->prop.wm_rot.h))
1226                          {
1227                             edata->wm_rot.configure_coming = 0;
1228                          }
1229                     }
1230                   if (!edata->wm_rot.configure_coming)
1231                     {
1232                        if (ee->prop.wm_rot.manual_mode.set)
1233                          {
1234                             ee->prop.wm_rot.manual_mode.wait_for_done = EINA_TRUE;
1235                             _ecore_evas_x_wm_rot_manual_rotation_done_timeout_update(ee);
1236                          }
1237                        _ecore_evas_x_rotation_set(ee, angle, (!resize));
1238                     }
1239                }
1240           }
1241      }
1242    else if (e->message_type == ECORE_X_ATOM_E_WINDOW_AUX_HINT_ALLOWED)
1243      {
1244         ee = ecore_event_window_match(e->win);
1245         if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1246
1247         int id = e->data.l[1]; /* id of aux hint */
1248         Eina_List *l;
1249         Ecore_Evas_Aux_Hint *aux;
1250         EINA_LIST_FOREACH(ee->prop.aux_hint.hints, l, aux)
1251           {
1252              if (id == aux->id)
1253                {
1254                   aux->allowed = 1;
1255                   if (!aux->notified)
1256                     {
1257                        if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
1258                        aux->notified = 1;
1259                     }
1260                   break;
1261                }
1262           }
1263      }
1264    return ECORE_CALLBACK_PASS_ON;
1265 }
1266
1267 static inline void
1268 _feed_cancel_out(const Ecore_X_Event_Mouse_Out *e, Eina_Bool cancel)
1269 {
1270    /* equivalent to:
1271     *  if (cancel) evas_event_feed_mouse_cancel(ee->evas, e->time, NULL);
1272     *  evas_event_feed_mouse_out(ee->evas, e->time, NULL);
1273     * but this goes through ecore_event_evas and direct eo event callback
1274     */
1275    if (cancel)
1276      {
1277         Ecore_Event_Mouse_Button ev = {
1278            .event_window = (Ecore_Window) e->win, /* not event_win */
1279            .modifiers = e->modifiers,
1280            .timestamp = e->time,
1281            .window = (Ecore_Window) e->win,
1282            .x = e->x,
1283            .y = e->y,
1284         };
1285         ecore_event_evas_mouse_button_cancel(NULL, ECORE_EVENT_MOUSE_BUTTON_CANCEL, &ev);
1286      }
1287
1288    Ecore_Event_Mouse_IO io = {
1289       .event_window = (Ecore_Window) e->win, /* not event_win */
1290       .modifiers = e->modifiers,
1291       .timestamp = e->time,
1292       .window = (Ecore_Window) e->win,
1293       .x = e->x,
1294       .y = e->y
1295    };
1296    ecore_event_evas_mouse_out(NULL, ECORE_EVENT_MOUSE_OUT, &io);
1297 }
1298
1299 static Eina_Bool
1300 _fake_out(void *data)
1301 {
1302    Ecore_Evas *ee = data;
1303    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
1304    Ecore_X_Event_Mouse_Out *e = &(edata->out_ev);
1305
1306    edata->outdelay = NULL;
1307
1308    ecore_event_evas_modifier_lock_update(ee->evas, e->modifiers);
1309    _ecore_evas_mouse_move_process(ee, e->x, e->y, e->time);
1310    _feed_cancel_out(e, (e->mode == ECORE_X_EVENT_MODE_GRAB));
1311
1312    if (ee->func.fn_mouse_out) ee->func.fn_mouse_out(ee);
1313    if (ee->prop.cursor.object) evas_object_hide(ee->prop.cursor.object);
1314    ee->in = EINA_FALSE;
1315    return EINA_FALSE;
1316 }
1317
1318 static Eina_Bool
1319 _ecore_evas_x_event_mouse_in(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1320 {
1321    Ecore_Evas *ee;
1322    Ecore_X_Event_Mouse_In *e;
1323    Ecore_Evas_Engine_Data_X11 *edata;
1324
1325    e = event;
1326    ee = ecore_event_window_match(e->win);
1327    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1328    if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1329    edata = ee->engine.data;
1330 /*   
1331     {
1332        time_t t;
1333        char *ct;
1334
1335        const char *modes[] = {
1336         "MODE_NORMAL",
1337         "MODE_WHILE_GRABBED",
1338         "MODE_GRAB",
1339         "MODE_UNGRAB"
1340        };
1341        const char *details[] = {
1342         "DETAIL_ANCESTOR",
1343         "DETAIL_VIRTUAL",
1344         "DETAIL_INFERIOR",
1345         "DETAIL_NON_LINEAR",
1346         "DETAIL_NON_LINEAR_VIRTUAL",
1347         "DETAIL_POINTER",
1348         "DETAIL_POINTER_ROOT",
1349         "DETAIL_DETAIL_NONE"
1350        };
1351        t = time(NULL);
1352        ct = ctime(&t);
1353        ct[strlen(ct) - 1] = 0;
1354        printf("@@ ->IN 0x%x 0x%x %s md=%s dt=%s\n",
1355              e->win, e->event_win,
1356              ct,
1357              modes[e->mode],
1358              details[e->detail]);
1359     }
1360  */
1361    // disable. causes more problems than it fixes
1362    //   if ((e->mode == ECORE_X_EVENT_MODE_GRAB) ||
1363    //       (e->mode == ECORE_X_EVENT_MODE_UNGRAB))
1364    //     return 0;
1365
1366    // handle click to focus passive buton grab side-effects
1367    if ((e->mode == ECORE_X_EVENT_MODE_UNGRAB) &&
1368        (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR) &&
1369        (edata->outdelay))
1370      {
1371         ecore_timer_del(edata->outdelay);
1372         edata->outdelay = NULL;
1373         return 0;
1374      }
1375    if (edata->outdelay)
1376      {
1377         ecore_timer_del(edata->outdelay);
1378         edata->outdelay = NULL;
1379         _fake_out(ee);
1380      }
1381    
1382    /* if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0; */
1383    if (!ee->in)
1384      {
1385         Ecore_Event_Mouse_IO io = {
1386            .event_window = (Ecore_Window) e->win, /* not event_win! */
1387            .modifiers = e->modifiers,
1388            .timestamp = e->time,
1389            .window = (Ecore_Window) e->win,
1390            .x = e->x,
1391            .y = e->y
1392         };
1393
1394         if (ee->func.fn_mouse_in) ee->func.fn_mouse_in(ee);
1395         ecore_event_evas_mouse_in(NULL, ECORE_EVENT_MOUSE_IN, &io);
1396         ee->in = EINA_TRUE;
1397      }
1398    return ECORE_CALLBACK_PASS_ON;
1399 }
1400
1401 static Eina_Bool
1402 _ecore_evas_x_event_mouse_out(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1403 {
1404    Ecore_Evas *ee;
1405    Ecore_X_Event_Mouse_Out *e;
1406    Ecore_Evas_Engine_Data_X11 *edata;
1407
1408    e = event;
1409    ee = ecore_event_window_match(e->win);
1410    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
1411    /* pass on event */
1412    if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1413    edata = ee->engine.data;
1414 /*
1415     {
1416        time_t t;
1417        char *ct;
1418
1419        const char *modes[] = {
1420         "MODE_NORMAL",
1421         "MODE_WHILE_GRABBED",
1422         "MODE_GRAB",
1423         "MODE_UNGRAB"
1424        };
1425        const char *details[] = {
1426         "DETAIL_ANCESTOR",
1427         "DETAIL_VIRTUAL",
1428         "DETAIL_INFERIOR",
1429         "DETAIL_NON_LINEAR",
1430         "DETAIL_NON_LINEAR_VIRTUAL",
1431         "DETAIL_POINTER",
1432         "DETAIL_POINTER_ROOT",
1433         "DETAIL_DETAIL_NONE"
1434        };
1435        t = time(NULL);
1436        ct = ctime(&t);
1437        ct[strlen(ct) - 1] = 0;
1438        printf("@@ ->OUT 0x%x 0x%x %s md=%s dt=%s\n",
1439              e->win, e->event_win,
1440              ct,
1441              modes[e->mode],
1442              details[e->detail]);
1443     }
1444  */
1445    // disable. causes more problems than it fixes
1446    //   if ((e->mode == ECORE_X_EVENT_MODE_GRAB) ||
1447    //       (e->mode == ECORE_X_EVENT_MODE_UNGRAB))
1448    //     return 0;
1449
1450    // click to focus mouse out+in work-around
1451    if ((e->mode == ECORE_X_EVENT_MODE_GRAB) &&
1452        (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR))
1453      {
1454         // defer out handling in case its a "fake" out thanks to click
1455         // to focus (which gets us another out soon after
1456         if (edata->outdelay) ecore_timer_del(edata->outdelay);
1457         edata->out_ev = *e;
1458         edata->outdelay = ecore_timer_add(0.05, _fake_out, ee);
1459         return 0;
1460      }
1461    if (edata->outdelay)
1462      {
1463         ecore_timer_del(edata->outdelay);
1464         edata->outdelay = NULL;
1465      }
1466    
1467 //   if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0;
1468 //   printf("OUT: ee->in=%i, e->mode=%i, e->detail=%i, dount_count=%i\n",
1469 //          ee->in, e->mode, e->detail, evas_event_down_count_get(ee->evas));
1470    if (ee->in)
1471      {
1472         if ((evas_event_down_count_get(ee->evas) > 0) &&
1473             (!((e->mode == ECORE_X_EVENT_MODE_GRAB) &&
1474                (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR))))
1475           return ECORE_CALLBACK_PASS_ON;
1476         ecore_event_evas_modifier_lock_update(ee->evas, e->modifiers);
1477         _ecore_evas_mouse_move_process(ee, e->x, e->y, e->time);
1478         _feed_cancel_out(e, (e->mode == ECORE_X_EVENT_MODE_GRAB));
1479         if (ee->func.fn_mouse_out) ee->func.fn_mouse_out(ee);
1480         if (ee->prop.cursor.object) evas_object_hide(ee->prop.cursor.object);
1481         ee->in = EINA_FALSE;
1482      }
1483    return ECORE_CALLBACK_PASS_ON;
1484 }
1485
1486 static Eina_Bool
1487 _ecore_evas_x_event_window_focus_in(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1488 {
1489    Ecore_Evas *ee;
1490    Ecore_X_Event_Window_Focus_In *e;
1491
1492    e = event;
1493    ee = ecore_event_window_match(e->win);
1494    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1495    if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1496 //xx// filtering with these doesnt help   
1497 //xx//   if (e->mode == ECORE_X_EVENT_MODE_UNGRAB) return ECORE_CALLBACK_PASS_ON;
1498    ee->prop.focused = EINA_TRUE;
1499    evas_focus_in(ee->evas);
1500    if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
1501    return ECORE_CALLBACK_PASS_ON;
1502 }
1503
1504 static Eina_Bool
1505 _ecore_evas_x_event_window_focus_out(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1506 {
1507    Ecore_Evas *ee;
1508    Ecore_X_Event_Window_Focus_Out *e;
1509
1510    e = event;
1511    ee = ecore_event_window_match(e->win);
1512    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1513    if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1514 //xx// filtering with these doesnt help   
1515 //xx//   if (e->mode == ECORE_X_EVENT_MODE_GRAB) return ECORE_CALLBACK_PASS_ON;
1516
1517 //   if (ee->prop.fullscreen)
1518 //     ecore_x_window_focus(ee->prop.window);
1519    evas_focus_out(ee->evas);
1520    ee->prop.focused = EINA_FALSE;
1521    if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
1522    return ECORE_CALLBACK_PASS_ON;
1523 }
1524
1525 static Eina_Bool
1526 _ecore_evas_x_event_window_damage(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1527 {
1528    Ecore_Evas *ee;
1529    Ecore_X_Event_Window_Damage *e;
1530    Ecore_Evas_Engine_Data_X11 *edata;
1531
1532    e = event;
1533    ee = ecore_event_window_match(e->win);
1534    if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1535    edata = ee->engine.data;
1536    if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1537    if (edata->using_bg_pixmap) return ECORE_CALLBACK_PASS_ON;
1538 //   printf("EXPOSE %p [%i] %i %i %ix%i\n", ee, ee->prop.avoid_damage, e->x, e->y, e->w, e->h);
1539    if (ee->prop.avoid_damage)
1540      {
1541         Ecore_X_Rectangle rect;
1542         Ecore_X_XRegion *tmpr;
1543
1544         if (!edata->damages)
1545           edata->damages = ecore_x_xregion_new();
1546         tmpr = ecore_x_xregion_new();
1547         rect.x = e->x;
1548         rect.y = e->y;
1549         rect.width = e->w;
1550         rect.height = e->h;
1551         ecore_x_xregion_union_rect(tmpr, edata->damages, &rect);
1552         ecore_x_xregion_free(edata->damages);
1553         edata->damages = tmpr;
1554 /* no - this breaks things badly. disable. Ecore_X_Rectangle != XRectangle - see
1555  *  the typedefs in x's headers and ecore_x's. also same with Region - it's a pointer in x - not an X ID
1556         Ecore_X_Rectangle rect;
1557         Ecore_X_XRegion  *tmpr;
1558
1559         if (!edata->damages) edata->damages = ecore_x_xregion_new();
1560         tmpr = ecore_x_xregion_new();
1561         rect.x = e->x;
1562         rect.y = e->y;
1563         rect.width = e->w;
1564         rect.height = e->h;
1565         ecore_x_xregion_union_rect(tmpr, edata->damages, &rect);
1566         ecore_x_xregion_free(edata->damages);
1567         edata->damages = tmpr;
1568  */
1569      }
1570    else
1571      {
1572         if (ee->rotation == 0)
1573           evas_damage_rectangle_add(ee->evas, e->x, e->y, e->w, e->h);
1574         else if (ee->rotation == 90)
1575           evas_damage_rectangle_add(ee->evas,
1576                                     ee->h - e->y - e->h, e->x, e->h, e->w);
1577         else if (ee->rotation == 180)
1578           evas_damage_rectangle_add(ee->evas, ee->w - e->x - e->w,
1579                                     ee->h - e->y - e->h, e->w, e->h);
1580         else if (ee->rotation == 270)
1581           evas_damage_rectangle_add(ee->evas, e->y, ee->w - e->x - e->w,
1582                                     e->h, e->w);
1583      }
1584    return ECORE_CALLBACK_PASS_ON;
1585 }
1586
1587 static Eina_Bool
1588 _ecore_evas_x_event_window_destroy(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1589 {
1590    Ecore_Evas *ee;
1591    Ecore_X_Event_Window_Destroy *e;
1592    Ecore_Evas_Engine_Data_X11 *edata;
1593
1594    e = event;
1595    ee = ecore_event_window_match(e->win);
1596    if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1597    if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1598    edata = ee->engine.data;
1599    if (ee->func.fn_destroy) ee->func.fn_destroy(ee);
1600    edata->destroyed = 1;
1601    _ecore_evas_x_sync_clear(ee);
1602    ecore_evas_free(ee);
1603    return ECORE_CALLBACK_PASS_ON;
1604 }
1605
1606 static Eina_Bool
1607 _ecore_evas_x_event_window_configure(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1608 {
1609    Ecore_Evas *ee;
1610    Ecore_X_Event_Window_Configure *e;
1611    Ecore_Evas_Engine_Data_X11 *edata;
1612
1613    e = event;
1614    ee = ecore_event_window_match(e->win);
1615    if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1616    edata = ee->engine.data;
1617    if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1618    if (edata->direct_resize) return ECORE_CALLBACK_PASS_ON;
1619
1620    if (edata->configure_reqs > 0) edata->configure_reqs--;
1621
1622    edata->configure_coming = 0;
1623    if ((e->from_wm) || (ee->prop.override))
1624      {
1625         if ((ee->x != e->x) || (ee->y != e->y))
1626           {
1627              ee->x = e->x;
1628              ee->y = e->y;
1629              ee->req.x = ee->x;
1630              ee->req.y = ee->y;
1631              if (ee->func.fn_move) ee->func.fn_move(ee);
1632           }
1633      }
1634    if ((ee->w != e->w) || (ee->h != e->h) ||
1635        (ee->req.w != e->w) || (ee->req.h != e->h))
1636      {
1637         ee->w = e->w;
1638         ee->h = e->h;
1639         if (edata->configure_reqs == 0)
1640           {
1641              ee->req.w = ee->w;
1642              ee->req.h = ee->h;
1643           }
1644         if (ECORE_EVAS_PORTRAIT(ee))
1645           {
1646              evas_output_size_set(ee->evas, ee->w, ee->h);
1647              evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
1648           }
1649         else
1650           {
1651              evas_output_size_set(ee->evas, ee->h, ee->w);
1652              evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
1653           }
1654         if (ee->prop.avoid_damage)
1655           {
1656              int pdam;
1657
1658              pdam = ecore_evas_avoid_damage_get(ee);
1659              ecore_evas_avoid_damage_set(ee, 0);
1660              ecore_evas_avoid_damage_set(ee, pdam);
1661           }
1662         if ((ee->shaped) || (ee->alpha))
1663           _ecore_evas_x_resize_shape(ee);
1664         if ((ee->expecting_resize.w > 0) && (ee->expecting_resize.h > 0))
1665           {
1666              if ((ee->expecting_resize.w == ee->w) &&
1667                  (ee->expecting_resize.h == ee->h))
1668                _ecore_evas_mouse_move_process(ee, ee->mouse.x, ee->mouse.y,
1669                                               ecore_x_current_time_get());
1670              ee->expecting_resize.w = 0;
1671              ee->expecting_resize.h = 0;
1672           }
1673         if (ee->func.fn_resize) ee->func.fn_resize(ee);
1674
1675         if (ee->prop.wm_rot.supported)
1676           {
1677              if (edata->wm_rot.prepare)
1678                {
1679                   if ((ee->prop.wm_rot.w == e->w) &&
1680                       (ee->prop.wm_rot.h == e->h))
1681                     {
1682                        ee->prop.wm_rot.win_resize = 0;
1683                        edata->wm_rot.configure_coming = 0;
1684                     }
1685                }
1686              else if (edata->wm_rot.request)
1687                {
1688                   if ((edata->wm_rot.configure_coming) &&
1689                       (ee->prop.wm_rot.w == e->w) &&
1690                       (ee->prop.wm_rot.h == e->h))
1691                     {
1692                        edata->wm_rot.configure_coming = 0;
1693                        if (ee->prop.wm_rot.manual_mode.set)
1694                          {
1695                             ee->prop.wm_rot.manual_mode.wait_for_done = EINA_TRUE;
1696                             _ecore_evas_x_wm_rot_manual_rotation_done_timeout_update(ee);
1697                          }
1698                        _ecore_evas_x_rotation_set(ee,
1699                                                   ee->prop.wm_rot.angle,
1700                                                   EINA_TRUE);
1701                     }
1702                }
1703           }
1704      }
1705    return ECORE_CALLBACK_PASS_ON;
1706 }
1707
1708 static Eina_Bool
1709 _ecore_evas_x_event_window_delete_request(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1710 {
1711    Ecore_Evas *ee;
1712    Ecore_X_Event_Window_Delete_Request *e;
1713
1714    e = event;
1715    ee = ecore_event_window_match(e->win);
1716    if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1717    if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1718    if (ee->func.fn_delete_request) ee->func.fn_delete_request(ee);
1719    return ECORE_CALLBACK_PASS_ON;
1720 }
1721
1722 static Eina_Bool
1723 _ecore_evas_x_event_window_show(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1724 {
1725    Ecore_Evas *ee;
1726    Ecore_X_Event_Window_Show *e;
1727    static int first_map_bug = -1;
1728
1729    e = event;
1730    ee = ecore_event_window_match(e->win);
1731    if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1732    if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1733
1734    if (ee->gl_sync_draw_done < 0)
1735      {
1736         char *sync = getenv("ECORE_EVAS_GL_SYNC_DRAW_DONE");
1737         if (sync && (atoi(sync) == 1))
1738           ee->gl_sync_draw_done = 1;
1739         else
1740           ee->gl_sync_draw_done = 0;
1741      }
1742
1743    if (first_map_bug < 0)
1744      {
1745         char *bug = NULL;
1746
1747         if ((bug = getenv("ECORE_EVAS_GL_FIRST_MAP_BUG")))
1748           first_map_bug = atoi(bug);
1749         else
1750           first_map_bug = 0;
1751      }
1752    if ((first_map_bug) && (!strcmp(ee->driver, "opengl_x11")))
1753      evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
1754    if (ee->visible) return ECORE_CALLBACK_PASS_ON;
1755 //   if (ee->visible) return ECORE_CALLBACK_DONE;
1756 //   printf("SHOW EVENT %p\n", ee);
1757    ee->visible = 1;
1758    if (ee->func.fn_show) ee->func.fn_show(ee);
1759    return ECORE_CALLBACK_PASS_ON;
1760 }
1761
1762 static Eina_Bool
1763 _ecore_evas_x_event_window_hide(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1764 {
1765    Ecore_Evas *ee;
1766    Ecore_X_Event_Window_Hide *e;
1767
1768    e = event;
1769    ee = ecore_event_window_match(e->win);
1770    if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1771    if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1772    if (ee->in)
1773      {
1774         Ecore_X_Event_Mouse_Out out = {
1775            .event_win = e->event_win,
1776            .modifiers = 0,
1777            .time = e->time,
1778            .win = e->win,
1779            .x = 0,
1780            .y = 0,
1781         };
1782         _feed_cancel_out(&out, EINA_TRUE);
1783         if (ee->func.fn_mouse_out) ee->func.fn_mouse_out(ee);
1784         if (ee->prop.cursor.object) evas_object_hide(ee->prop.cursor.object);
1785         ee->in = EINA_FALSE;
1786      }
1787    if (ee->prop.override)
1788      {
1789         ee->prop.withdrawn = EINA_TRUE;
1790         if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
1791      }
1792    if (!ee->visible) return ECORE_CALLBACK_PASS_ON;
1793 //   if (!ee->visible) return ECORE_CALLBACK_DONE;
1794 //   printf("HIDE EVENT %p\n", ee);
1795    ee->visible = 0;
1796    if (ee->func.fn_hide) ee->func.fn_hide(ee);
1797    return ECORE_CALLBACK_PASS_ON;
1798 }
1799
1800 /* FIXME, should be in idler */
1801 /* FIXME, round trip */
1802 static void
1803 _ecore_evas_x_size_pos_hints_update(Ecore_Evas *ee)
1804 {
1805    ecore_x_icccm_size_pos_hints_set(ee->prop.window,
1806                                     ee->prop.request_pos /*request_pos */,
1807                                     ECORE_X_GRAVITY_NW /* gravity */,
1808                                     ee->prop.min.w /* min_w */,
1809                                     ee->prop.min.h /* min_h */,
1810                                     ee->prop.max.w /* max_w */,
1811                                     ee->prop.max.h /* max_h */,
1812                                     ee->prop.base.w /* base_w */,
1813                                     ee->prop.base.h /* base_h */,
1814                                     ee->prop.step.w /* step_x */,
1815                                     ee->prop.step.h /* step_y */,
1816                                     ee->prop.aspect /* min_aspect */,
1817                                     ee->prop.aspect /* max_aspect */);
1818 }
1819
1820 /* FIXME, should be in idler */
1821 static void
1822 _ecore_evas_x_state_update(Ecore_Evas *ee)
1823 {
1824    Ecore_X_Window_State state[10];
1825    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
1826    int num = 0;
1827
1828    if (ee->prop.modal)
1829      state[num++] = ECORE_X_WINDOW_STATE_MODAL;
1830    if (ee->prop.sticky)
1831      state[num++] = ECORE_X_WINDOW_STATE_STICKY;
1832    if (ee->prop.maximized)
1833      state[num++] = ECORE_X_WINDOW_STATE_MAXIMIZED_VERT;
1834    if (ee->prop.maximized)
1835      state[num++] = ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ;
1836 //   if (bd->client.netwm.state.shaded)
1837 //     state[num++] = ECORE_X_WINDOW_STATE_SHADED;
1838    if (ee->prop.focus_skip)
1839      state[num++] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
1840    if (ee->prop.focus_skip)
1841      state[num++] = ECORE_X_WINDOW_STATE_SKIP_PAGER;
1842 //   if (bd->client.netwm.state.hidden)
1843 //     state[num++] = ECORE_X_WINDOW_STATE_HIDDEN;
1844    if (edata->state.fullscreen)
1845      state[num++] = ECORE_X_WINDOW_STATE_FULLSCREEN;
1846    if (edata->state.above)
1847      state[num++] = ECORE_X_WINDOW_STATE_ABOVE;
1848    if (edata->state.below)
1849      state[num++] = ECORE_X_WINDOW_STATE_BELOW;
1850    if (ee->prop.demand_attention)
1851      state[num++] = ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION;
1852
1853    ecore_x_netwm_window_state_set(ee->prop.window, state, num);
1854 }
1855
1856 static void
1857 _ecore_evas_x_layer_update(Ecore_Evas *ee)
1858 {
1859    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
1860
1861    if (ee->should_be_visible)
1862      {
1863         /* We need to send a netwm request to the wm */
1864         /* FIXME: Do we have to remove old state before adding new? */
1865         if (ee->prop.layer < 3)
1866           {
1867              if (edata->state.above)
1868                {
1869                   edata->state.above = 0;
1870                   ecore_x_netwm_state_request_send(ee->prop.window,
1871                                                    edata->win_root,
1872                                                    ECORE_X_WINDOW_STATE_ABOVE, -1, 0);
1873                }
1874              if (!edata->state.below)
1875                {
1876                   edata->state.below = 1;
1877                   ecore_x_netwm_state_request_send(ee->prop.window,
1878                                                    edata->win_root,
1879                                                    ECORE_X_WINDOW_STATE_BELOW, -1, 1);
1880                }
1881           }
1882         else if (ee->prop.layer > 5)
1883           {
1884              if (edata->state.below)
1885                {
1886                   edata->state.below = 0;
1887                   ecore_x_netwm_state_request_send(ee->prop.window,
1888                                                    edata->win_root,
1889                                                    ECORE_X_WINDOW_STATE_BELOW, -1, 0);
1890                }
1891              if (!edata->state.above)
1892                {
1893                   edata->state.above = 1;
1894                   ecore_x_netwm_state_request_send(ee->prop.window,
1895                                                    edata->win_root,
1896                                                    ECORE_X_WINDOW_STATE_ABOVE, -1, 1);
1897                }
1898           }
1899         else
1900           {
1901              if (edata->state.below)
1902                {
1903                   edata->state.below = 0;
1904                   ecore_x_netwm_state_request_send(ee->prop.window,
1905                                                    edata->win_root,
1906                                                    ECORE_X_WINDOW_STATE_BELOW, -1, 0);
1907                }
1908              if (edata->state.above)
1909                {
1910                   edata->state.above = 0;
1911                   ecore_x_netwm_state_request_send(ee->prop.window,
1912                                                    edata->win_root,
1913                                                    ECORE_X_WINDOW_STATE_ABOVE, -1, 0);
1914                }
1915           }
1916      }
1917    else
1918      {
1919         /* Just set the state */
1920         if (ee->prop.layer < 3)
1921           {
1922              if ((edata->state.above) || (!edata->state.below))
1923                {
1924                   edata->state.above = 0;
1925                   edata->state.below = 1;
1926                   _ecore_evas_x_state_update(ee);
1927                }
1928           }
1929         else if (ee->prop.layer > 5)
1930           {
1931              if ((!edata->state.above) || (edata->state.below))
1932                {
1933                   edata->state.above = 1;
1934                   edata->state.below = 0;
1935                   _ecore_evas_x_state_update(ee);
1936                }
1937           }
1938         else
1939           {
1940              if ((edata->state.above) || (edata->state.below))
1941                {
1942                   edata->state.above = 0;
1943                   edata->state.below = 0;
1944                   _ecore_evas_x_state_update(ee);
1945                }
1946           }
1947      }
1948    /* FIXME: Set gnome layer */
1949 }
1950
1951 static int
1952 _ecore_evas_x_init(void)
1953 {
1954    _ecore_evas_init_count++;
1955    if (_ecore_evas_init_count > 1) return _ecore_evas_init_count;
1956    ecore_evas_event_handlers[0] =
1957      ecore_event_handler_add(ECORE_X_EVENT_MOUSE_IN,
1958                              _ecore_evas_x_event_mouse_in, NULL);
1959    ecore_evas_event_handlers[1] =
1960      ecore_event_handler_add(ECORE_X_EVENT_MOUSE_OUT,
1961                              _ecore_evas_x_event_mouse_out, NULL);
1962    ecore_evas_event_handlers[2] =
1963      ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_IN,
1964                              _ecore_evas_x_event_window_focus_in, NULL);
1965    ecore_evas_event_handlers[3] =
1966      ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT,
1967                              _ecore_evas_x_event_window_focus_out, NULL);
1968    ecore_evas_event_handlers[4] =
1969      ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DAMAGE,
1970                              _ecore_evas_x_event_window_damage, NULL);
1971    ecore_evas_event_handlers[5] =
1972      ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY,
1973                              _ecore_evas_x_event_window_destroy, NULL);
1974    ecore_evas_event_handlers[6] =
1975      ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE,
1976                              _ecore_evas_x_event_window_configure, NULL);
1977    ecore_evas_event_handlers[7] =
1978      ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DELETE_REQUEST,
1979                              _ecore_evas_x_event_window_delete_request, NULL);
1980    ecore_evas_event_handlers[8] =
1981      ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW,
1982                              _ecore_evas_x_event_window_show, NULL);
1983    ecore_evas_event_handlers[9] =
1984      ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE,
1985                              _ecore_evas_x_event_window_hide, NULL);
1986    ecore_evas_event_handlers[10] =
1987      ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY,
1988                              _ecore_evas_x_event_property_change, NULL);
1989    ecore_evas_event_handlers[11] =
1990      ecore_event_handler_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE,
1991                              _ecore_evas_x_event_visibility_change, NULL);
1992    ecore_evas_event_handlers[12] =
1993      ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
1994                              _ecore_evas_x_event_client_message, NULL);
1995    ecore_event_evas_init();
1996    return _ecore_evas_init_count;
1997 }
1998
1999 int
2000 _ecore_evas_x_shutdown(void)
2001 {
2002    _ecore_evas_init_count--;
2003    if (_ecore_evas_init_count == 0)
2004      {
2005         unsigned int i;
2006
2007         for (i = 0; i < sizeof(ecore_evas_event_handlers) / sizeof(Ecore_Event_Handler*); i++)
2008           {
2009              if (ecore_evas_event_handlers[i])
2010                ecore_event_handler_del(ecore_evas_event_handlers[i]);
2011           }
2012         ecore_event_evas_shutdown();
2013      }
2014    if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
2015    return _ecore_evas_init_count;
2016 }
2017
2018 static void
2019 _ecore_evas_x_free(Ecore_Evas *ee)
2020 {
2021    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2022
2023    if (edata->pixmap.back)
2024      ecore_x_pixmap_free(edata->pixmap.back);
2025    if (edata->pixmap.front)
2026      ecore_x_pixmap_free(edata->pixmap.front);
2027    if (edata->wm_rot.manual_mode_job)
2028      {
2029         ecore_job_del(edata->wm_rot.manual_mode_job);
2030         edata->wm_rot.manual_mode_job = NULL;
2031      }
2032
2033    _ecore_evas_x_group_leader_unset(ee);
2034    if (edata->sync_counter)
2035      ecore_x_sync_counter_free(edata->sync_counter);
2036    if (edata->netwm_sync_counter)
2037      ecore_x_sync_counter_free(edata->netwm_sync_counter);
2038    if (edata->win_shaped_input)
2039      ecore_x_window_free(edata->win_shaped_input);
2040    ecore_event_window_unregister(ee->prop.window);
2041    if (ee->prop.window && (!edata->destroyed)) ecore_x_window_free(ee->prop.window);
2042    if (edata->pmap) ecore_x_pixmap_free(edata->pmap);
2043    if (edata->mask) ecore_x_pixmap_free(edata->mask);
2044    if (edata->gc) ecore_x_gc_free(edata->gc);
2045    if (edata->damages) ecore_x_xregion_free(edata->damages);
2046    edata->pmap = 0;
2047    edata->mask = 0;
2048    edata->gc = 0;
2049    edata->damages = NULL;
2050    while (edata->win_extra)
2051      {
2052         Ecore_X_Window *winp;
2053
2054         winp = edata->win_extra->data;
2055         edata->win_extra =
2056           eina_list_remove_list(edata->win_extra, edata->win_extra);
2057         ecore_event_window_unregister(*winp);
2058         free(winp);
2059      }
2060    if (edata->outdelay)
2061      {
2062         ecore_timer_del(edata->outdelay);
2063         edata->outdelay = NULL;
2064      }
2065
2066    free(edata);
2067    _ecore_evas_x_shutdown();
2068    ecore_x_shutdown();
2069 }
2070
2071 static void
2072 _ecore_evas_x_callback_delete_request_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
2073 {
2074    ee->func.fn_delete_request = func;
2075    _ecore_evas_x_protocols_set(ee);
2076    _ecore_evas_x_sync_set(ee);
2077 }
2078
2079 static void
2080 _ecore_evas_x_move(Ecore_Evas *ee, int x, int y)
2081 {
2082    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2083    Eina_Bool changed = EINA_FALSE;
2084
2085    if ((ee->req.x != x) || (ee->req.y != y))
2086      {
2087         changed = EINA_TRUE;
2088         ee->req.x = x;
2089         ee->req.y = y;
2090      }
2091
2092    if (edata->direct_resize)
2093      {
2094         if (!edata->managed)
2095           {
2096              if ((x != ee->x) || (y != ee->y))
2097                {
2098                   ee->x = x;
2099                   ee->y = y;
2100                   if (changed) edata->configure_reqs++;
2101                   ecore_x_window_move(ee->prop.window, x, y);
2102                   if (!ee->should_be_visible)
2103                     {
2104                        /* We need to request pos */
2105                        ee->prop.request_pos = EINA_TRUE;
2106                        _ecore_evas_x_size_pos_hints_update(ee);
2107                     }
2108                   if (ee->func.fn_move) ee->func.fn_move(ee);
2109                }
2110           }
2111      }
2112    else
2113      {
2114         if (((ee->x != x) || (ee->y != y)) ||
2115             (edata->configure_coming))
2116           {
2117              edata->configure_coming = 1;
2118              if (!edata->managed)
2119                {
2120                   ee->x = x;
2121                   ee->y = y;
2122                }
2123              if (changed) edata->configure_reqs++;
2124              ecore_x_window_move(ee->prop.window, x, y);
2125           }
2126         if (!ee->should_be_visible)
2127           {
2128              /* We need to request pos */
2129              ee->prop.request_pos = EINA_TRUE;
2130              _ecore_evas_x_size_pos_hints_update(ee);
2131           }
2132      }
2133 }
2134
2135 static void
2136 _ecore_evas_x_managed_move(Ecore_Evas *ee, int x, int y)
2137 {
2138    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2139
2140    ee->req.x = x;
2141    ee->req.y = y;
2142    if (edata->direct_resize)
2143      {
2144         edata->managed = 1;
2145         if ((x != ee->x) || (y != ee->y))
2146           {
2147              ee->x = x;
2148              ee->y = y;
2149              if (ee->func.fn_move) ee->func.fn_move(ee);
2150           }
2151      }
2152 }
2153
2154 static void
2155 _ecore_evas_x_resize(Ecore_Evas *ee, int w, int h)
2156 {
2157    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2158    Eina_Bool changed = EINA_FALSE;
2159
2160    if ((ee->req.w != w) || (ee->req.h != h))
2161      {
2162         changed = EINA_TRUE;
2163         ee->req.w = w;
2164         ee->req.h = h;
2165      }
2166
2167    /* check for valid property window
2168     * 
2169     * NB: If we do not have one, check for valid pixmap rendering */
2170    if (!ee->prop.window)
2171      {
2172         /* the ecore_evas was resized. we need to free the back pixmap */
2173         if ((edata->pixmap.w != w) || (edata->pixmap.h != h))
2174           {
2175              /* free the backing pixmap */
2176              if (edata->pixmap.back) 
2177                ecore_x_pixmap_free(edata->pixmap.back);
2178           }
2179      }
2180
2181    if (edata->direct_resize)
2182      {
2183         if ((ee->w == w) && (ee->h == h)) return;
2184
2185         ee->w = w;
2186         ee->h = h;
2187         if (changed) edata->configure_reqs++;
2188         if (ee->prop.window) ecore_x_window_resize(ee->prop.window, w, h);
2189         if (ECORE_EVAS_PORTRAIT(ee))
2190           {
2191              evas_output_size_set(ee->evas, ee->w, ee->h);
2192              evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
2193           }
2194         else
2195           {
2196              evas_output_size_set(ee->evas, ee->h, ee->w);
2197              evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
2198           }
2199         if (ee->prop.avoid_damage)
2200           {
2201              int pdam;
2202
2203              pdam = ecore_evas_avoid_damage_get(ee);
2204              ecore_evas_avoid_damage_set(ee, 0);
2205              ecore_evas_avoid_damage_set(ee, pdam);
2206           }
2207         if ((ee->shaped) || (ee->alpha))
2208           _ecore_evas_x_resize_shape(ee);
2209         if (ee->func.fn_resize) ee->func.fn_resize(ee);
2210      }
2211    else
2212      {
2213         edata->configure_coming = 1;
2214         if (changed) edata->configure_reqs++;
2215         if (ee->prop.window) ecore_x_window_resize(ee->prop.window, w, h);
2216      }
2217 }
2218
2219 static void
2220 _ecore_evas_x_move_resize(Ecore_Evas *ee, int x, int y, int w, int h)
2221 {
2222    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2223    Eina_Bool changed = EINA_FALSE;
2224
2225    if ((ee->req.x != x) || (ee->req.y != y) ||
2226        (ee->req.w != w) || (ee->req.h != h))
2227      {
2228         changed = EINA_TRUE;
2229         ee->req.x = x;
2230         ee->req.y = y;
2231         ee->req.w = w;
2232         ee->req.h = h;
2233      }
2234
2235    if (edata->direct_resize)
2236      {
2237         if ((ee->w != w) || (ee->h != h) || (x != ee->x) || (y != ee->y))
2238           {
2239              int change_size = 0, change_pos = 0;
2240
2241              if ((ee->w != w) || (ee->h != h)) change_size = 1;
2242              if (!edata->managed)
2243                {
2244                   if ((x != ee->x) || (y != ee->y)) change_pos = 1;
2245                }
2246              if (changed) edata->configure_reqs++;
2247              ecore_x_window_move_resize(ee->prop.window, x, y, w, h);
2248              if (!edata->managed)
2249                {
2250                   ee->x = x;
2251                   ee->y = y;
2252                }
2253              ee->w = w;
2254              ee->h = h;
2255              if (ECORE_EVAS_PORTRAIT(ee))
2256                {
2257                   evas_output_size_set(ee->evas, ee->w, ee->h);
2258                   evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
2259                }
2260              else
2261                {
2262                   evas_output_size_set(ee->evas, ee->h, ee->w);
2263                   evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
2264                }
2265              if (ee->prop.avoid_damage)
2266                {
2267                   int pdam;
2268
2269                   pdam = ecore_evas_avoid_damage_get(ee);
2270                   ecore_evas_avoid_damage_set(ee, 0);
2271                   ecore_evas_avoid_damage_set(ee, pdam);
2272                }
2273              if ((ee->shaped) || (ee->alpha))
2274                _ecore_evas_x_resize_shape(ee);
2275              if (change_pos)
2276                {
2277                   if (ee->func.fn_move) ee->func.fn_move(ee);
2278                }
2279              if (change_size)
2280                {
2281                   if (ee->func.fn_resize) ee->func.fn_resize(ee);
2282                }
2283           }
2284      }
2285    else
2286      {
2287         if ((ee->x != x) || (ee->y != y) || (edata->configure_coming))
2288           {
2289              edata->configure_coming = 1;
2290              if (changed) edata->configure_reqs++;
2291              ecore_x_window_move_resize(ee->prop.window, x, y, w, h);
2292              if (!edata->managed)
2293                {
2294                   ee->x = x;
2295                   ee->y = y;
2296                }
2297           }
2298         else
2299           {
2300              edata->configure_coming = 1;
2301              if (changed) edata->configure_reqs++;
2302              if (ee->prop.window) ecore_x_window_resize(ee->prop.window, w, h);
2303           }
2304      }
2305 }
2306
2307 static void
2308 _ecore_evas_x_rotation_set_internal(Ecore_Evas *ee, int rotation, int resize,
2309                                     Evas_Engine_Info *einfo)
2310 {
2311    int rot_dif;
2312    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2313
2314    rot_dif = ee->rotation - rotation;
2315    if (rot_dif < 0) rot_dif = -rot_dif;
2316
2317    if (rot_dif != 180)
2318      {
2319         int minw, minh, maxw, maxh, basew, baseh, stepw, steph;
2320
2321         if (!evas_engine_info_set(ee->evas, einfo))
2322           {
2323              ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
2324           }
2325
2326         if (!resize)
2327           {
2328              edata->configure_coming = 1;
2329              if (!ee->prop.fullscreen)
2330                {
2331                   ecore_x_window_resize(ee->prop.window, ee->req.h, ee->req.w);
2332                   ee->expecting_resize.w = ee->h;
2333                   ee->expecting_resize.h = ee->w;
2334                   evas_output_size_set(ee->evas, ee->req.h, ee->req.w);
2335                   evas_output_viewport_set(ee->evas, 0, 0, ee->req.h, ee->req.w);
2336                }
2337              else
2338                {
2339                   int w, h;
2340
2341                   ecore_x_window_size_get(ee->prop.window, &w, &h);
2342                   ecore_x_window_resize(ee->prop.window, h, w);
2343                   if (PORTRAIT_CHECK(rotation))
2344                     {
2345                        evas_output_size_set(ee->evas, ee->req.w, ee->req.h);
2346                        evas_output_viewport_set(ee->evas, 0, 0, ee->req.w, ee->req.h);
2347                     }
2348                   else
2349                     {
2350                        evas_output_size_set(ee->evas, ee->req.h, ee->req.w);
2351                        evas_output_viewport_set(ee->evas, 0, 0, ee->req.h, ee->req.w);
2352                     }
2353                   if (ee->func.fn_resize) ee->func.fn_resize(ee);
2354                }
2355              if (PORTRAIT_CHECK(rotation))
2356                evas_damage_rectangle_add(ee->evas, 0, 0, ee->req.w, ee->req.h);
2357              else
2358                evas_damage_rectangle_add(ee->evas, 0, 0, ee->req.h, ee->req.w);
2359           }
2360         else
2361           {
2362              /* int w, h; */
2363
2364              /* ecore_x_window_size_get(ee->prop.window, &w, &h); */
2365              if (PORTRAIT_CHECK(rotation))
2366                {
2367                   evas_output_size_set(ee->evas, ee->w, ee->h);
2368                   evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
2369                }
2370              else
2371                {
2372                   evas_output_size_set(ee->evas, ee->h, ee->w);
2373                   evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w);
2374                }
2375              if (ee->func.fn_resize) ee->func.fn_resize(ee);
2376              if (PORTRAIT_CHECK(rotation))
2377                evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
2378              else
2379                evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
2380           }
2381         ecore_evas_size_min_get(ee, &minw, &minh);
2382         ecore_evas_size_max_get(ee, &maxw, &maxh);
2383         ecore_evas_size_base_get(ee, &basew, &baseh);
2384         ecore_evas_size_step_get(ee, &stepw, &steph);
2385         ee->rotation = rotation;
2386         ecore_evas_size_min_set(ee, minh, minw);
2387         ecore_evas_size_max_set(ee, maxh, maxw);
2388         ecore_evas_size_base_set(ee, baseh, basew);
2389         ecore_evas_size_step_set(ee, steph, stepw);
2390         _ecore_evas_mouse_move_process(ee, ee->mouse.x, ee->mouse.y,
2391                                        ecore_x_current_time_get());
2392      }
2393    else
2394      {
2395         if (!evas_engine_info_set(ee->evas, einfo))
2396           {
2397              ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
2398           }
2399         ee->rotation = rotation;
2400         _ecore_evas_mouse_move_process(ee, ee->mouse.x, ee->mouse.y,
2401                                        ecore_x_current_time_get());
2402         if (ee->func.fn_resize) ee->func.fn_resize(ee);
2403
2404         if (ECORE_EVAS_PORTRAIT(ee))
2405           evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
2406         else
2407           evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
2408      }
2409 }
2410
2411 static Eina_Bool
2412 _ecore_evas_x_wm_rotation_check(Ecore_Evas *ee)
2413 {
2414    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2415    if (ee->prop.wm_rot.supported)
2416      {
2417         if (ee->prop.wm_rot.app_set)
2418           {
2419              if (edata->wm_rot.request)
2420                {
2421                   if (ee->prop.wm_rot.win_resize)
2422                     {
2423                        if (!((ee->w == ee->prop.wm_rot.w) &&
2424                              (ee->h == ee->prop.wm_rot.h)))
2425                          {
2426                             return EINA_FALSE;
2427                          }
2428                        else
2429                          edata->wm_rot.configure_coming = 0;
2430                     }
2431                }
2432           }
2433      }
2434    return EINA_TRUE;
2435 }
2436
2437 static void
2438 _rotation_do(Ecore_Evas *ee, int rotation, int resize)
2439 {
2440 #ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
2441    if (ee->prop.wm_rot.supported)
2442      if (!_ecore_evas_x_wm_rotation_check(ee)) return;
2443    Evas_Engine_Info_Software_X11 *einfo;
2444    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2445
2446    einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
2447    if (!einfo) return;
2448    einfo->info.rotation = rotation;
2449    _ecore_evas_x_rotation_set_internal(ee, rotation, resize,
2450                                        (Evas_Engine_Info *)einfo);
2451    if (ee->prop.wm_rot.supported)
2452      {
2453         if (ee->prop.wm_rot.app_set)
2454           {
2455              if (edata->wm_rot.request)
2456                {
2457                   if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
2458                   edata->wm_rot.request = 0;
2459                   edata->wm_rot.done = 1;
2460                }
2461           }
2462      }
2463
2464    int angles[2] = { rotation, rotation };
2465    ecore_x_window_prop_property_set(ee->prop.window,
2466                                     ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
2467                                     ECORE_X_ATOM_CARDINAL, 32, &angles, 2);
2468 #endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */
2469 }
2470
2471 static void
2472 _ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation, int resize)
2473 {
2474    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2475
2476    if (ee->rotation == rotation)
2477      {
2478         if (ee->prop.wm_rot.supported)
2479           {
2480              if (edata->wm_rot.request)
2481                {
2482                   if (ee->prop.wm_rot.manual_mode.set)
2483                     {
2484                        ee->prop.wm_rot.manual_mode.wait_for_done = EINA_FALSE;
2485                        if (ee->prop.wm_rot.manual_mode.timer)
2486                          ecore_timer_del(ee->prop.wm_rot.manual_mode.timer);
2487                        ee->prop.wm_rot.manual_mode.timer = NULL;
2488                     }
2489                   /* send rotation done message to wm, even if window is already rotated.
2490                    * that's why wm must be wait for comming rotation done message
2491                    * after sending rotation request.
2492                    */
2493                   ecore_x_e_window_rotation_change_done_send
2494                     (edata->win_root, ee->prop.window, ee->rotation, ee->w, ee->h);
2495                   edata->wm_rot.request = 0;
2496                }
2497           }
2498         return;
2499      }
2500
2501    if (ee->prop.wm_rot.supported)
2502      if (!_ecore_evas_x_wm_rotation_check(ee)) return;
2503
2504    if (!strcmp(ee->driver, "opengl_x11"))
2505      {
2506 #ifdef BUILD_ECORE_EVAS_OPENGL_X11
2507         Evas_Engine_Info_GL_X11 *einfo;
2508
2509         einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas);
2510         if (!einfo) return;
2511         einfo->info.rotation = rotation;
2512         _ecore_evas_x_rotation_set_internal(ee, rotation, resize,
2513                                             (Evas_Engine_Info *)einfo);
2514         if (ee->prop.wm_rot.supported)
2515           {
2516              if (ee->prop.wm_rot.app_set)
2517                {
2518                   if (edata->wm_rot.request)
2519                     {
2520                        if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
2521                        edata->wm_rot.request = 0;
2522                        edata->wm_rot.done = 1;
2523                     }
2524                }
2525           }
2526
2527         int angles[2] = { rotation, rotation };
2528         ecore_x_window_prop_property_set(ee->prop.window,
2529                                          ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
2530                                          ECORE_X_ATOM_CARDINAL, 32, &angles, 2);
2531 #endif /* BUILD_ECORE_EVAS_OPENGL_X11 */
2532      }
2533    else if (!strcmp(ee->driver, "software_x11"))
2534      {
2535         if (ee->in_async_render)
2536           {
2537              ee->delayed.rotation = rotation;
2538              ee->delayed.rotation_resize = resize;
2539              ee->delayed.rotation_changed = EINA_TRUE;
2540              return;
2541           }
2542         _rotation_do(ee, rotation, resize);
2543         return;
2544      }
2545 }
2546
2547 static void
2548 _shaped_do(Ecore_Evas *ee, int shaped)
2549 {
2550 #ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
2551    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2552    Evas_Engine_Info_Software_X11 *einfo;
2553
2554    if (ee->shaped == shaped) return;
2555    einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
2556    ee->shaped = shaped;
2557    if (einfo)
2558      {
2559         if (ee->shaped)
2560           {
2561              unsigned int foreground;
2562              Ecore_X_GC gc;
2563
2564              if (!edata->mask)
2565                edata->mask = ecore_x_pixmap_new(ee->prop.window, ee->w, ee->h, 1);
2566              foreground = 0;
2567              gc = ecore_x_gc_new(edata->mask,
2568                                  ECORE_X_GC_VALUE_MASK_FOREGROUND,
2569                                  &foreground);
2570              ecore_x_drawable_rectangle_fill(edata->mask, gc,
2571                                              0, 0, ee->w, ee->h);
2572              ecore_x_gc_free(gc);
2573              einfo->info.mask = edata->mask;
2574              if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
2575                {
2576                   ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
2577                }
2578              evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
2579              ecore_x_window_shape_input_mask_set(ee->prop.window, 0);
2580           }
2581         else
2582           {
2583              if (edata->mask) ecore_x_pixmap_free(edata->mask);
2584              edata->mask = 0;
2585              einfo->info.mask = 0;
2586              if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
2587                {
2588                   ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
2589                }
2590              ecore_x_window_shape_mask_set(ee->prop.window, 0);
2591              ecore_x_window_shape_input_mask_set(ee->prop.window, 0);
2592           }
2593      }
2594 #endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */
2595 }
2596
2597 static void
2598 _ecore_evas_x_shaped_set(Ecore_Evas *ee, int shaped)
2599 {
2600    if (!strcmp(ee->driver, "opengl_x11")) return;
2601    if (!strcmp(ee->driver, "software_x11"))
2602      {
2603         if (ee->in_async_render)
2604           {
2605              ee->delayed.shaped = shaped;
2606              ee->delayed.shaped_changed = EINA_TRUE;
2607              return;
2608           }
2609         _shaped_do(ee, shaped);
2610      }
2611 }
2612
2613 static void
2614 _alpha_do(Ecore_Evas *ee, int alpha)
2615 {
2616    char *id = NULL;
2617 #ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
2618    Ecore_X_Window_Attributes att;
2619    Evas_Engine_Info_Software_X11 *einfo;
2620    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2621
2622    if (ee->alpha == alpha) return;
2623
2624    einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
2625    if (!einfo) return;
2626
2627    if (!ecore_x_composite_query()) return;
2628
2629    ee->shaped = 0;
2630    ee->alpha = alpha;
2631    _ecore_evas_x_sync_clear(ee);
2632    ecore_x_window_free(ee->prop.window);
2633    ecore_event_window_unregister(ee->prop.window);
2634    if (ee->alpha)
2635      {
2636         if (ee->prop.override)
2637           ee->prop.window = ecore_x_window_override_argb_new(edata->win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
2638         else
2639           ee->prop.window = ecore_x_window_argb_new(edata->win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
2640         //             if (!edata->mask)
2641         //               edata->mask = ecore_x_pixmap_new(ee->prop.window, ee->req.w, ee->req.h, 1);
2642      }
2643    else
2644      {
2645         if (ee->prop.override)
2646           ee->prop.window = ecore_x_window_override_new(edata->win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
2647         else
2648           ee->prop.window = ecore_x_window_new(edata->win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
2649         if (edata->mask) ecore_x_pixmap_free(edata->mask);
2650         edata->mask = 0;
2651         ecore_x_window_shape_input_mask_set(ee->prop.window, 0);
2652         ecore_x_vsync_animator_tick_source_set(ee->prop.window);
2653      }
2654
2655    einfo->info.destination_alpha = alpha;
2656
2657    ecore_x_window_attributes_get(ee->prop.window, &att);
2658    einfo->info.visual = att.visual;
2659    einfo->info.colormap = att.colormap;
2660    einfo->info.depth = att.depth;
2661
2662    //        if (edata->mask) ecore_x_pixmap_free(edata->mask);
2663    //        edata->mask = 0;
2664    einfo->info.mask = edata->mask;
2665    einfo->info.drawable = ee->prop.window;
2666    if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
2667      {
2668         ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
2669      }
2670    evas_damage_rectangle_add(ee->evas, 0, 0, ee->req.w, ee->req.h);
2671    ecore_x_window_shape_mask_set(ee->prop.window, 0);
2672    ecore_x_input_multi_select(ee->prop.window);
2673    ecore_event_window_register(ee->prop.window, ee, ee->evas,
2674                                (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
2675                                (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
2676                                (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
2677                                (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
2678    _ecore_event_window_direct_cb_set(ee->prop.window, _ecore_evas_input_direct_cb);
2679
2680    if (ee->prop.borderless)
2681      ecore_x_mwm_borderless_set(ee->prop.window, ee->prop.borderless);
2682    if (ee->visible || ee->should_be_visible)
2683      ecore_x_window_show(ee->prop.window);
2684    if (ee->prop.focused) ecore_x_window_focus(ee->prop.window);
2685    if (ee->prop.title)
2686      {
2687         ecore_x_icccm_title_set(ee->prop.window, ee->prop.title);
2688         ecore_x_netwm_name_set(ee->prop.window, ee->prop.title);
2689      }
2690    if (ee->prop.name)
2691      ecore_x_icccm_name_class_set(ee->prop.window,
2692                                   ee->prop.name, ee->prop.clas);
2693    _ecore_evas_x_hints_update(ee);
2694    _ecore_evas_x_group_leader_update(ee);
2695    ecore_x_window_defaults_set(ee->prop.window);
2696    _ecore_evas_x_protocols_set(ee);
2697    _ecore_evas_x_window_profile_protocol_set(ee);
2698    _ecore_evas_x_wm_rotation_protocol_set(ee);
2699    _ecore_evas_x_aux_hints_supported_update(ee);
2700    _ecore_evas_x_aux_hints_update(ee);
2701    _ecore_evas_x_sync_set(ee);
2702    _ecore_evas_x_size_pos_hints_update(ee);
2703 #endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */
2704    if ((id = getenv("DESKTOP_STARTUP_ID")))
2705      {
2706         ecore_x_netwm_startup_id_set(ee->prop.window, id);
2707         /* NB: on linux this may simply empty the env as opposed to completely
2708          * unset it to being empty - unsure as solartis libc crashes looking
2709          * for the '=' char */
2710         //        putenv((char*)"DESKTOP_STARTUP_ID=");
2711      }
2712 }
2713
2714 /* FIXME, round trip */
2715 static void
2716 _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
2717 {
2718    char *id = NULL;
2719
2720    if (!strcmp(ee->driver, "software_x11"))
2721      {
2722         if (ee->in_async_render)
2723           {
2724              if (ee->visible)
2725                {
2726                   ee->delayed.alpha = alpha;
2727                   ee->delayed.alpha_changed = EINA_TRUE;
2728                   return;
2729                }
2730              evas_sync(ee->evas);
2731           }
2732         _alpha_do(ee, alpha);
2733      }
2734    else if (!strcmp(ee->driver, "opengl_x11"))
2735      {
2736 #ifdef BUILD_ECORE_EVAS_OPENGL_X11
2737         Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2738         Ecore_X_Window_Attributes att;
2739         if (ee->alpha == alpha) return;
2740
2741         Evas_Engine_Info_GL_X11 *einfo;
2742         Ecore_Window prev_win;
2743
2744         einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas);
2745         if (!einfo) return;
2746
2747         if (!ecore_x_composite_query()) return;
2748
2749         ee->shaped = 0;
2750         ee->alpha = alpha;
2751         _ecore_evas_x_sync_clear(ee);
2752         prev_win = ee->prop.window;
2753         ee->prop.window = 0;
2754
2755         einfo->info.destination_alpha = alpha;
2756
2757         if (edata->win_root != 0)
2758           {
2759              /* FIXME: round trip in ecore_x_window_argb_get */
2760              if (ecore_x_window_argb_get(edata->win_root))
2761                {
2762                   ee->prop.window =
2763                     _ecore_evas_x_gl_window_new(ee, edata->win_root,
2764                                                 ee->req.x, ee->req.y,
2765                                                 ee->req.w, ee->req.h,
2766                                                 ee->prop.override, 1, NULL);
2767                }
2768              else
2769                {
2770                   ee->prop.window =
2771                     _ecore_evas_x_gl_window_new(ee, edata->win_root,
2772                                                 ee->req.x, ee->req.y,
2773                                                 ee->req.w, ee->req.h,
2774                                                 ee->prop.override, ee->alpha,
2775                                                 NULL);
2776                }
2777           }
2778         else
2779           {
2780              ee->prop.window =
2781                _ecore_evas_x_gl_window_new(ee, edata->win_root,
2782                                            ee->req.x, ee->req.y,
2783                                            ee->req.w, ee->req.h,
2784                                            ee->prop.override, ee->alpha, NULL);
2785           }
2786
2787         ecore_x_window_free(prev_win);
2788         ecore_event_window_unregister(prev_win);
2789
2790         if (!ee->prop.window) return;
2791 /*
2792         if (ee->alpha)
2793           {
2794              if (ee->prop.override)
2795                ee->prop.window = ecore_x_window_override_argb_new(edata->win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
2796              else
2797                ee->prop.window = ecore_x_window_argb_new(edata->win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
2798              if (!edata->mask)
2799                edata->mask = ecore_x_pixmap_new(ee->prop.window, ee->req.w, ee->req.h, 1);
2800           }
2801         else
2802           {
2803              if (ee->prop.override)
2804                ee->prop.window = ecore_x_window_override_new(edata->win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
2805              else
2806                ee->prop.window = ecore_x_window_new(edata->win_root, ee->req.x, ee->req.y, ee->req.w, ee->req.h);
2807              if (edata->mask) ecore_x_pixmap_free(edata->mask);
2808              edata->mask = 0;
2809              ecore_x_window_shape_input_mask_set(ee->prop.window, 0);
2810           }
2811  */
2812
2813         ecore_x_window_attributes_get(ee->prop.window, &att);
2814         einfo->info.visual = att.visual;
2815         einfo->info.colormap = att.colormap;
2816         einfo->info.depth = att.depth;
2817
2818 //        if (edata->mask) ecore_x_pixmap_free(edata->mask);
2819 //        edata->mask = 0;
2820 //        einfo->info.mask = edata->mask;
2821         einfo->info.drawable = ee->prop.window;
2822         if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
2823           {
2824              ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
2825           }
2826         evas_damage_rectangle_add(ee->evas, 0, 0, ee->req.w, ee->req.h);
2827 //        ecore_x_window_shape_mask_set(ee->prop.window, 0);
2828         ecore_x_input_multi_select(ee->prop.window);
2829         ecore_event_window_register(ee->prop.window, ee, ee->evas,
2830                                     (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
2831                                     (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
2832                                     (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
2833                                     (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
2834         _ecore_event_window_direct_cb_set(ee->prop.window, _ecore_evas_input_direct_cb);
2835
2836         if (ee->prop.borderless)
2837           ecore_x_mwm_borderless_set(ee->prop.window, ee->prop.borderless);
2838         if (ee->visible || ee->should_be_visible)
2839           ecore_x_window_show(ee->prop.window);
2840         if (ee->prop.focused) ecore_x_window_focus(ee->prop.window);
2841         if (ee->prop.title)
2842           {
2843              ecore_x_icccm_title_set(ee->prop.window, ee->prop.title);
2844              ecore_x_netwm_name_set(ee->prop.window, ee->prop.title);
2845           }
2846         if (ee->prop.name)
2847           ecore_x_icccm_name_class_set(ee->prop.window,
2848                                        ee->prop.name, ee->prop.clas);
2849         _ecore_evas_x_hints_update(ee);
2850         _ecore_evas_x_group_leader_update(ee);
2851         ecore_x_window_defaults_set(ee->prop.window);
2852         _ecore_evas_x_protocols_set(ee);
2853         _ecore_evas_x_window_profile_protocol_set(ee);
2854         _ecore_evas_x_wm_rotation_protocol_set(ee);
2855         _ecore_evas_x_aux_hints_supported_update(ee);
2856         _ecore_evas_x_aux_hints_update(ee);
2857         _ecore_evas_x_sync_set(ee);
2858         _ecore_evas_x_size_pos_hints_update(ee);
2859 #endif /* BUILD_ECORE_EVAS_OPENGL_X11 */
2860         if ((id = getenv("DESKTOP_STARTUP_ID")))
2861           {
2862              ecore_x_netwm_startup_id_set(ee->prop.window, id);
2863              /* NB: on linux this may simply empty the env as opposed to completely
2864               * unset it to being empty - unsure as solartis libc crashes looking
2865               * for the '=' char */
2866              //        putenv((char*)"DESKTOP_STARTUP_ID=");
2867           }
2868      }
2869 }
2870
2871 static void
2872 _transparent_do(Ecore_Evas *ee, int transparent)
2873 {
2874 #ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
2875    if (ee->transparent == transparent) return;
2876
2877    Evas_Engine_Info_Software_X11 *einfo;
2878
2879    einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
2880    if (!einfo) return;
2881
2882    ee->transparent = transparent;
2883    einfo->info.destination_alpha = transparent;
2884    if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
2885      {
2886         ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
2887      }
2888    evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
2889 #endif
2890 }
2891
2892 static void
2893 _ecore_evas_x_transparent_set(Ecore_Evas *ee, int transparent)
2894 {
2895    if (!strcmp(ee->driver, "software_x11"))
2896      {
2897         if (ee->in_async_render)
2898           {
2899              ee->delayed.transparent = transparent;
2900              ee->delayed.transparent_changed = EINA_TRUE;
2901              return;
2902           }
2903         _transparent_do(ee, transparent);
2904      }
2905 }
2906
2907 static void
2908 _ecore_evas_x_window_group_set(Ecore_Evas *ee, const Ecore_Evas *group_ee)
2909 {
2910    if (ee->prop.group_ee == group_ee) return;
2911
2912    ee->prop.group_ee = (Ecore_Evas *)group_ee;
2913    if (ee->prop.group_ee)
2914      ee->prop.group_ee_win = group_ee->prop.window;
2915    else
2916      ee->prop.group_ee_win = 0;
2917    _ecore_evas_x_hints_update(ee);
2918 }
2919
2920 static void
2921 _ecore_evas_x_aspect_set(Ecore_Evas *ee, double aspect)
2922 {
2923    if (ee->prop.aspect == aspect) return;
2924
2925    ee->prop.aspect = aspect;
2926    _ecore_evas_x_size_pos_hints_update(ee);
2927 // netwm state  
2928 //   if (ee->should_be_visible)
2929 //     ecore_x_netwm_state_request_send(ee->prop.window, ee->engine.x.win_root,
2930 //                                      ECORE_X_WINDOW_STATE_STICKY, -1, sticky);
2931 //   else
2932 //     _ecore_evas_x_state_update(ee);
2933 }
2934
2935 static void
2936 _ecore_evas_x_urgent_set(Ecore_Evas *ee, Eina_Bool on)
2937 {
2938    if (ee->prop.urgent == on) return;
2939
2940    ee->prop.urgent = on;
2941    _ecore_evas_x_hints_update(ee);
2942 }
2943
2944 static void
2945 _ecore_evas_x_modal_set(Ecore_Evas *ee, Eina_Bool on)
2946 {
2947    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2948
2949    if (ee->prop.modal == on) return;
2950
2951    ee->prop.modal = on;
2952    if (ee->should_be_visible)
2953      ecore_x_netwm_state_request_send(ee->prop.window, edata->win_root,
2954                                       ECORE_X_WINDOW_STATE_MODAL, -1, on);
2955    else
2956      _ecore_evas_x_state_update(ee);
2957 }
2958
2959 static void
2960 _ecore_evas_x_demand_attention_set(Ecore_Evas *ee, Eina_Bool on)
2961 {
2962    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2963
2964    if (ee->prop.demand_attention == on) return;
2965
2966    ee->prop.demand_attention = on;
2967    if (ee->should_be_visible)
2968      ecore_x_netwm_state_request_send(ee->prop.window, edata->win_root,
2969                                       ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION,
2970                                       -1, on);
2971    else
2972      _ecore_evas_x_state_update(ee);
2973 }
2974
2975 static void
2976 _ecore_evas_x_focus_skip_set(Ecore_Evas *ee, Eina_Bool on)
2977 {
2978    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2979
2980    if (ee->prop.focus_skip == on) return;
2981
2982    ee->prop.focus_skip = on;
2983    if (ee->should_be_visible)
2984      {
2985         ecore_x_netwm_state_request_send(ee->prop.window, edata->win_root,
2986                                          ECORE_X_WINDOW_STATE_SKIP_TASKBAR, -1,
2987                                          on);
2988         ecore_x_netwm_state_request_send(ee->prop.window, edata->win_root,
2989                                          ECORE_X_WINDOW_STATE_SKIP_PAGER, -1,
2990                                          on);
2991      }
2992    else
2993      _ecore_evas_x_state_update(ee);
2994    _ecore_evas_x_hints_update(ee);
2995 }
2996
2997 static void
2998 _ecore_evas_x_show(Ecore_Evas *ee)
2999 {
3000    ee->should_be_visible = 1;
3001    if (ee->prop.avoid_damage)
3002      _ecore_evas_x_render(ee);
3003    _ecore_evas_x_sync_set(ee);
3004    _ecore_evas_x_window_profile_set(ee);
3005    if (!ee->prop.withdrawn) _ecore_evas_x_hints_update(ee);
3006    else
3007      {
3008         ee->prop.withdrawn = EINA_FALSE;
3009         _ecore_evas_x_hints_update(ee);
3010         ee->prop.withdrawn = EINA_TRUE;
3011      }
3012    ecore_x_window_show(ee->prop.window);
3013    if (ee->prop.fullscreen) ecore_x_window_focus(ee->prop.window);
3014 }
3015
3016 static void
3017 _ecore_evas_x_hide(Ecore_Evas *ee)
3018 {
3019    ecore_x_window_hide(ee->prop.window);
3020    ee->should_be_visible = 0;
3021    _ecore_evas_x_sync_set(ee);
3022 }
3023
3024 static void
3025 _ecore_evas_x_raise(Ecore_Evas *ee)
3026 {
3027    ecore_x_window_raise(ee->prop.window);
3028 }
3029
3030 static void
3031 _ecore_evas_x_lower(Ecore_Evas *ee)
3032 {
3033    ecore_x_window_lower(ee->prop.window);
3034 }
3035
3036 static void
3037 _ecore_evas_x_activate(Ecore_Evas *ee)
3038 {
3039    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
3040
3041    ecore_evas_show(ee);
3042    ecore_x_netwm_client_active_request(edata->win_root,
3043                                        ee->prop.window, 2, 0);
3044 }
3045
3046 static void
3047 _ecore_evas_x_title_set(Ecore_Evas *ee, const char *t)
3048 {
3049    if (eina_streq(ee->prop.title, t)) return;
3050    if (ee->prop.title) free(ee->prop.title);
3051    ee->prop.title = NULL;
3052    if (!t) return;
3053    ee->prop.title = strdup(t);
3054    ecore_x_icccm_title_set(ee->prop.window, ee->prop.title);
3055    ecore_x_netwm_name_set(ee->prop.window, ee->prop.title);
3056 }
3057
3058 static void
3059 _ecore_evas_x_name_class_set(Ecore_Evas *ee, const char *n, const char *c)
3060 {
3061    if (!eina_streq(n, ee->prop.name))
3062      {
3063         free(ee->prop.name);
3064         ee->prop.name = NULL;
3065         if (n) ee->prop.name = strdup(n);
3066      }
3067    if (!eina_streq(c, ee->prop.clas))
3068      {
3069         free(ee->prop.clas);
3070         ee->prop.clas = NULL;
3071         if (c) ee->prop.clas = strdup(c);
3072      }
3073    ecore_x_icccm_name_class_set(ee->prop.window, ee->prop.name, ee->prop.clas);
3074 }
3075
3076 static void
3077 _ecore_evas_x_size_min_set(Ecore_Evas *ee, int w, int h)
3078 {
3079    if (w < 0) w = 0;
3080    if (h < 0) h = 0;
3081    if ((ee->prop.min.w == w) && (ee->prop.min.h == h)) return;
3082    ee->prop.min.w = w;
3083    ee->prop.min.h = h;
3084    _ecore_evas_x_size_pos_hints_update(ee);
3085 }
3086
3087 static void
3088 _ecore_evas_x_size_max_set(Ecore_Evas *ee, int w, int h)
3089 {
3090    if (w < 0) w = 0;
3091    if (h < 0) h = 0;
3092    if ((ee->prop.max.w == w) && (ee->prop.max.h == h)) return;
3093    ee->prop.max.w = w;
3094    ee->prop.max.h = h;
3095    _ecore_evas_x_size_pos_hints_update(ee);
3096 }
3097
3098 static void
3099 _ecore_evas_x_size_base_set(Ecore_Evas *ee, int w, int h)
3100 {
3101    if (w < 0) w = 0;
3102    if (h < 0) h = 0;
3103    if ((ee->prop.base.w == w) && (ee->prop.base.h == h)) return;
3104    ee->prop.base.w = w;
3105    ee->prop.base.h = h;
3106    _ecore_evas_x_size_pos_hints_update(ee);
3107 }
3108
3109 static void
3110 _ecore_evas_x_size_step_set(Ecore_Evas *ee, int w, int h)
3111 {
3112    if (w < 1) w = 1;
3113    if (h < 1) h = 1;
3114    if ((ee->prop.step.w == w) && (ee->prop.step.h == h)) return;
3115    ee->prop.step.w = w;
3116    ee->prop.step.h = h;
3117    _ecore_evas_x_size_pos_hints_update(ee);
3118 }
3119
3120 static void
3121 _ecore_evas_object_cursor_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
3122 {
3123    Ecore_Evas *ee;
3124
3125    ee = data;
3126    if (ee) ee->prop.cursor.object = NULL;
3127 }
3128
3129 static void
3130 _ecore_evas_x_object_cursor_unset(Ecore_Evas *ee)
3131 {
3132    evas_object_event_callback_del_full(ee->prop.cursor.object, EVAS_CALLBACK_DEL, _ecore_evas_object_cursor_del, ee);
3133 }
3134
3135 static void
3136 _ecore_evas_x_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
3137 {
3138    int x = 0, y = 0;
3139    Evas_Object *old;
3140
3141    old = ee->prop.cursor.object;
3142    if (!obj)
3143      {
3144         ee->prop.cursor.object = NULL;
3145         ee->prop.cursor.layer = 0;
3146         ee->prop.cursor.hot.x = 0;
3147         ee->prop.cursor.hot.y = 0;
3148         ecore_x_window_cursor_show(ee->prop.window, 1);
3149         goto end;
3150      }
3151
3152    ee->prop.cursor.object = obj;
3153    ee->prop.cursor.layer = layer;
3154    ee->prop.cursor.hot.x = hot_x;
3155    ee->prop.cursor.hot.y = hot_y;
3156
3157    evas_pointer_output_xy_get(ee->evas, &x, &y);
3158
3159    if (obj != old)
3160      {
3161         ecore_x_window_cursor_show(ee->prop.window, 0);
3162         evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
3163         evas_object_pass_events_set(ee->prop.cursor.object, 1);
3164         if (evas_pointer_inside_get(ee->evas))
3165           evas_object_show(ee->prop.cursor.object);
3166         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
3167                                        _ecore_evas_object_cursor_del, ee);
3168      }
3169
3170    evas_object_move(ee->prop.cursor.object, x - ee->prop.cursor.hot.x,
3171                     y - ee->prop.cursor.hot.y);
3172
3173 end:
3174    if ((old) && (obj != old))
3175      {
3176         evas_object_event_callback_del_full
3177           (old, EVAS_CALLBACK_DEL, _ecore_evas_object_cursor_del, ee);
3178         evas_object_del(old);
3179      }
3180 }
3181
3182 /*
3183  * @param ee
3184  * @param layer If < 3, @a ee will be put below all other windows.
3185  *              If > 5, @a ee will be "always-on-top"
3186  *              If = 4, @a ee will be put in the default layer.
3187  *              Acceptable values range from 1 to 255 (0 reserved for
3188  *              desktop windows)
3189  */
3190 static void
3191 _ecore_evas_x_layer_set(Ecore_Evas *ee, int layer)
3192 {
3193    if (ee->prop.layer == layer) return;
3194
3195    /* FIXME: Should this logic be here? */
3196    if (layer < 1)
3197      layer = 1;
3198    else if (layer > 255)
3199      layer = 255;
3200
3201    ee->prop.layer = layer;
3202    _ecore_evas_x_layer_update(ee);
3203 }
3204
3205 static void
3206 _ecore_evas_x_focus_set(Ecore_Evas *ee, Eina_Bool on EINA_UNUSED)
3207 {
3208    ecore_x_window_focus(ee->prop.window);
3209 }
3210
3211 static void
3212 _ecore_evas_x_iconified_set(Ecore_Evas *ee, Eina_Bool on)
3213 {
3214    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
3215
3216    if (ee->prop.iconified == on) return;
3217    ee->prop.iconified = on;
3218    _ecore_evas_x_hints_update(ee);
3219    if (on)
3220      ecore_x_icccm_iconic_request_send(ee->prop.window, edata->win_root);
3221    else
3222      ecore_evas_activate(ee);
3223 }
3224
3225 static void
3226 _ecore_evas_x_borderless_set(Ecore_Evas *ee, Eina_Bool on)
3227 {
3228    if (ee->prop.borderless == on) return;
3229    ee->prop.borderless = on;
3230    ecore_x_mwm_borderless_set(ee->prop.window, ee->prop.borderless);
3231 }
3232
3233 /* FIXME: This function changes the initial state of the ee
3234  * whilest the iconic function changes the current state! */
3235 static void
3236 _ecore_evas_x_withdrawn_set(Ecore_Evas *ee, Eina_Bool on)
3237 {
3238    if (ee->prop.withdrawn == on) return;
3239 //   ee->prop.withdrawn = on;
3240    if (on)
3241      ecore_evas_hide(ee);
3242    else
3243      ecore_evas_show(ee);
3244 }
3245
3246 static void
3247 _ecore_evas_x_sticky_set(Ecore_Evas *ee, Eina_Bool on)
3248 {
3249    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
3250
3251    if (ee->prop.sticky == on) return;
3252
3253    /* We dont want to set prop.sticky here as it will cause
3254     * the sticky callback not to get called. Its set on the
3255     * property change event.
3256     * ee->prop.sticky = on;
3257     */
3258 //   edata->state.sticky = on;
3259    if (ee->should_be_visible)
3260      ecore_x_netwm_state_request_send(ee->prop.window, edata->win_root,
3261                                       ECORE_X_WINDOW_STATE_STICKY, -1, on);
3262    else
3263      _ecore_evas_x_state_update(ee);
3264 }
3265
3266 static void
3267 _ecore_evas_x_ignore_events_set(Ecore_Evas *ee, int ignore)
3268 {
3269    if (ee->ignore_events == ignore) return;
3270
3271    ee->ignore_events = ignore;
3272    if (ee->prop.window)
3273      ecore_x_window_ignore_set(ee->prop.window, ignore);
3274 }
3275
3276 /*
3277 static void
3278 _ecore_evas_x_reinit_win(Ecore_Evas *ee)
3279 {
3280    if (!strcmp(ee->driver, "software_x11"))
3281      {
3282 #ifdef BUILD_ECORE_EVAS_X11
3283         Evas_Engine_Info_Software_X11 *einfo;
3284
3285         einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
3286         if (einfo)
3287           {
3288              einfo->info.drawable = ee->prop.window;
3289              if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
3290                {
3291                   ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
3292                }
3293           }
3294 #endif
3295      }
3296    else if (!strcmp(ee->driver, "opengl_x11"))
3297      {
3298 #ifdef BUILD_ECORE_EVAS_OPENGL_X11
3299         Evas_Engine_Info_GL_X11 *einfo;
3300
3301         einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas);
3302         if (einfo)
3303           {
3304              einfo->info.drawable = ee->prop.window;
3305              if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
3306                {
3307                   ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
3308                }
3309           }
3310 #endif
3311      }
3312 }
3313 */
3314
3315 static void
3316 _ecore_evas_x_override_set(Ecore_Evas *ee, Eina_Bool on)
3317 {
3318    if (ee->prop.override == on) return;
3319    if (ee->should_be_visible) ecore_x_window_hide(ee->prop.window);
3320    ecore_x_window_override_set(ee->prop.window, on);
3321    if (ee->should_be_visible) ecore_x_window_show(ee->prop.window);
3322    if (ee->prop.focused) ecore_x_window_focus(ee->prop.window);
3323    ee->prop.override = on;
3324 }
3325
3326 static void
3327 _ecore_evas_x_maximized_set(Ecore_Evas *ee, Eina_Bool on)
3328 {
3329    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
3330
3331    if (ee->prop.maximized == on) return;
3332    edata->state.maximized_h = 1;
3333    edata->state.maximized_v = 1;
3334 //   ee->prop.maximized = on;
3335    if (ee->should_be_visible)
3336      {
3337         ecore_x_netwm_state_request_send(ee->prop.window, edata->win_root,
3338                                          ECORE_X_WINDOW_STATE_MAXIMIZED_VERT, -1, on);
3339         ecore_x_netwm_state_request_send(ee->prop.window, edata->win_root,
3340                                          ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ, -1, on);
3341      }
3342    else
3343      _ecore_evas_x_state_update(ee);
3344 }
3345
3346 static void
3347 _ecore_evas_x_fullscreen_set(Ecore_Evas *ee, Eina_Bool on)
3348 {
3349    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
3350
3351    if (ee->prop.fullscreen == on) return;
3352
3353    /* FIXME: Detect if WM is EWMH compliant and handle properly if not,
3354     * i.e. reposition, resize, and change borderless hint */
3355    edata->state.fullscreen = on;
3356    if (ee->should_be_visible)
3357      ecore_x_netwm_state_request_send(ee->prop.window, edata->win_root,
3358                                       ECORE_X_WINDOW_STATE_FULLSCREEN, -1, on);
3359    else
3360      _ecore_evas_x_state_update(ee);
3361 }
3362
3363 static void
3364 _ecore_evas_x_profile_set(Ecore_Evas *ee, const char *profile)
3365 {
3366    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
3367
3368    _ecore_evas_window_profile_free(ee);
3369    ee->prop.profile.name = NULL;
3370
3371    if (profile)
3372      ee->prop.profile.name = (char *)eina_stringshare_add(profile);
3373    edata->profile.change = 1;
3374    _ecore_evas_x_window_profile_set(ee);
3375 }
3376
3377 static void
3378 _ecore_evas_x_profiles_set(Ecore_Evas *ee, const char **plist, int n)
3379 {
3380    int i;
3381    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
3382
3383    _ecore_evas_window_available_profiles_free(ee);
3384    ee->prop.profile.available_list = NULL;
3385
3386    if ((plist) && (n >= 1))
3387      {
3388         ee->prop.profile.available_list = calloc(n, sizeof(char *));
3389         if (ee->prop.profile.available_list)
3390           {
3391              for (i = 0; i < n; i++)
3392                ee->prop.profile.available_list[i] = (char *)eina_stringshare_add(plist[i]);
3393              ee->prop.profile.count = n;
3394           }
3395      }
3396    edata->profile.available = 1;
3397    _ecore_evas_x_window_profile_set(ee);
3398 }
3399
3400 static void
3401 _avoid_damage_do(Ecore_Evas *ee, int on)
3402 {
3403 #ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
3404    Evas_Engine_Info_Software_X11 *einfo;
3405    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
3406
3407    ee->prop.avoid_damage = on;
3408    einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
3409    if (einfo)
3410      {
3411         if (ee->prop.avoid_damage)
3412           {
3413              edata->pmap = ecore_x_pixmap_new(ee->prop.window, ee->w, ee->h, einfo->info.depth);
3414              edata->gc = ecore_x_gc_new(edata->pmap, 0, NULL);
3415              einfo->info.drawable = edata->pmap;
3416              if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
3417                {
3418                   ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
3419                }
3420              if (ECORE_EVAS_PORTRAIT(ee))
3421                evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
3422              else
3423                evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w);
3424              if (ee->prop.avoid_damage == ECORE_EVAS_AVOID_DAMAGE_BUILT_IN)
3425                {
3426                   edata->using_bg_pixmap = 1;
3427                   ecore_x_window_pixmap_set(ee->prop.window, edata->pmap);
3428                   ecore_x_window_area_expose(ee->prop.window, 0, 0, ee->w, ee->h);
3429                }
3430              if (edata->direct_resize)
3431                {
3432                   /* Turn this off for now
3433                      edata->using_bg_pixmap = 1;
3434                      ecore_x_window_pixmap_set(ee->prop.window, edata->pmap);
3435                      */
3436                }
3437           }
3438         else
3439           {
3440              if (edata->pmap) ecore_x_pixmap_free(edata->pmap);
3441              if (edata->gc) ecore_x_gc_free(edata->gc);
3442              if (edata->using_bg_pixmap)
3443                {
3444                   ecore_x_window_pixmap_set(ee->prop.window, 0);
3445                   edata->using_bg_pixmap = 0;
3446                   ecore_x_window_area_expose(ee->prop.window, 0, 0, ee->w, ee->h);
3447                }
3448              edata->pmap = 0;
3449              edata->gc = 0;
3450              einfo->info.drawable = ee->prop.window;
3451              if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
3452                {
3453                   ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
3454                }
3455           }
3456      }
3457 #endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */
3458 }
3459
3460 static void
3461 _ecore_evas_x_avoid_damage_set(Ecore_Evas *ee, int on)
3462 {
3463    if (ee->prop.avoid_damage == on) return;
3464    if (!strcmp(ee->driver, "opengl_x11")) return;
3465
3466    if (!strcmp(ee->driver, "software_x11"))
3467      {
3468         if (ee->in_async_render)
3469           {
3470              ee->delayed.avoid_damage = on;
3471              return;
3472           }
3473         _avoid_damage_do(ee, on);
3474      }
3475 }
3476
3477 static void
3478 _ecore_evas_x_screen_geometry_get(const Ecore_Evas *ee EINA_UNUSED, int *x, int *y, int *w, int *h)
3479 {
3480    int outnum = 0;
3481    int px = 0, py = 0, pw = 0, ph = 0;
3482    Ecore_X_Window root;
3483    Ecore_X_Randr_Output *out = NULL;
3484    Ecore_X_Randr_Crtc crtc;
3485    unsigned int val[4] = { 0 };
3486    
3487    if (ecore_x_window_prop_card32_get
3488        (ee->prop.window, ecore_x_atom_get("E_ZONE_GEOMETRY"), val, 4) == 4)
3489      {
3490         if (x) *x = (int)val[0];
3491         if (y) *y = (int)val[1];
3492         if (w) *w = (int)val[2];
3493         if (h) *h = (int)val[3];
3494         return;
3495      }
3496    
3497    root = ecore_x_window_root_get(ee->prop.window);
3498    out = ecore_x_randr_window_outputs_get(ee->prop.window, &outnum);
3499    if (!out)
3500      {
3501 norandr:
3502         if (out) free(out);
3503         if (x) *x = 0;
3504         if (y) *y = 0;
3505         ecore_x_window_size_get(root, w, h);
3506         return;
3507      }
3508    crtc = ecore_x_randr_output_crtc_get(root, out[0]);
3509    if (!crtc) goto norandr;
3510    ecore_x_randr_crtc_geometry_get(root, crtc, &px, &py, &pw, &ph);
3511    if ((pw == 0) || (ph == 0)) goto norandr;
3512    if (x) *x = px;
3513    if (y) *y = py;
3514    if (w) *w = pw;
3515    if (h) *h = ph;
3516    free(out);
3517 }
3518
3519 static void
3520 _ecore_evas_x_screen_dpi_get(const Ecore_Evas *ee, int *xdpi, int *ydpi)
3521 {
3522    int scdpi, xmm = 0, ymm = 0, outnum = 0, w = 0, h = 0;
3523    int px = 0, py = 0;
3524    Ecore_X_Window root;
3525    Ecore_X_Randr_Output *out = NULL;
3526    Ecore_X_Randr_Crtc crtc;
3527
3528    root = ecore_x_window_root_get(ee->prop.window);
3529    out = ecore_x_randr_window_outputs_get(ee->prop.window, &outnum);
3530    if (!out)
3531      {
3532 norandr:
3533         if (out) free(out);
3534         scdpi = ecore_x_dpi_get();
3535         if (xdpi) *xdpi = scdpi;
3536         if (ydpi) *ydpi = scdpi;
3537         return;
3538      }
3539    crtc = ecore_x_randr_output_crtc_get(root, out[0]);
3540    if (!crtc) goto norandr;
3541    ecore_x_randr_crtc_geometry_get(root, crtc, &px, &py, &w, &h);
3542    if ((w == 0) || (h == 0)) goto norandr;
3543    ecore_x_randr_output_size_mm_get(root, out[0], &xmm, &ymm);
3544    if ((xmm == 0) || (ymm == 0)) goto norandr;
3545    if (xdpi) *xdpi = (w * 254) / (xmm * 10); // 25.4mm / inch
3546    if (ydpi) *ydpi = (h * 254) / (ymm * 10); // 25.4mm / inch
3547    free(out);
3548 }
3549
3550 static void 
3551 _ecore_evas_x_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y)
3552 {
3553    if (ee->prop.window)
3554      ecore_x_pointer_xy_get(ee->prop.window, x, y);
3555 }
3556
3557 static Eina_Bool 
3558 _ecore_evas_x_pointer_warp(const Ecore_Evas *ee, Evas_Coord x, Evas_Coord y)
3559 {
3560    return ecore_x_pointer_warp(ee->prop.window, x, y);
3561 }
3562
3563 static void
3564 _ecore_evas_x_wm_rot_preferred_rotation_set(Ecore_Evas *ee, int rot)
3565 {
3566    if (ee->prop.wm_rot.supported)
3567      {
3568         if (!ee->prop.wm_rot.app_set)
3569           {
3570              ecore_x_e_window_rotation_app_set(ee->prop.window, EINA_TRUE);
3571              ee->prop.wm_rot.app_set = EINA_TRUE;
3572           }
3573         ecore_x_e_window_rotation_preferred_rotation_set(ee->prop.window, rot);
3574         ee->prop.wm_rot.preferred_rot = rot;
3575      }
3576 }
3577
3578 static void
3579 _ecore_evas_x_wm_rot_available_rotations_set(Ecore_Evas *ee, const int *rots, unsigned int count)
3580 {
3581    if (ee->prop.wm_rot.supported)
3582      {
3583         if (!ee->prop.wm_rot.app_set)
3584           {
3585              ecore_x_e_window_rotation_app_set(ee->prop.window, EINA_TRUE);
3586              ee->prop.wm_rot.app_set = EINA_TRUE;
3587           }
3588
3589         if (ee->prop.wm_rot.available_rots)
3590           {
3591              free(ee->prop.wm_rot.available_rots);
3592              ee->prop.wm_rot.available_rots = NULL;
3593           }
3594
3595         ee->prop.wm_rot.count = 0;
3596
3597         if (count > 0)
3598           {
3599              ee->prop.wm_rot.available_rots = calloc(count, sizeof(int));
3600              if (!ee->prop.wm_rot.available_rots) return;
3601
3602              memcpy(ee->prop.wm_rot.available_rots, rots, sizeof(int) * count);
3603           }
3604
3605         ee->prop.wm_rot.count = count;
3606
3607         ecore_x_e_window_rotation_available_rotations_set(ee->prop.window, rots, count);
3608      }
3609 }
3610
3611 static void
3612 _ecore_evas_x_wm_rot_manual_rotation_done_set(Ecore_Evas *ee, Eina_Bool set)
3613 {
3614    ee->prop.wm_rot.manual_mode.set = set;
3615 }
3616
3617 static void
3618 _ecore_evas_x_wm_rot_manual_rotation_done(Ecore_Evas *ee)
3619 {
3620    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
3621
3622    if ((ee->prop.wm_rot.supported) &&
3623        (ee->prop.wm_rot.app_set) &&
3624        (ee->prop.wm_rot.manual_mode.set))
3625      {
3626         if (ee->prop.wm_rot.manual_mode.wait_for_done)
3627           {
3628              if (ee->prop.wm_rot.manual_mode.timer)
3629                ecore_timer_del(ee->prop.wm_rot.manual_mode.timer);
3630              ee->prop.wm_rot.manual_mode.timer = NULL;
3631
3632              if (edata->wm_rot.manual_mode_job)
3633                ecore_job_del(edata->wm_rot.manual_mode_job);
3634              edata->wm_rot.manual_mode_job = ecore_job_add
3635                (_ecore_evas_x_wm_rot_manual_rotation_done_job, ee);
3636           }
3637      }
3638 }
3639
3640 static Eina_Bool
3641 _ecore_evas_x_wm_rot_manual_rotation_done_timeout(void *data)
3642 {
3643    Ecore_Evas *ee = data;
3644
3645    ee->prop.wm_rot.manual_mode.timer = NULL;
3646    _ecore_evas_x_wm_rot_manual_rotation_done(ee);
3647    return ECORE_CALLBACK_CANCEL;
3648 }
3649
3650 static void
3651 _ecore_evas_x_wm_rot_manual_rotation_done_timeout_update(Ecore_Evas *ee)
3652 {
3653    if (ee->prop.wm_rot.manual_mode.timer)
3654      ecore_timer_del(ee->prop.wm_rot.manual_mode.timer);
3655
3656    ee->prop.wm_rot.manual_mode.timer = ecore_timer_add
3657      (4.0f, _ecore_evas_x_wm_rot_manual_rotation_done_timeout, ee);
3658 }
3659
3660 static void
3661 _ecore_evas_x_aux_hints_set(Ecore_Evas *ee, const char *hints)
3662 {
3663    if (hints)
3664      ecore_x_window_prop_property_set
3665        (ee->prop.window, ECORE_X_ATOM_E_WINDOW_AUX_HINT,
3666         ECORE_X_ATOM_STRING, 8, (void *)hints, strlen(hints) + 1);
3667    else
3668      ecore_x_window_prop_property_del
3669        (ee->prop.window, ECORE_X_ATOM_E_WINDOW_AUX_HINT);
3670 }
3671
3672 static Ecore_Evas_Engine_Func _ecore_x_engine_func =
3673 {
3674    _ecore_evas_x_free,
3675    NULL,
3676    NULL,
3677    NULL,
3678    NULL,
3679    _ecore_evas_x_callback_delete_request_set,
3680    NULL,
3681    NULL,
3682    NULL,
3683    NULL,
3684    NULL,
3685    NULL,
3686    NULL,
3687    NULL,
3688    NULL,
3689    _ecore_evas_x_move,
3690    _ecore_evas_x_managed_move,
3691    _ecore_evas_x_resize,
3692    _ecore_evas_x_move_resize,
3693    _ecore_evas_x_rotation_set,
3694    _ecore_evas_x_shaped_set,
3695    _ecore_evas_x_show,
3696    _ecore_evas_x_hide,
3697    _ecore_evas_x_raise,
3698    _ecore_evas_x_lower,
3699    _ecore_evas_x_activate,
3700    _ecore_evas_x_title_set,
3701    _ecore_evas_x_name_class_set,
3702    _ecore_evas_x_size_min_set,
3703    _ecore_evas_x_size_max_set,
3704    _ecore_evas_x_size_base_set,
3705    _ecore_evas_x_size_step_set,
3706    _ecore_evas_x_object_cursor_set,
3707    _ecore_evas_x_object_cursor_unset,
3708    _ecore_evas_x_layer_set,
3709    _ecore_evas_x_focus_set,
3710    _ecore_evas_x_iconified_set,
3711    _ecore_evas_x_borderless_set,
3712    _ecore_evas_x_override_set,
3713    _ecore_evas_x_maximized_set,
3714    _ecore_evas_x_fullscreen_set,
3715    _ecore_evas_x_avoid_damage_set,
3716    _ecore_evas_x_withdrawn_set,
3717    _ecore_evas_x_sticky_set,
3718    _ecore_evas_x_ignore_events_set,
3719    _ecore_evas_x_alpha_set,
3720    _ecore_evas_x_transparent_set,
3721    _ecore_evas_x_profiles_set,
3722    _ecore_evas_x_profile_set,
3723
3724    _ecore_evas_x_window_group_set,
3725    _ecore_evas_x_aspect_set,
3726    _ecore_evas_x_urgent_set,
3727    _ecore_evas_x_modal_set,
3728    _ecore_evas_x_demand_attention_set,
3729    _ecore_evas_x_focus_skip_set,
3730
3731    NULL, // render
3732    _ecore_evas_x_screen_geometry_get,
3733    _ecore_evas_x_screen_dpi_get,
3734    NULL,
3735    NULL, //fn_msg_send
3736
3737    _ecore_evas_x_pointer_xy_get,
3738    _ecore_evas_x_pointer_warp,
3739
3740    _ecore_evas_x_wm_rot_preferred_rotation_set,
3741    _ecore_evas_x_wm_rot_available_rotations_set,
3742    _ecore_evas_x_wm_rot_manual_rotation_done_set,
3743    _ecore_evas_x_wm_rot_manual_rotation_done,
3744
3745    _ecore_evas_x_aux_hints_set,
3746
3747    NULL, // fn_animator_register
3748    NULL, // fn_animator_unregister
3749
3750    NULL, // fn_evas_changed
3751 };
3752
3753 /*
3754  * FIXME: there are some round trips. Especially, we can split
3755  * ecore_x_init in 2 functions and suppress some round trips.
3756  */
3757
3758 #if defined (BUILD_ECORE_EVAS_SOFTWARE_X11) || defined (BUILD_ECORE_EVAS_OPENGL_X11)
3759 static void
3760 _ecore_evas_x_render_pre(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
3761 {
3762    Ecore_Evas *ee = data;
3763    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
3764
3765    /* printf("Ecore_Evas Render Pre\n"); */
3766    /* printf("\tPixman Size: %d %d\n", edata->pixmap.w, edata->pixmap.h); */
3767    /* printf("\tEE Size: %d %d\n", ee->w, ee->h); */
3768
3769    /* before rendering to the back buffer pixmap, we should check the 
3770     * size. If the back buffer is not the proper size, destroy it and 
3771     * create a new one at the proper size */
3772    if ((edata->pixmap.w != ee->w) || (edata->pixmap.h != ee->h))
3773      {
3774         /* free the backing pixmap */
3775         if (edata->pixmap.back) 
3776           ecore_x_pixmap_free(edata->pixmap.back);
3777
3778         edata->pixmap.back = 
3779           ecore_x_pixmap_new(edata->win_root, ee->w, ee->h, 
3780                              edata->pixmap.depth);
3781
3782         edata->pixmap.w = ee->w;
3783         edata->pixmap.h = ee->h;
3784
3785         if (!strcmp(ee->driver, "software_x11"))
3786           {
3787 # ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
3788              Evas_Engine_Info_Software_X11 *einfo;
3789
3790              einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
3791              if (einfo)
3792                {
3793                   einfo->info.drawable = edata->pixmap.back;
3794
3795                   if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
3796                     {
3797                        ERR("evas_engine_info_set() init engine '%s' failed.", 
3798                            ee->driver);
3799                     }
3800                }
3801 # endif
3802           }
3803         else if (!strcmp(ee->driver, "opengl_x11"))
3804           {
3805 # ifdef BUILD_ECORE_EVAS_OPENGL_X11
3806              Evas_Engine_Info_GL_X11 *einfo;
3807
3808              einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas);
3809              if (einfo)
3810                {
3811                   einfo->info.drawable = edata->pixmap.back;
3812
3813                   if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
3814                     {
3815                        ERR("evas_engine_info_set() init engine '%s' failed.", 
3816                            ee->driver);
3817                     }
3818                }
3819 # endif
3820           }
3821      }
3822 }
3823
3824 static void
3825 _ecore_evas_x_flush_pre(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
3826 {
3827    Ecore_Evas *ee = data;
3828    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
3829
3830    if (ee->no_comp_sync) return;
3831    if (!_ecore_evas_app_comp_sync) return;
3832    if (!edata->sync_counter) return;
3833    if (!edata->sync_began) return;
3834
3835    edata->sync_val++;
3836    if (!edata->sync_cancel)
3837      {
3838         if (!ee->semi_sync)
3839           ecore_x_sync_counter_val_wait(edata->sync_counter,
3840                                         edata->sync_val);
3841      }
3842 }
3843
3844 static void
3845 _ecore_evas_x_flush_post(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
3846 {
3847    Ecore_Evas *ee = data;
3848    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
3849
3850    if ((!ee->prop.window) && (edata->pixmap.back))
3851      {
3852         Ecore_X_Pixmap prev;
3853
3854         /* printf("Ecore_Evas Flush Post\n"); */
3855         /* printf("\tBack Pixmap: %d\n", edata->pixmap.back); */
3856         /* printf("\tFront Pixmap: %d\n", edata->pixmap.front); */
3857
3858         /* done drawing to the back buffer. flip it to the front so that 
3859          * any calls to "fetch pixmap" will return the front buffer already 
3860          * pre-rendered */
3861
3862         /* record the current front buffer */
3863         prev = edata->pixmap.front;
3864
3865         /* flip them */
3866         edata->pixmap.front = edata->pixmap.back;
3867
3868         /* reassign back buffer to be the old front one */
3869         edata->pixmap.back = prev;
3870
3871         /* update evas drawable */
3872         if (!strcmp(ee->driver, "software_x11"))
3873           {
3874 # ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
3875              Evas_Engine_Info_Software_X11 *einfo;
3876
3877              einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
3878              if (einfo)
3879                {
3880                   einfo->info.drawable = edata->pixmap.back;
3881
3882                   if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
3883                     {
3884                        ERR("evas_engine_info_set() init engine '%s' failed.", 
3885                            ee->driver);
3886                     }
3887                }
3888 # endif
3889           }
3890         else if (!strcmp(ee->driver, "opengl_x11"))
3891           {
3892 # ifdef BUILD_ECORE_EVAS_OPENGL_X11
3893              Evas_Engine_Info_GL_X11 *einfo;
3894
3895              einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas);
3896              if (einfo)
3897                {
3898                   einfo->info.drawable = edata->pixmap.back;
3899
3900                   if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
3901                     {
3902                        ERR("evas_engine_info_set() init engine '%s' failed.", 
3903                            ee->driver);
3904                     }
3905                }
3906 # endif
3907           }
3908      }
3909
3910    if ((!ee->no_comp_sync) && (_ecore_evas_app_comp_sync) &&
3911        (ee->gl_sync_draw_done != 1))
3912      {
3913         if (edata->sync_counter)
3914           {
3915              if (edata->sync_began)
3916                {
3917                   if (!edata->sync_cancel)
3918                     {
3919                        if (ee->prop.window)
3920                          {
3921                             ecore_x_e_comp_sync_draw_size_done_send
3922                               (edata->win_root, ee->prop.window, ee->w, ee->h);
3923                          }
3924                     }
3925                }
3926           }
3927      }
3928    if (edata->netwm_sync_set)
3929      {
3930         ecore_x_sync_counter_2_set(edata->netwm_sync_counter,
3931                                    edata->netwm_sync_val_hi,
3932                                    edata->netwm_sync_val_lo);
3933         edata->netwm_sync_set = 0;
3934      }
3935    if (edata->profile.done)
3936      {
3937         if (ee->prop.window)
3938           {
3939              ecore_x_e_window_profile_change_done_send
3940                (edata->win_root, ee->prop.window, ee->prop.profile.name);
3941           }
3942         edata->profile.done = 0;
3943      }
3944    if ((ee->prop.wm_rot.supported) &&
3945        (edata->wm_rot.done))
3946      {
3947         if (!ee->prop.wm_rot.manual_mode.set)
3948           {
3949              ecore_x_e_window_rotation_change_done_send
3950                (edata->win_root, ee->prop.window, ee->rotation, ee->w, ee->h);
3951              edata->wm_rot.done = 0;
3952           }
3953      }
3954 }
3955 #endif
3956
3957 #ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
3958 EAPI Ecore_Evas *
3959 ecore_evas_software_x11_new_internal(const char *disp_name, Ecore_X_Window parent,
3960                                      int x, int y, int w, int h)
3961 {
3962    Evas_Engine_Info_Software_X11 *einfo;
3963    Ecore_Evas_Interface_X11 *iface;
3964    Ecore_Evas_Interface_Software_X11 *siface;
3965    Ecore_Evas_Engine_Data_X11 *edata;
3966    Ecore_Evas *ee;
3967    int argb = 0, rmethod;
3968    static int redraw_debug = -1;
3969    char *id = NULL;
3970
3971    rmethod = evas_render_method_lookup("software_x11");
3972    if (!rmethod) return NULL;
3973    if (!ecore_x_init(disp_name)) return NULL;
3974    ee = calloc(1, sizeof(Ecore_Evas));
3975    if (!ee) return NULL;
3976    edata = calloc(1, sizeof(Ecore_Evas_Engine_Data_X11));
3977    if (!edata)
3978      {
3979         free(ee);
3980         return NULL;
3981      }
3982
3983    ee->engine.data = edata;
3984    iface = _ecore_evas_x_interface_x11_new();
3985    siface = _ecore_evas_x_interface_software_x11_new();
3986
3987    ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface);
3988    ee->engine.ifaces = eina_list_append(ee->engine.ifaces, siface);
3989
3990    ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
3991
3992    _ecore_evas_x_init();
3993
3994    ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_x_engine_func;
3995
3996    ee->driver = "software_x11";
3997    if (disp_name) ee->name = strdup(disp_name);
3998
3999    if (w < 1) w = 1;
4000    if (h < 1) h = 1;
4001    ee->x = x;
4002    ee->y = y;
4003    ee->w = w;
4004    ee->h = h;
4005    ee->req.x = ee->x;
4006    ee->req.y = ee->y;
4007    ee->req.w = ee->w;
4008    ee->req.h = ee->h;
4009
4010    ee->prop.max.w = 32767;
4011    ee->prop.max.h = 32767;
4012    ee->prop.layer = 4;
4013    ee->prop.request_pos = EINA_FALSE;
4014    ee->prop.sticky = 0;
4015    ee->prop.withdrawn = EINA_TRUE;
4016    edata->state.sticky = 0;
4017
4018    if (getenv("ECORE_EVAS_FORCE_SYNC_RENDER"))
4019      ee->can_async_render = 0;
4020    else
4021      ee->can_async_render = 1;
4022
4023    /* init evas here */
4024    ee->evas = evas_new();
4025    evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_PRE,
4026                            _ecore_evas_x_flush_pre, ee);
4027    evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_POST,
4028                            _ecore_evas_x_flush_post, ee);
4029    if (ee->can_async_render)
4030      evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST,
4031                              _ecore_evas_x_render_updates, ee);
4032    evas_data_attach_set(ee->evas, ee);
4033    evas_output_method_set(ee->evas, rmethod);
4034    evas_output_size_set(ee->evas, w, h);
4035    evas_output_viewport_set(ee->evas, 0, 0, w, h);
4036
4037    edata->win_root = parent;
4038    edata->screen_num = 0;
4039
4040    if (parent != 0)
4041      {
4042         edata->screen_num = 1; /* FIXME: get real scren # */
4043        /* FIXME: round trip in ecore_x_window_argb_get */
4044         if (ecore_x_window_argb_get(parent))
4045           {
4046              ee->prop.window = ecore_x_window_argb_new(parent, x, y, w, h);
4047              argb = 1;
4048           }
4049         else
4050           ee->prop.window = ecore_x_window_new(parent, x, y, w, h);
4051      }
4052    else
4053      ee->prop.window = ecore_x_window_new(parent, x, y, w, h);
4054    ecore_x_vsync_animator_tick_source_set(ee->prop.window);
4055    if ((id = getenv("DESKTOP_STARTUP_ID")))
4056      {
4057         ecore_x_netwm_startup_id_set(ee->prop.window, id);
4058         /* NB: on linux this may simply empty the env as opposed to completely
4059          * unset it to being empty - unsure as solartis libc crashes looking
4060          * for the '=' char */
4061 //        putenv((char*)"DESKTOP_STARTUP_ID=");
4062      }
4063    einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
4064    if (einfo)
4065      {
4066         Ecore_X_Screen *screen;
4067
4068         /* FIXME: this is inefficient as its 1 or more round trips */
4069         screen = ecore_x_default_screen_get();
4070         if (ecore_x_screen_count_get() > 1)
4071           {
4072              Ecore_X_Window *roots;
4073              int num, i;
4074
4075              num = 0;
4076              roots = ecore_x_window_root_list(&num);
4077              if (roots)
4078                {
4079                   Ecore_X_Window root;
4080
4081                   root = ecore_x_window_root_get(parent);
4082                   for (i = 0; i < num; i++)
4083                     {
4084                        if (root == roots[i])
4085                          {
4086                             screen = ecore_x_screen_get(i);
4087                             break;
4088                          }
4089                     }
4090                   free(roots);
4091                }
4092           }
4093
4094         einfo->info.destination_alpha = argb;
4095
4096         if (redraw_debug < 0)
4097           {
4098              if (getenv("REDRAW_DEBUG"))
4099                redraw_debug = atoi(getenv("REDRAW_DEBUG"));
4100              else
4101                redraw_debug = 0;
4102           }
4103
4104 # ifdef BUILD_ECORE_EVAS_SOFTWARE_XCB
4105         einfo->info.backend = EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XCB;
4106         einfo->info.connection = ecore_x_connection_get();
4107         einfo->info.screen = screen;
4108 # else
4109         einfo->info.backend = EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB;
4110         einfo->info.connection = ecore_x_display_get();
4111         einfo->info.screen = NULL;
4112 # endif
4113         einfo->info.drawable = ee->prop.window;
4114
4115         if (argb)
4116           {
4117              Ecore_X_Window_Attributes at;
4118
4119              ecore_x_window_attributes_get(ee->prop.window, &at);
4120              einfo->info.visual = at.visual;
4121              einfo->info.colormap = at.colormap;
4122              einfo->info.depth = at.depth;
4123              einfo->info.destination_alpha = 1;
4124           }
4125         else
4126           {
4127              einfo->info.visual =
4128                ecore_x_default_visual_get(einfo->info.connection, screen);
4129              einfo->info.colormap =
4130                ecore_x_default_colormap_get(einfo->info.connection, screen);
4131              einfo->info.depth =
4132                ecore_x_default_depth_get(einfo->info.connection, screen);
4133              einfo->info.destination_alpha = 0;
4134           }
4135
4136         einfo->info.rotation = 0;
4137         einfo->info.debug = redraw_debug;
4138         if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
4139           {
4140              ERR("evas_engine_info_set() init engine '%s' failed.", ee->driver);
4141              ecore_evas_free(ee);
4142              return NULL;
4143           }
4144      }
4145
4146    _ecore_evas_x_hints_update(ee);
4147    _ecore_evas_x_group_leader_set(ee);
4148    ecore_x_window_defaults_set(ee->prop.window);
4149    _ecore_evas_x_protocols_set(ee);
4150    _ecore_evas_x_window_profile_protocol_set(ee);
4151    _ecore_evas_x_wm_rotation_protocol_set(ee);
4152    _ecore_evas_x_aux_hints_supported_update(ee);
4153    _ecore_evas_x_aux_hints_update(ee);
4154    _ecore_evas_x_sync_set(ee);
4155
4156    ee->engine.func->fn_render = _ecore_evas_x_render;
4157    _ecore_evas_register(ee);
4158    ecore_x_input_multi_select(ee->prop.window);
4159    ecore_event_window_register(ee->prop.window, ee, ee->evas,
4160                                (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
4161                                (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
4162                                (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
4163                                (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
4164    _ecore_event_window_direct_cb_set(ee->prop.window, _ecore_evas_input_direct_cb);
4165
4166    return ee;
4167 }
4168
4169 EAPI Ecore_Evas *
4170 ecore_evas_software_x11_pixmap_new_internal(const char *disp_name, Ecore_X_Window parent,
4171                                             int x, int y, int w, int h)
4172 {
4173    Evas_Engine_Info_Software_X11 *einfo;
4174    Ecore_Evas_Interface_X11 *iface;
4175    Ecore_Evas_Interface_Software_X11 *siface;
4176    Ecore_Evas_Engine_Data_X11 *edata;
4177    Ecore_Evas *ee;
4178    int argb = 0, rmethod;
4179    static int redraw_debug = -1;
4180
4181    rmethod = evas_render_method_lookup("software_x11");
4182    if (!rmethod) return NULL;
4183    if (!ecore_x_init(disp_name)) return NULL;
4184    ee = calloc(1, sizeof(Ecore_Evas));
4185    if (!ee) return NULL;
4186    edata = calloc(1, sizeof(Ecore_Evas_Engine_Data_X11));
4187    if (!edata)
4188      {
4189         free(ee);
4190         return NULL;
4191      }
4192
4193    ee->engine.data = edata;
4194    iface = _ecore_evas_x_interface_x11_new();
4195    siface = _ecore_evas_x_interface_software_x11_new();
4196
4197    ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface);
4198    ee->engine.ifaces = eina_list_append(ee->engine.ifaces, siface);
4199
4200    ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
4201
4202    _ecore_evas_x_init();
4203
4204    ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_x_engine_func;
4205
4206    ee->driver = "software_x11";
4207    if (disp_name) ee->name = strdup(disp_name);
4208
4209    if (w < 1) w = 1;
4210    if (h < 1) h = 1;
4211    ee->x = x;
4212    ee->y = y;
4213    ee->w = w;
4214    ee->h = h;
4215    ee->req.x = ee->x;
4216    ee->req.y = ee->y;
4217    ee->req.w = ee->w;
4218    ee->req.h = ee->h;
4219
4220    ee->prop.max.w = 32767;
4221    ee->prop.max.h = 32767;
4222    ee->prop.layer = 4;
4223    ee->prop.request_pos = EINA_FALSE;
4224    ee->prop.sticky = 0;
4225    edata->state.sticky = 0;
4226
4227    if (getenv("ECORE_EVAS_FORCE_SYNC_RENDER"))
4228      ee->can_async_render = 0;
4229    else
4230      ee->can_async_render = 1;
4231
4232    /* init evas here */
4233    ee->evas = evas_new();
4234
4235    evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_PRE,
4236                            _ecore_evas_x_flush_pre, ee);
4237    evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_POST,
4238                            _ecore_evas_x_flush_post, ee);
4239    evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_PRE, 
4240                            _ecore_evas_x_render_pre, ee);
4241
4242    if (ee->can_async_render)
4243      evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST,
4244                              _ecore_evas_x_render_updates, ee);
4245    evas_data_attach_set(ee->evas, ee);
4246    evas_output_method_set(ee->evas, rmethod);
4247    evas_output_size_set(ee->evas, w, h);
4248    evas_output_viewport_set(ee->evas, 0, 0, w, h);
4249
4250    edata->win_root = parent;
4251    edata->screen_num = 0;
4252    edata->direct_resize = 1;
4253
4254    if (parent != 0)
4255      {
4256         edata->screen_num = 1; /* FIXME: get real scren # */
4257        /* FIXME: round trip in ecore_x_window_argb_get */
4258         if (ecore_x_window_argb_get(parent))
4259           argb = 1;
4260      }
4261
4262    /* if ((id = getenv("DESKTOP_STARTUP_ID"))) */
4263    /*   { */
4264         /* ecore_x_netwm_startup_id_set(ee->prop.window, id); */
4265         /* NB: on linux this may simply empty the env as opposed to completely
4266          * unset it to being empty - unsure as solartis libc crashes looking
4267          * for the '=' char */
4268 //        putenv((char*)"DESKTOP_STARTUP_ID=");
4269      /* } */
4270
4271    einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas);
4272    if (einfo)
4273      {
4274         Ecore_X_Screen *screen;
4275
4276         /* FIXME: this is inefficient as its 1 or more round trips */
4277         screen = ecore_x_default_screen_get();
4278         if (ecore_x_screen_count_get() > 1)
4279           {
4280              Ecore_X_Window *roots;
4281              int num, i;
4282
4283              num = 0;
4284              roots = ecore_x_window_root_list(&num);
4285              if (roots)
4286                {
4287                   Ecore_X_Window root;
4288
4289                   root = ecore_x_window_root_get(parent);
4290                   for (i = 0; i < num; i++)
4291                     {
4292                        if (root == roots[i])
4293                          {
4294                             screen = ecore_x_screen_get(i);
4295                             break;
4296                          }
4297                     }
4298                   free(roots);
4299                }
4300           }
4301
4302         einfo->info.destination_alpha = argb;
4303
4304         if (redraw_debug < 0)
4305           {
4306              if (getenv("REDRAW_DEBUG"))
4307                redraw_debug = atoi(getenv("REDRAW_DEBUG"));
4308              else
4309                redraw_debug = 0;
4310           }
4311
4312 # ifdef BUILD_ECORE_EVAS_SOFTWARE_XCB
4313         einfo->info.backend = EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XCB;
4314         einfo->info.connection = ecore_x_connection_get();
4315         einfo->info.screen = screen;
4316 # else
4317         einfo->info.backend = EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB;
4318         einfo->info.connection = ecore_x_display_get();
4319         einfo->info.screen = NULL;
4320 # endif
4321
4322         if ((argb) && (ee->prop.window))
4323           {
4324              Ecore_X_Window_Attributes at;
4325
4326              ecore_x_window_attributes_get(ee->prop.window, &at);
4327              einfo->info.visual = at.visual;
4328              einfo->info.colormap = at.colormap;
4329              einfo->info.depth = at.depth;
4330              einfo->info.destination_alpha = 1;
4331           }
4332         else
4333           {
4334              einfo->info.visual =
4335                ecore_x_default_visual_get(einfo->info.connection, screen);
4336              einfo->info.colormap =
4337                ecore_x_default_colormap_get(einfo->info.connection, screen);
4338              einfo->info.depth =
4339                ecore_x_default_depth_get(einfo->info.connection, screen);
4340              einfo->info.destination_alpha = 0;
4341           }
4342
4343         einfo->info.rotation = 0;
4344         einfo->info.debug = redraw_debug;
4345
4346         /* record pixmap size to save X roundtrips */
4347         edata->pixmap.w = w;
4348         edata->pixmap.h = h;
4349         edata->pixmap.depth = einfo->info.depth;
4350         edata->pixmap.visual = einfo->info.visual;
4351         edata->pixmap.colormap = einfo->info.colormap;
4352
4353         /* create front and back pixmaps for double-buffer rendering */
4354         edata->pixmap.front = 
4355           ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth);
4356         edata->pixmap.back = 
4357           ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth);
4358
4359         einfo->info.drawable = edata->pixmap.back;
4360
4361         if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
4362           {
4363              ERR("evas_engine_info_set() init engine '%s' failed.", ee->driver);
4364              ecore_evas_free(ee);
4365              return NULL;
4366           }
4367      }
4368
4369    /* FIXME: Allow of these set properties or do something with the 
4370     * ee->prop.window (x window), which we do not have in pixmap case */
4371
4372    /* _ecore_evas_x_hints_update(ee); */
4373    /* _ecore_evas_x_group_leader_set(ee); */
4374    /* ecore_x_window_defaults_set(ee->prop.window); */
4375    /* _ecore_evas_x_protocols_set(ee); */
4376    /* _ecore_evas_x_window_profile_protocol_set(ee); */
4377    /* _ecore_evas_x_sync_set(ee); */
4378
4379    ee->engine.func->fn_render = _ecore_evas_x_render;
4380    _ecore_evas_register(ee);
4381
4382    ee->draw_ok = 1;
4383
4384    /* ecore_x_input_multi_select(ee->prop.window); */
4385    /* ecore_event_window_register(ee->prop.window, ee, ee->evas, */
4386    /*                             (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process, */
4387    /*                             (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process, */
4388    /*                             (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process, */
4389    /*                             (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process); */
4390
4391    return ee;
4392 }
4393
4394 static Ecore_X_Window
4395 _ecore_evas_software_x11_window_get(const Ecore_Evas *ee)
4396 {
4397    if (!(!strcmp(ee->driver, "software_x11"))) return 0;
4398    return (Ecore_X_Window) ecore_evas_window_get(ee);
4399 }
4400
4401 static Ecore_X_Pixmap
4402 _ecore_evas_software_x11_pixmap_get(const Ecore_Evas *ee)
4403 {
4404    if (!(!strcmp(ee->driver, "software_x11"))) return 0;
4405    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4406    return (Ecore_X_Pixmap) edata->pixmap.front;
4407 }
4408
4409 static void *
4410 _ecore_evas_software_x11_pixmap_visual_get(const Ecore_Evas *ee)
4411 {
4412    if (!(!strcmp(ee->driver, "software_x11"))) return 0;
4413    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4414    return edata->pixmap.visual;
4415 }
4416
4417 static unsigned long 
4418 _ecore_evas_software_x11_pixmap_colormap_get(const Ecore_Evas *ee)
4419 {
4420    if (!(!strcmp(ee->driver, "software_x11"))) return 0;
4421    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4422    return edata->pixmap.colormap;
4423 }
4424
4425 static int 
4426 _ecore_evas_software_x11_pixmap_depth_get(const Ecore_Evas *ee)
4427 {
4428    if (!(!strcmp(ee->driver, "software_x11"))) return 0;
4429    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4430    return edata->pixmap.depth;
4431 }
4432
4433 static void
4434 _ecore_evas_software_x11_direct_resize_set(Ecore_Evas *ee, Eina_Bool on)
4435 {
4436    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4437    edata->direct_resize = on;
4438    if (ee->prop.avoid_damage)
4439      {
4440         if (edata->direct_resize)
4441           {
4442 /* turn this off for now
4443              ee->engine.x.using_bg_pixmap = 1;
4444              ecore_x_window_pixmap_set(ee->prop.window, ee->engine.x.pmap);
4445  */
4446           }
4447         else
4448           {
4449 /* turn this off too- bg pixmap is controlled by avoid damage directly
4450              ee->engine.x.using_bg_pixmap = 0;
4451              ecore_x_window_pixmap_set(ee->prop.window, 0);
4452              ecore_x_window_area_expose(ee->prop.window, 0, 0, ee->w, ee->h);
4453  */
4454           }
4455      }
4456 }
4457
4458 static Eina_Bool
4459 _ecore_evas_software_x11_direct_resize_get(const Ecore_Evas *ee)
4460 {
4461    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4462
4463    return edata->direct_resize;
4464 }
4465
4466 static void
4467 _ecore_evas_software_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window win)
4468 {
4469    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4470    Ecore_X_Window *winp;
4471
4472    winp = malloc(sizeof(Ecore_X_Window));
4473    if (winp)
4474      {
4475         *winp = win;
4476         edata->win_extra = eina_list_append(edata->win_extra, winp);
4477         ecore_x_input_multi_select(win);
4478         ecore_event_window_register(win, ee, ee->evas,
4479                                     (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
4480                                     (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
4481                                     (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
4482                                     (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
4483         _ecore_event_window_direct_cb_set(win, _ecore_evas_input_direct_cb);
4484      }
4485 }
4486 #endif
4487
4488 #ifdef BUILD_ECORE_EVAS_OPENGL_X11
4489 EAPI Ecore_Evas *
4490 ecore_evas_gl_x11_options_new_internal(const char *disp_name, Ecore_X_Window parent,
4491                                        int x, int y, int w, int h, const int *opt)
4492 {
4493    Ecore_Evas *ee;
4494    Ecore_Evas_Engine_Data_X11 *edata;
4495    Ecore_Evas_Interface_X11 *iface;
4496    Ecore_Evas_Interface_Gl_X11 *giface;
4497    int rmethod;
4498    char *id = NULL;
4499
4500    rmethod = evas_render_method_lookup("gl_x11");
4501    if (!rmethod) return NULL;
4502    if (!ecore_x_init(disp_name)) return NULL;
4503    ee = calloc(1, sizeof(Ecore_Evas));
4504    if (!ee) return NULL;
4505    edata = calloc(1, sizeof(Ecore_Evas_Engine_Data_X11));
4506    if (!edata)
4507      {
4508         free(ee);
4509         return NULL;
4510      }
4511
4512    iface = _ecore_evas_x_interface_x11_new();
4513    giface = _ecore_evas_x_interface_gl_x11_new();
4514
4515    ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface);
4516    ee->engine.ifaces = eina_list_append(ee->engine.ifaces, giface);
4517
4518    ee->engine.data = edata;
4519
4520    ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
4521
4522    ee->gl_sync_draw_done = -1;
4523
4524    _ecore_evas_x_init();
4525
4526    ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_x_engine_func;
4527
4528    ee->driver = "opengl_x11";
4529 #if 1
4530    ee->semi_sync = 0; // gl engine doesn't need to sync - its whole swaps
4531 #else
4532    if (!getenv("ECORE_EVAS_COMP_NOSEMISYNC"))
4533       ee->semi_sync = 1; // gl engine doesn't need to sync - its whole swaps
4534 //   ee->no_comp_sync = 1; // gl engine doesn't need to sync - its whole swaps
4535 #endif
4536    if (disp_name) ee->name = strdup(disp_name);
4537
4538    if (w < 1) w = 1;
4539    if (h < 1) h = 1;
4540    ee->x = x;
4541    ee->y = y;
4542    ee->w = w;
4543    ee->h = h;
4544    ee->req.x = ee->x;
4545    ee->req.y = ee->y;
4546    ee->req.w = ee->w;
4547    ee->req.h = ee->h;
4548
4549    ee->prop.max.w = 32767;
4550    ee->prop.max.h = 32767;
4551    ee->prop.layer = 4;
4552    ee->prop.request_pos = EINA_FALSE;
4553    ee->prop.sticky = 0;
4554    ee->prop.withdrawn = EINA_TRUE;
4555    edata->state.sticky = 0;
4556
4557    /* init evas here */
4558    ee->evas = evas_new();
4559    evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_PRE, _ecore_evas_x_flush_pre, ee);
4560    evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_POST, _ecore_evas_x_flush_post, ee);
4561    evas_data_attach_set(ee->evas, ee);
4562    evas_output_method_set(ee->evas, rmethod);
4563    evas_output_size_set(ee->evas, w, h);
4564    evas_output_viewport_set(ee->evas, 0, 0, w, h);
4565
4566    if (parent == 0) parent = ecore_x_window_root_first_get();
4567    edata->win_root = parent;
4568
4569    if (edata->win_root != 0)
4570      {
4571         edata->screen_num = 1; /* FIXME: get real scren # */
4572        /* FIXME: round trip in ecore_x_window_argb_get */
4573         if (ecore_x_window_argb_get(edata->win_root))
4574           {
4575              ee->prop.window = _ecore_evas_x_gl_window_new
4576                (ee, edata->win_root, x, y, w, h, 0, 1, opt);
4577           }
4578         else
4579           ee->prop.window = _ecore_evas_x_gl_window_new
4580           (ee, edata->win_root, x, y, w, h, 0, 0, opt);
4581      }
4582    else
4583      ee->prop.window = _ecore_evas_x_gl_window_new
4584      (ee, edata->win_root, x, y, w, h, 0, 0, opt);
4585    if (!ee->prop.window)
4586      {
4587         ERR("evas_engine_info_set() init engine '%s' failed.", ee->driver);
4588         ecore_evas_free(ee);
4589         return NULL;
4590      }
4591    if ((id = getenv("DESKTOP_STARTUP_ID")))
4592      {
4593         ecore_x_netwm_startup_id_set(ee->prop.window, id);
4594         /* NB: on linux this may simply empty the env as opposed to completely
4595          * unset it to being empty - unsure as solartis libc crashes looking
4596          * for the '=' char */
4597 //        putenv((char*)"DESKTOP_STARTUP_ID=");
4598      }
4599
4600    _ecore_evas_x_hints_update(ee);
4601    _ecore_evas_x_group_leader_set(ee);
4602    ecore_x_window_defaults_set(ee->prop.window);
4603    _ecore_evas_x_protocols_set(ee);
4604    _ecore_evas_x_window_profile_protocol_set(ee);
4605    _ecore_evas_x_wm_rotation_protocol_set(ee);
4606    _ecore_evas_x_aux_hints_supported_update(ee);
4607    _ecore_evas_x_aux_hints_update(ee);
4608    _ecore_evas_x_sync_set(ee);
4609
4610    ee->engine.func->fn_render = _ecore_evas_x_render;
4611    _ecore_evas_register(ee);
4612    ecore_x_input_multi_select(ee->prop.window);
4613    ecore_event_window_register(ee->prop.window, ee, ee->evas,
4614                                (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
4615                                (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
4616                                (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
4617                                (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
4618    _ecore_event_window_direct_cb_set(ee->prop.window, _ecore_evas_input_direct_cb);
4619
4620    return ee;
4621 }
4622
4623 EAPI Ecore_Evas *
4624 ecore_evas_gl_x11_new_internal(const char *disp_name, Ecore_X_Window parent,
4625                       int x, int y, int w, int h)
4626 {
4627    return ecore_evas_gl_x11_options_new_internal(disp_name, parent, x, y, w, h, NULL);
4628 }
4629
4630 EAPI Ecore_Evas *
4631 ecore_evas_gl_x11_pixmap_new_internal(const char *disp_name, Ecore_X_Window parent,
4632                                       int x, int y, int w, int h)
4633 {
4634    Ecore_Evas *ee;
4635    Ecore_Evas_Engine_Data_X11 *edata;
4636    Ecore_Evas_Interface_X11 *iface;
4637    Ecore_Evas_Interface_Gl_X11 *giface;
4638    Evas_Engine_Info_GL_X11 *einfo;
4639    int rmethod, argb = 0;
4640    static int redraw_debug = -1;
4641
4642    rmethod = evas_render_method_lookup("gl_x11");
4643    if (!rmethod) return NULL;
4644    if (!ecore_x_init(disp_name)) return NULL;
4645    ee = calloc(1, sizeof(Ecore_Evas));
4646    if (!ee) return NULL;
4647    edata = calloc(1, sizeof(Ecore_Evas_Engine_Data_X11));
4648    if (!edata)
4649      {
4650         free(ee);
4651         return NULL;
4652      }
4653
4654    iface = _ecore_evas_x_interface_x11_new();
4655    giface = _ecore_evas_x_interface_gl_x11_new();
4656
4657    ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface);
4658    ee->engine.ifaces = eina_list_append(ee->engine.ifaces, giface);
4659
4660    ee->engine.data = edata;
4661
4662    ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
4663
4664    ee->gl_sync_draw_done = -1;
4665
4666    _ecore_evas_x_init();
4667
4668    ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_x_engine_func;
4669
4670    ee->driver = "opengl_x11";
4671 #if 1
4672    ee->semi_sync = 0; // gl engine doesn't need to sync - its whole swaps
4673 #else
4674    if (!getenv("ECORE_EVAS_COMP_NOSEMISYNC"))
4675       ee->semi_sync = 1; // gl engine doesn't need to sync - its whole swaps
4676 //   ee->no_comp_sync = 1; // gl engine doesn't need to sync - its whole swaps
4677 #endif
4678    if (disp_name) ee->name = strdup(disp_name);
4679
4680    if (w < 1) w = 1;
4681    if (h < 1) h = 1;
4682    ee->x = x;
4683    ee->y = y;
4684    ee->w = w;
4685    ee->h = h;
4686    ee->req.x = ee->x;
4687    ee->req.y = ee->y;
4688    ee->req.w = ee->w;
4689    ee->req.h = ee->h;
4690
4691    ee->prop.max.w = 32767;
4692    ee->prop.max.h = 32767;
4693    ee->prop.layer = 4;
4694    ee->prop.request_pos = EINA_FALSE;
4695    ee->prop.sticky = 0;
4696    edata->state.sticky = 0;
4697
4698    /* init evas here */
4699    ee->evas = evas_new();
4700    evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_PRE, 
4701                            _ecore_evas_x_flush_pre, ee);
4702    evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_FLUSH_POST, 
4703                            _ecore_evas_x_flush_post, ee);
4704    evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_PRE, 
4705                            _ecore_evas_x_render_pre, ee);
4706    evas_data_attach_set(ee->evas, ee);
4707    evas_output_method_set(ee->evas, rmethod);
4708    evas_output_size_set(ee->evas, w, h);
4709    evas_output_viewport_set(ee->evas, 0, 0, w, h);
4710
4711    if (ee->can_async_render)
4712      evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST,
4713                              _ecore_evas_x_render_updates, ee);
4714
4715    if (parent == 0) parent = ecore_x_window_root_first_get();
4716    edata->win_root = parent;
4717
4718    if (parent != 0)
4719      {
4720         edata->screen_num = 1; /* FIXME: get real scren # */
4721        /* FIXME: round trip in ecore_x_window_argb_get */
4722         if (ecore_x_window_argb_get(parent))
4723           argb = 1;
4724      }
4725
4726    edata->direct_resize = 1;
4727
4728    einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas);
4729    if (einfo)
4730      {
4731         int screen = 0;
4732
4733         /* FIXME: this is inefficient as its 1 or more round trips */
4734         screen = ecore_x_screen_index_get(ecore_x_default_screen_get());
4735         if (ecore_x_screen_count_get() > 1)
4736           {
4737              Ecore_X_Window *roots;
4738              int num, i;
4739
4740              num = 0;
4741              roots = ecore_x_window_root_list(&num);
4742              if (roots)
4743                {
4744                   Ecore_X_Window root;
4745
4746                   root = ecore_x_window_root_get(parent);
4747                   for (i = 0; i < num; i++)
4748                     {
4749                        if (root == roots[i])
4750                          {
4751                             screen = i;
4752                             break;
4753                          }
4754                     }
4755                   free(roots);
4756                }
4757           }
4758
4759         einfo->info.display = ecore_x_display_get();
4760         einfo->info.screen = screen;
4761
4762         einfo->info.destination_alpha = argb;
4763
4764         einfo->info.visual = einfo->func.best_visual_get(einfo);
4765         einfo->info.colormap = einfo->func.best_colormap_get(einfo);
4766         einfo->info.depth = einfo->func.best_depth_get(einfo);
4767
4768         if (redraw_debug < 0)
4769           {
4770              if (getenv("REDRAW_DEBUG"))
4771                redraw_debug = atoi(getenv("REDRAW_DEBUG"));
4772              else
4773                redraw_debug = 0;
4774           }
4775
4776         einfo->info.rotation = 0;
4777
4778         /* record pixmap size to save X roundtrips */
4779         edata->pixmap.w = w;
4780         edata->pixmap.h = h;
4781         edata->pixmap.depth = einfo->info.depth;
4782         edata->pixmap.visual = einfo->info.visual;
4783         edata->pixmap.colormap = einfo->info.colormap;
4784
4785         /* create front and back pixmaps for double-buffer rendering */
4786         edata->pixmap.front = 
4787           ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth);
4788         edata->pixmap.back = 
4789           ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth);
4790
4791         einfo->info.drawable = edata->pixmap.back;
4792
4793         if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
4794           {
4795              ERR("evas_engine_info_set() init engine '%s' failed.", ee->driver);
4796              ecore_evas_free(ee);
4797              return NULL;
4798           }
4799      }
4800
4801    /* _ecore_evas_x_hints_update(ee); */
4802    /* _ecore_evas_x_group_leader_set(ee); */
4803    /* ecore_x_window_defaults_set(ee->prop.window); */
4804    /* _ecore_evas_x_protocols_set(ee); */
4805    /* _ecore_evas_x_window_profile_protocol_set(ee); */
4806    /* _ecore_evas_x_sync_set(ee); */
4807
4808    ee->engine.func->fn_render = _ecore_evas_x_render;
4809    _ecore_evas_register(ee);
4810
4811    /* ecore_x_input_multi_select(ee->prop.window); */
4812    /* ecore_event_window_register(ee->prop.window, ee, ee->evas, */
4813    /*                             (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process, */
4814    /*                             (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process, */
4815    /*                             (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process, */
4816    /*                             (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process); */
4817
4818    return ee;
4819 }
4820
4821 static Ecore_X_Window
4822 _ecore_evas_gl_x11_window_get(const Ecore_Evas *ee)
4823 {
4824    if (!(!strcmp(ee->driver, "opengl_x11"))) return 0;
4825    return (Ecore_X_Window) ecore_evas_window_get(ee);
4826 }
4827
4828 static Ecore_X_Pixmap
4829 _ecore_evas_gl_x11_pixmap_get(const Ecore_Evas *ee)
4830 {
4831    if (!(!strcmp(ee->driver, "opengl_x11"))) return 0;
4832    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4833    return (Ecore_X_Pixmap) edata->pixmap.front;
4834 }
4835
4836 static void *
4837 _ecore_evas_gl_x11_pixmap_visual_get(const Ecore_Evas *ee)
4838 {
4839    if (!(!strcmp(ee->driver, "opengl_x11"))) return 0;
4840    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4841    return edata->pixmap.visual;
4842 }
4843
4844 static unsigned long 
4845 _ecore_evas_gl_x11_pixmap_colormap_get(const Ecore_Evas *ee)
4846 {
4847    if (!(!strcmp(ee->driver, "opengl_x11"))) return 0;
4848    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4849    return edata->pixmap.colormap;
4850 }
4851
4852 static int 
4853 _ecore_evas_gl_x11_pixmap_depth_get(const Ecore_Evas *ee)
4854 {
4855    if (!(!strcmp(ee->driver, "opengl_x11"))) return 0;
4856    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4857    return edata->pixmap.depth;
4858 }
4859
4860 static void
4861 _ecore_evas_gl_x11_direct_resize_set(Ecore_Evas *ee, Eina_Bool on)
4862 {
4863    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4864    edata->direct_resize = on;
4865 }
4866
4867 static Eina_Bool
4868 _ecore_evas_gl_x11_direct_resize_get(const Ecore_Evas *ee)
4869 {
4870    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4871
4872    return edata->direct_resize;
4873 }
4874
4875 static void
4876 _ecore_evas_gl_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window win)
4877 {
4878    ecore_evas_software_x11_extra_event_window_add(ee, win);
4879 }
4880
4881 static void
4882 _ecore_evas_gl_x11_pre_post_swap_callback_set(const Ecore_Evas *ee, void *data, void (*pre_cb) (void *data, Evas *e), void (*post_cb) (void *data, Evas *e))
4883 {
4884    Evas_Engine_Info_GL_X11 *einfo;
4885
4886    if (!(!strcmp(ee->driver, "opengl_x11"))) return;
4887
4888    einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas);
4889    if (einfo)
4890      {
4891         einfo->callback.pre_swap = pre_cb;
4892         einfo->callback.post_swap = post_cb;
4893         einfo->callback.data = data;
4894         if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
4895           {
4896              ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
4897           }
4898      }
4899 }
4900 #endif /* ! BUILD_ECORE_EVAS_OPENGL_X11 */
4901
4902 static void
4903 _ecore_evas_x11_leader_set(Ecore_Evas *ee, Ecore_X_Window win)
4904 {
4905    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4906
4907    _ecore_evas_x_group_leader_unset(ee);
4908    edata->leader = win;
4909    _ecore_evas_x_group_leader_update(ee);
4910 }
4911
4912 static Ecore_X_Window
4913 _ecore_evas_x11_leader_get(Ecore_Evas *ee)
4914 {
4915    Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
4916
4917    return edata->leader;
4918 }
4919
4920 static void
4921 _ecore_evas_x11_leader_default_set(Ecore_Evas *ee)
4922 {
4923    _ecore_evas_x_group_leader_unset(ee);
4924    _ecore_evas_x_group_leader_set(ee);
4925 }
4926
4927 static Eina_Bool
4928 _ecore_evas_x11_convert_rectangle_with_angle(Ecore_Evas *ee, Ecore_X_Rectangle *dst_rect, Ecore_X_Rectangle *src_rect)
4929 {
4930    if ((!src_rect) || (!dst_rect)) return 0;
4931
4932    if (ee->rotation == 0)
4933      {
4934         dst_rect->x = src_rect->x;
4935         dst_rect->y = src_rect->y;
4936         dst_rect->width = src_rect->width;
4937         dst_rect->height = src_rect->height;
4938      }
4939    else if (ee->rotation == 90)
4940      {
4941         dst_rect->x = src_rect->y;
4942         dst_rect->y = ee->req.h - src_rect->x - src_rect->width;
4943         dst_rect->width = src_rect->height;
4944         dst_rect->height = src_rect->width;
4945      }
4946    else if (ee->rotation == 180)
4947      {
4948         dst_rect->x = ee->req.w - src_rect->x - src_rect->width;
4949         dst_rect->y = ee->req.h - src_rect->y - src_rect->height;
4950         dst_rect->width = src_rect->width;
4951         dst_rect->height = src_rect->height;
4952      }
4953    else if (ee->rotation == 270)
4954      {
4955         dst_rect->x = ee->req.w - src_rect->y - src_rect->height;
4956         dst_rect->y = src_rect->x;
4957         dst_rect->width = src_rect->height;
4958         dst_rect->height = src_rect->width;
4959      }
4960    else
4961      {
4962         return 0;
4963      }
4964
4965    return 1;
4966 }
4967
4968 static void
4969 _ecore_evas_x11_shape_input_rectangle_set(Ecore_Evas *ee, int x, int y, int w, int h)
4970 {
4971    Eina_Bool ret;
4972    Ecore_X_Rectangle src_rect;
4973    Ecore_X_Rectangle dst_rect;
4974    Ecore_Evas_Engine_Data_X11 *edata;
4975
4976    if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
4977      {
4978         ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
4979                          "ecore_evas_x11_shape_input_rectangle_set");
4980         return;
4981      }
4982
4983    edata = ee->engine.data;
4984    src_rect.x = x;
4985    src_rect.y = y;
4986    src_rect.width = w;
4987    src_rect.height = h;
4988
4989    dst_rect.x = 0;
4990    dst_rect.y = 0;
4991    dst_rect.width = 0;
4992    dst_rect.height = 0;
4993
4994    ret = _ecore_evas_x11_convert_rectangle_with_angle(ee, &dst_rect, &src_rect);
4995
4996    if (!edata->win_shaped_input)
4997       edata->win_shaped_input = ecore_x_window_override_new(edata->win_root,
4998                                                                   0, 0, 1, 1);
4999
5000    if (ret)
5001       ecore_x_window_shape_input_rectangle_set(edata->win_shaped_input,
5002                                                dst_rect.x, dst_rect.y,
5003                                                dst_rect.width, dst_rect.height);
5004 }
5005
5006 static void
5007 _ecore_evas_x11_shape_input_rectangle_add(Ecore_Evas *ee, int x, int y, int w, int h)
5008 {
5009    Eina_Bool ret;
5010    Ecore_X_Rectangle src_rect;
5011    Ecore_X_Rectangle dst_rect;
5012    Ecore_Evas_Engine_Data_X11 *edata;
5013
5014    if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
5015      {
5016         ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
5017                          "ecore_evas_x11_shape_input_rectangle_add");
5018         return;
5019      }
5020
5021    edata = ee->engine.data;
5022    src_rect.x = x;
5023    src_rect.y = y;
5024    src_rect.width = w;
5025    src_rect.height = h;
5026
5027    dst_rect.x = 0;
5028    dst_rect.y = 0;
5029    dst_rect.width = 0;
5030    dst_rect.height = 0;
5031
5032    ret = _ecore_evas_x11_convert_rectangle_with_angle(ee, &dst_rect, &src_rect);
5033
5034    if (!edata->win_shaped_input)
5035       edata->win_shaped_input = ecore_x_window_override_new(edata->win_root,
5036                                                                   0, 0, 1, 1);
5037
5038    if (ret)
5039       ecore_x_window_shape_input_rectangle_add(edata->win_shaped_input,
5040                                                dst_rect.x, dst_rect.y,
5041                                                dst_rect.width, dst_rect.height);
5042 }
5043
5044 static void
5045 _ecore_evas_x11_shape_input_rectangle_subtract(Ecore_Evas *ee, int x, int y, int w, int h)
5046 {
5047    Eina_Bool ret;
5048    Ecore_X_Rectangle src_rect;
5049    Ecore_X_Rectangle dst_rect;
5050    Ecore_Evas_Engine_Data_X11 *edata;
5051
5052    if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
5053      {
5054         ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
5055                          "ecore_evas_x11_shape_input_rectangle_subtract");
5056         return;
5057      }
5058
5059    edata = ee->engine.data;
5060    src_rect.x = x;
5061    src_rect.y = y;
5062    src_rect.width = w;
5063    src_rect.height = h;
5064
5065    dst_rect.x = 0;
5066    dst_rect.y = 0;
5067    dst_rect.width = 0;
5068    dst_rect.height = 0;
5069
5070    ret = _ecore_evas_x11_convert_rectangle_with_angle(ee, &dst_rect, &src_rect);
5071
5072    if (!edata->win_shaped_input)
5073       edata->win_shaped_input = ecore_x_window_override_new(edata->win_root,
5074                                                                   0, 0, 1, 1);
5075
5076    if (ret)
5077       ecore_x_window_shape_input_rectangle_subtract(edata->win_shaped_input,
5078                                                     dst_rect.x, dst_rect.y,
5079                                                     dst_rect.width, dst_rect.height);
5080 }
5081
5082 static void
5083 _ecore_evas_x11_shape_input_empty(Ecore_Evas *ee)
5084 {
5085    Ecore_Evas_Engine_Data_X11 *edata;
5086    if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
5087      {
5088         ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
5089                          "ecore_evas_x11_shape_input_empty");
5090         return;
5091      }
5092
5093    edata = ee->engine.data;
5094    if (!edata->win_shaped_input)
5095       edata->win_shaped_input = ecore_x_window_override_new(edata->win_root, 0, 0, 1, 1);
5096
5097    ecore_x_window_shape_input_rectangle_set(edata->win_shaped_input, 0, 0, 0, 0);
5098 }
5099
5100 static void
5101 _ecore_evas_x11_shape_input_reset(Ecore_Evas *ee)
5102 {
5103    Ecore_Evas_Engine_Data_X11 *edata;
5104    if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
5105      {
5106         ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
5107                          "ecore_evas_x11_shape_input_reset");
5108         return;
5109      }
5110
5111    edata = ee->engine.data;
5112    if (!edata->win_shaped_input)
5113       edata->win_shaped_input = ecore_x_window_override_new(edata->win_root, 0, 0, 1, 1);
5114
5115    ecore_x_window_shape_input_rectangle_set(edata->win_shaped_input, 0, 0, 65535, 65535);
5116 }
5117
5118 static void
5119 _ecore_evas_x11_shape_input_apply(Ecore_Evas *ee)
5120 {
5121    Ecore_Evas_Engine_Data_X11 *edata;
5122    if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
5123      {
5124         ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
5125                          "ecore_evas_x11_shape_input_apply");
5126         return;
5127      }
5128
5129    edata = ee->engine.data;
5130    if (!edata->win_shaped_input) return;
5131
5132    ecore_x_window_shape_input_window_set(ee->prop.window, edata->win_shaped_input);
5133 }
5134
5135 static Ecore_Evas_Interface_X11 *
5136 _ecore_evas_x_interface_x11_new(void)
5137 {
5138    Ecore_Evas_Interface_X11 *iface;
5139
5140    iface = calloc(1, sizeof(Ecore_Evas_Interface_X11));
5141    if (!iface) return NULL;
5142
5143    iface->base.name = interface_x11_name;
5144    iface->base.version = interface_x11_version;
5145
5146    iface->leader_set = _ecore_evas_x11_leader_set;
5147    iface->leader_get = _ecore_evas_x11_leader_get;
5148    iface->leader_default_set = _ecore_evas_x11_leader_default_set;
5149    iface->shape_input_rectangle_set = _ecore_evas_x11_shape_input_rectangle_set;
5150    iface->shape_input_rectangle_add = _ecore_evas_x11_shape_input_rectangle_add;
5151    iface->shape_input_rectangle_subtract = _ecore_evas_x11_shape_input_rectangle_subtract;
5152    iface->shape_input_empty = _ecore_evas_x11_shape_input_empty;
5153    iface->shape_input_reset = _ecore_evas_x11_shape_input_reset;
5154    iface->shape_input_apply = _ecore_evas_x11_shape_input_apply;
5155
5156    return iface;
5157 }
5158
5159 #ifdef BUILD_ECORE_EVAS_SOFTWARE_X11
5160 static Ecore_Evas_Interface_Software_X11 *
5161 _ecore_evas_x_interface_software_x11_new(void)
5162 {
5163    Ecore_Evas_Interface_Software_X11 *iface;
5164
5165    iface = calloc(1, sizeof(Ecore_Evas_Interface_Software_X11));
5166    if (!iface) return NULL;
5167
5168    iface->base.name = interface_software_x11_name;
5169    iface->base.version = interface_software_x11_version;
5170
5171    iface->window_get = _ecore_evas_software_x11_window_get;
5172    iface->pixmap_get = _ecore_evas_software_x11_pixmap_get;
5173    iface->resize_set = _ecore_evas_software_x11_direct_resize_set;
5174    iface->resize_get = _ecore_evas_software_x11_direct_resize_get;
5175    iface->extra_event_window_add = _ecore_evas_software_x11_extra_event_window_add;
5176    iface->pixmap_visual_get = _ecore_evas_software_x11_pixmap_visual_get;
5177    iface->pixmap_colormap_get = _ecore_evas_software_x11_pixmap_colormap_get;
5178    iface->pixmap_depth_get = _ecore_evas_software_x11_pixmap_depth_get;
5179
5180    return iface;
5181 }
5182 #endif
5183
5184 #ifdef BUILD_ECORE_EVAS_OPENGL_X11
5185 static Ecore_Evas_Interface_Gl_X11 *
5186 _ecore_evas_x_interface_gl_x11_new(void)
5187 {
5188    Ecore_Evas_Interface_Gl_X11 *iface;
5189
5190    iface = calloc(1, sizeof(Ecore_Evas_Interface_Gl_X11));
5191    if (!iface) return NULL;
5192
5193    iface->base.name = interface_gl_x11_name;
5194    iface->base.version = interface_gl_x11_version;
5195
5196    iface->window_get = _ecore_evas_gl_x11_window_get;
5197    iface->pixmap_get = _ecore_evas_gl_x11_pixmap_get;
5198    iface->resize_set = _ecore_evas_gl_x11_direct_resize_set;
5199    iface->resize_get = _ecore_evas_gl_x11_direct_resize_get;
5200    iface->extra_event_window_add = _ecore_evas_gl_x11_extra_event_window_add;
5201    iface->pre_post_swap_callback_set = _ecore_evas_gl_x11_pre_post_swap_callback_set;
5202    iface->pixmap_visual_get = _ecore_evas_gl_x11_pixmap_visual_get;
5203    iface->pixmap_colormap_get = _ecore_evas_gl_x11_pixmap_colormap_get;
5204    iface->pixmap_depth_get = _ecore_evas_gl_x11_pixmap_depth_get;
5205
5206    return iface;
5207 }
5208 #endif
5209