1 #define EXECUTIVE_MODE_ENABLED
2 #define E_COMP_X
3 #include "e.h"
4 
5 #define RANDR_VERSION_1_3 ((1 << 16) | 3)
6 #define RANDR_VERSION_1_4 ((1 << 16) | 4)
7 
8 #define GRAV_SET(ec, grav)                                                         \
9   ecore_x_window_gravity_set(e_client_util_pwin_get(ec), grav);                          \
10   if (_e_comp_x_client_data_get(ec)->lock_win) ecore_x_window_gravity_set(_e_comp_x_client_data_get(ec)->lock_win, grav);
11 
12 #ifdef HAVE_WAYLAND
13 # define E_COMP_X_PIXMAP_CHECK if ((e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_X) && (!e_client_has_xwindow(ec))) return
14 #else
15 # define E_COMP_X_PIXMAP_CHECK if (!e_pixmap_is_x(ec->pixmap)) return
16 #endif
17 /* maybe make configurable?
18  * not sure why anyone would want to change it...
19  */
20 #define MOVE_COUNTER_LIMIT 50
21 
22 #define PARENT_ACTIVATE_TIME 200
23 #define PARENT_ACTIVATE_LIMIT 2
24 
25 EINTERN void _e_main_cb_x_fatal(void *data EINA_UNUSED);
26 
27 typedef struct _Frame_Extents Frame_Extents;
28 
29 struct _Frame_Extents
30 {
31    int l, r, t, b;
32 };
33 
34 struct _E_Comp_X_Data
35 {
36    Ecore_X_Window lock_grab_break_wnd;
37 
38    Eina_List *retry_clients;
39    Ecore_Timer *retry_timer;
40    Eina_Bool restack E_BITFIELD;
41 };
42 
43 typedef struct Pending_Configure
44 {
45    Evas_Point point;
46    Ecore_X_Window win;
47    Ecore_Timer *timer;
48 } Pending_Configure;
49 
50 static Eina_Hash *pending_configures;
51 
52 static unsigned int focus_time = 0;
53 static unsigned int focus_canvas_time = 0;
54 static Ecore_Timer *focus_timer;
55 static E_Client *mouse_client;
56 static Eina_List *handlers = NULL;
57 static Eina_Hash *clients_win_hash = NULL;
58 static Eina_Hash *damages_hash = NULL;
59 static Eina_Hash *frame_extents = NULL;
60 static Eina_Hash *alarm_hash = NULL;
61 
62 static Evas_Point mouse_in_coords = {-1, -1};
63 static Ecore_Job *mouse_in_job;
64 static E_Client *focus_job_client;
65 static Ecore_Job *focus_job;
66 static E_Client *unfocus_job_client;
67 static Ecore_Job *unfocus_job;
68 static Ecore_Idle_Enterer *_e_comp_x_post_client_idler = NULL;
69 static Ecore_Idle_Enterer *_x_idle_flush = NULL;
70 static Eina_List *post_clients = NULL;
71 
72 static int _e_comp_x_mapping_change_disabled = 0;
73 
74 static Ecore_X_Randr_Screen_Size screen_size = { -1, -1 };
75 static int screen_size_index = -1;
76 
77 static Ecore_X_Atom backlight_atom = 0;
78 
79 static Ecore_Timer *mouse_in_fix_check_timer = NULL;
80 
81 static Eina_Hash *dead_wins;
82 
83 static Ecore_Window _e_comp_x_suspend_grabbed; // window grabber for suspending pointer
84 
85 static void _e_comp_x_hook_client_pre_frame_assign(void *d EINA_UNUSED, E_Client *ec);
86 
87 static inline E_Comp_X_Client_Data *
_e_comp_x_client_data_get(const E_Client * ec)88 _e_comp_x_client_data_get(const E_Client *ec)
89 {
90 #ifdef HAVE_WAYLAND
91    if (!e_pixmap_is_x(ec->pixmap))
92      return e_comp_wl_client_xwayland_data(ec);
93 #endif
94    return ec->comp_data;
95 }
96 
97 static Eina_Bool
_e_comp_x_flusher(void * data EINA_UNUSED)98 _e_comp_x_flusher(void *data EINA_UNUSED)
99 {
100    ecore_x_flush();
101    return ECORE_CALLBACK_RENEW;
102 }
103 
104 static inline Ecore_X_Window
_e_comp_x_client_window_get(const E_Client * ec)105 _e_comp_x_client_window_get(const E_Client *ec)
106 {
107    E_Comp_X_Client_Data *cd = _e_comp_x_client_data_get(ec);
108    if (cd && cd->reparented)
109      return e_client_util_pwin_get(ec);
110    return e_client_util_win_get(ec);
111 }
112 
113 static void
_e_comp_x_client_damage_add(E_Client * ec)114 _e_comp_x_client_damage_add(E_Client *ec)
115 {
116    Ecore_X_Window win;
117 
118    if (_e_comp_x_client_data_get(ec)->damage) return;
119    win = _e_comp_x_client_window_get(ec);
120    _e_comp_x_client_data_get(ec)->damage = ecore_x_damage_new(win, ECORE_X_DAMAGE_REPORT_DELTA_RECTANGLES);
121    eina_hash_add(damages_hash, &_e_comp_x_client_data_get(ec)->damage, ec);
122 }
123 
124 static void
_e_comp_x_focus_check(void)125 _e_comp_x_focus_check(void)
126 {
127    E_Client *focused;
128 
129    if (stopping || e_comp->nocomp) return;
130    focused = e_client_focused_get();
131    /* if there is no new focused or it is a non-X client,
132     * focus comp canvas on focus-out */
133    if ((!focused) || (!e_client_has_xwindow(focused)))
134      {
135         focus_canvas_time = ecore_x_current_time_get();
136         focus_time = 0;
137         if (e_comp->comp_type != E_PIXMAP_TYPE_X)
138           e_grabinput_focus(e_comp->root, E_FOCUS_METHOD_PASSIVE);
139 // this breaks Qt because it seems to create override-redirect popup windows
140 // that it FOCUSES instead of grabbking the kbd like most other menu windows
141 // so this causes the parent window to lose focus in a way that then causes
142 // the popups to dismiss instantly
143 //             e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
144 // This might be more specific a workaround bit might miss other cases, so keep
145 // here as an idea and for future reference
146         else
147           {
148              Ecore_X_Window focus_win = ecore_x_window_focus_get();
149              if (focus_win)
150                {
151                   if ((ecore_x_window_root_get(focus_win) == focus_win) ||
152                       (!ecore_x_icccm_transient_for_get(focus_win)))
153                     e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
154                }
155              else
156                e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
157           }
158      }
159 }
160 
161 static void
_e_comp_x_client_modal_setup(E_Client * ec)162 _e_comp_x_client_modal_setup(E_Client *ec)
163 {
164    E_Comp_X_Client_Data *pcd;
165 
166    ec->parent->modal = ec;
167    ec->parent->lock_close = 1;
168    pcd = _e_comp_x_client_data_get(ec->parent);
169    if (!pcd->lock_win)
170      {
171         eina_hash_add(clients_win_hash, &pcd->lock_win, ec->parent);
172         pcd->lock_win = ecore_x_window_input_new(e_client_util_pwin_get(ec->parent), 0, 0, ec->parent->w, ec->parent->h);
173         e_comp_ignore_win_add(E_PIXMAP_TYPE_X, pcd->lock_win);
174         ecore_x_window_show(pcd->lock_win);
175         ecore_x_icccm_name_class_set(pcd->lock_win, "comp_data->lock_win", "comp_data->lock_win");
176      }
177 }
178 
179 static void
_e_comp_x_client_frame_update(E_Client * ec,int l,int r,int t,int b)180 _e_comp_x_client_frame_update(E_Client *ec, int l, int r, int t, int b)
181 {
182    ecore_x_netwm_frame_size_set(e_client_util_win_get(ec), l, r, t, b);
183    ecore_x_e_frame_size_set(e_client_util_win_get(ec), l, r, t, b);
184    _e_comp_x_client_data_get(ec)->frame_update = 0;
185 }
186 
187 static Eina_List *iconshare = NULL;
188 
189 typedef struct _E_Client_Icon_Entry E_Client_Icon_Entry;
190 
191 struct _E_Client_Icon_Entry
192 {
193    Ecore_X_Icon *icons;
194    int num_icons;
195    int ref;
196 };
197 
198 static Ecore_X_Icon *
_e_comp_x_client_icon_deduplicate(Ecore_X_Icon * icons,int num_icons)199 _e_comp_x_client_icon_deduplicate(Ecore_X_Icon *icons, int num_icons)
200 {
201    int i;
202    Eina_List *l;
203    E_Client_Icon_Entry *ie;
204 
205    // unless the rest of e uses border icons OTHER than icon #0
206    // then free the rest that we don't need anymore.
207    for (i = 1; i < num_icons; i++)
208      {
209         E_FREE(icons[i].data);
210      }
211    // lookup icon data in icons cache/share
212    EINA_LIST_FOREACH(iconshare, l, ie)
213      {
214         if ((ie->num_icons == num_icons) &&
215             (num_icons  > 0) &&
216             (ie->icons[0].width == icons[0].width) &&
217             (ie->icons[0].height == icons[0].height) &&
218             (!memcmp(ie->icons[0].data, icons[0].data,
219                      icons[0].width * icons[0].height * 4)))
220           {
221              // found so free the input icons
222              for (i = 0; i < num_icons; i++)
223                free(icons[i].data);
224              free(icons);
225              // ref the shared/cached one
226              ie->ref++;
227              iconshare = eina_list_promote_list(iconshare, l);
228              // and return that
229              return ie->icons;
230           }
231      }
232    // no hit - new entry to cache. add it
233    ie = calloc(1, sizeof(E_Client_Icon_Entry));
234    if (ie)
235      {
236         ie->icons = icons;
237         ie->num_icons = num_icons;
238         ie->ref = 1;
239         iconshare = eina_list_prepend(iconshare, ie);
240      }
241    return icons;
242 }
243 
244 static void
_e_comp_x_client_icon_free(Ecore_X_Icon * icons,int num_icons)245 _e_comp_x_client_icon_free(Ecore_X_Icon *icons, int num_icons)
246 {
247    int i;
248    Eina_List *l;
249    E_Client_Icon_Entry *ie;
250 
251    // lookup in icon share cache
252    EINA_LIST_FOREACH(iconshare, l, ie)
253      {
254         if ((ie->num_icons == num_icons) &&
255             (num_icons  > 0) &&
256             (ie->icons[0].width == icons[0].width) &&
257             (ie->icons[0].height == icons[0].height) &&
258             (!memcmp(ie->icons[0].data, icons[0].data,
259                      icons[0].width * icons[0].height * 4)))
260           {
261              // found so deref
262              ie->ref--;
263              if (ie->ref <= 0)
264                {
265                   // no refs left - free the icon from the share/cache
266                   iconshare = eina_list_remove_list(iconshare, l);
267                   for (i = 0; i < ie->num_icons; i++)
268                     free(ie->icons[i].data);
269                   free(ie->icons);
270                   free(ie);
271                }
272              return;
273           }
274      }
275    // not found - so just free it ... odd - we should never be here
276    for (i = 0; i < num_icons; i++)
277      free(icons[i].data);
278    free(icons);
279 }
280 
281 static void
_e_comp_x_client_event_free(void * d EINA_UNUSED,void * e)282 _e_comp_x_client_event_free(void *d EINA_UNUSED, void *e)
283 {
284    E_Event_Client *ev = e;
285 
286    UNREFD(ev->ec, 1);
287    e_object_unref(E_OBJECT(ev->ec));
288    free(ev);
289 }
290 
291 static void
_e_comp_x_print_win(Ecore_X_Window win)292 _e_comp_x_print_win(Ecore_X_Window win)
293 {
294    int x, y, w, h;
295    Eina_Bool vis;
296 
297    ecore_x_window_geometry_get(win, &x, &y, &w, &h);
298    vis = ecore_x_window_visible_get(win);
299    fprintf(stderr, "%s 0x%x: %d,%d @ %dx%d\n", vis ? "VIS" : "HID", win, x, y, w, h);
300 }
301 
302 static void
_e_comp_x_focus_grab(E_Client * ec)303 _e_comp_x_focus_grab(E_Client *ec)
304 {
305    if (ec->internal_elm_win) return;
306    ecore_x_window_button_grab(e_client_util_win_get(ec), 1,
307                               ECORE_X_EVENT_MASK_MOUSE_DOWN |
308                               ECORE_X_EVENT_MASK_MOUSE_UP |
309                               ECORE_X_EVENT_MASK_MOUSE_MOVE, 0, 1);
310    ecore_x_window_button_grab(e_client_util_win_get(ec), 2,
311                               ECORE_X_EVENT_MASK_MOUSE_DOWN |
312                               ECORE_X_EVENT_MASK_MOUSE_UP |
313                               ECORE_X_EVENT_MASK_MOUSE_MOVE, 0, 1);
314    ecore_x_window_button_grab(e_client_util_win_get(ec), 3,
315                               ECORE_X_EVENT_MASK_MOUSE_DOWN |
316                               ECORE_X_EVENT_MASK_MOUSE_UP |
317                               ECORE_X_EVENT_MASK_MOUSE_MOVE, 0, 1);
318    _e_comp_x_client_data_get(ec)->button_grabbed = 1;
319 }
320 
321 static void
_e_comp_x_focus_init(E_Client * ec)322 _e_comp_x_focus_init(E_Client *ec)
323 {
324    if (_e_comp_x_client_data_get(ec)->button_grabbed) return;
325    if (!((e_client_focus_policy_click(ec)) ||
326        (e_config->always_click_to_raise) ||
327        (e_config->always_click_to_focus))) return;
328    _e_comp_x_focus_grab(ec);
329 }
330 
331 static void
_e_comp_x_focus_setup(E_Client * ec)332 _e_comp_x_focus_setup(E_Client *ec)
333 {
334    if (_e_comp_x_client_data_get(ec)->button_grabbed) return;
335    if ((!e_client_focus_policy_click(ec)) ||
336        (e_config->always_click_to_raise) ||
337        (e_config->always_click_to_focus)) return;
338    _e_comp_x_focus_grab(ec);
339 }
340 
341 
342 static void
_e_comp_x_focus_setdown(E_Client * ec)343 _e_comp_x_focus_setdown(E_Client *ec)
344 {
345    Ecore_X_Window win, pwin;
346 
347    if (!_e_comp_x_client_data_get(ec)->button_grabbed) return;
348    if ((!e_client_focus_policy_click(ec)) ||
349        (e_config->always_click_to_raise) ||
350        (e_config->always_click_to_focus)) return;
351    win = e_client_util_win_get(ec);
352    pwin = e_client_util_pwin_get(ec);
353    e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, pwin);
354    e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, pwin);
355    ecore_x_window_button_ungrab(win, 1, 0, 1);
356    ecore_x_window_button_ungrab(win, 2, 0, 1);
357    ecore_x_window_button_ungrab(win, 3, 0, 1);
358    e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, pwin);
359    e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, pwin);
360    _e_comp_x_client_data_get(ec)->button_grabbed = 0;
361 }
362 
363 static Eina_Bool
_e_comp_x_client_new_helper(E_Client * ec)364 _e_comp_x_client_new_helper(E_Client *ec)
365 {
366    Ecore_X_Window win = e_client_util_win_get(ec);
367    int at_num = 0, i;
368    Ecore_X_Atom *atoms;
369 
370    if (!ecore_x_window_attributes_get(win, &ec->comp_data->initial_attributes))
371      {
372         //CRI("OUCH! FIX THIS!");
373         DELD(ec, 1);
374         e_object_del(E_OBJECT(ec));
375         return EINA_FALSE;
376      }
377    if (ec->re_manage && (!ec->comp_data->initial_attributes.visible))
378      {
379         /* ain't gonna be no hidden clients on my watch! */
380         DELD(ec, 1);
381         e_object_del(E_OBJECT(ec));
382         return EINA_FALSE;
383      }
384    ec->depth = ec->comp_data->initial_attributes.depth;
385    ec->override = ec->comp_data->initial_attributes.override;
386    ec->placed |= ec->override;
387    ec->input_only = ec->comp_data->initial_attributes.input_only;
388    ec->border_size = ec->comp_data->initial_attributes.border;
389    ec->icccm.accepts_focus = (!ec->override) && (!ec->input_only);
390    //INF("NEW CLIENT: %d,%d -> %d,%d", ec->x, ec->y, ec->comp_data->initial_attributes.x, ec->comp_data->initial_attributes.y);
391    ec->x = ec->client.x = ec->comp_data->initial_attributes.x;
392    ec->y = ec->client.y = ec->comp_data->initial_attributes.y;
393    if (ec->override && ((ec->x == -77) && (ec->y == -777)))
394      {
395         /* this is the ecore-x private window :/ */
396         e_comp_ignore_win_add(E_PIXMAP_TYPE_X, win);
397         DELD(ec, 1);
398         e_object_del(E_OBJECT(ec));
399         return EINA_FALSE;
400      }
401    if ((!e_client_util_ignored_get(ec)) && (!ec->internal) && (!ec->internal_elm_win))
402      {
403         ec->comp_data->need_reparent = 1;
404         EC_CHANGED(ec);
405         ec->take_focus = !starting;
406      }
407    ec->new_client ^= ec->override;
408    if (!ec->new_client)
409      e_comp->new_clients--;
410 
411    ec->w = ec->client.w = ec->comp_data->initial_attributes.w;
412    ec->h = ec->client.h = ec->comp_data->initial_attributes.h;
413    if (!ec->internal)
414      {
415         ec->comp_data->pw = ec->w;
416         ec->comp_data->ph = ec->h;
417      }
418    ec->changes.size = 1;
419 
420 
421    e_pixmap_visual_cmap_set(ec->pixmap, ec->comp_data->initial_attributes.visual, ec->comp_data->initial_attributes.colormap);
422    if (ec->override && (!ec->internal))
423      ecore_x_window_shape_events_select(win, 1);
424    if (ec->override && (!(ec->comp_data->initial_attributes.event_mask.mine & ECORE_X_EVENT_MASK_WINDOW_PROPERTY)))
425      ecore_x_event_mask_set(win, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
426 
427    atoms = ecore_x_window_prop_list(win, &at_num);
428    ec->icccm.fetch.command = 1;
429 
430    if (atoms)
431      {
432         Eina_Bool video_parent = EINA_FALSE;
433         Eina_Bool video_position = EINA_FALSE;
434         Eina_Bool found_desk = EINA_FALSE;
435         Eina_Bool found_zone = EINA_FALSE;
436 
437         /* icccm */
438         for (i = 0; i < at_num; i++)
439           {
440              if (atoms[i] == ECORE_X_ATOM_WM_NAME)
441                ec->icccm.fetch.title = 1;
442              else if (atoms[i] == ECORE_X_ATOM_WM_CLASS)
443                ec->icccm.fetch.name_class = 1;
444              else if (atoms[i] == ECORE_X_ATOM_WM_ICON_NAME)
445                ec->icccm.fetch.icon_name = 1;
446              else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_MACHINE)
447                ec->icccm.fetch.machine = 1;
448              else if (atoms[i] == ECORE_X_ATOM_WM_HINTS)
449                ec->icccm.fetch.hints = 1;
450              else if (atoms[i] == ECORE_X_ATOM_WM_NORMAL_HINTS)
451                ec->icccm.fetch.size_pos_hints = 1;
452              else if (atoms[i] == ECORE_X_ATOM_WM_PROTOCOLS)
453                ec->icccm.fetch.protocol = 1;
454              else if (atoms[i] == ECORE_X_ATOM_MOTIF_WM_HINTS)
455                ec->mwm.fetch.hints = 1;
456              else if (atoms[i] == ECORE_X_ATOM_WM_TRANSIENT_FOR)
457                {
458                   ec->icccm.fetch.transient_for = 1;
459                   ec->netwm.fetch.type = 1;
460                }
461              else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_LEADER)
462                ec->icccm.fetch.client_leader = 1;
463              else if (atoms[i] == ECORE_X_ATOM_WM_WINDOW_ROLE)
464                ec->icccm.fetch.window_role = 1;
465           }
466         /* netwm, loop again, netwm will ignore some icccm, so we
467          * have to be sure that netwm is checked after */
468         for (i = 0; i < at_num; i++)
469           {
470              if (atoms[i] == ECORE_X_ATOM_NET_WM_NAME)
471                {
472                   /* Ignore icccm */
473                   ec->icccm.fetch.title = 0;
474                   ec->netwm.fetch.name = 1;
475                }
476              else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON_NAME)
477                {
478                   /* Ignore icccm */
479                   ec->icccm.fetch.icon_name = 0;
480                   ec->netwm.fetch.icon_name = 1;
481                }
482              else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON)
483                {
484                   ec->netwm.fetch.icon = 1;
485                }
486              else if (atoms[i] == ECORE_X_ATOM_NET_WM_USER_TIME)
487                {
488                   ec->netwm.fetch.user_time = 1;
489                }
490              else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT)
491                {
492                   DBG("ECORE_X_ATOM_NET_WM_STRUT");
493                   ec->netwm.fetch.strut = 1;
494                }
495              else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
496                {
497                   DBG("ECORE_X_ATOM_NET_WM_STRUT_PARTIAL");
498                   ec->netwm.fetch.strut = 1;
499                }
500              else if (atoms[i] == ECORE_X_ATOM_NET_WM_WINDOW_TYPE)
501                {
502                   /* Ignore mwm
503                      ec->mwm.fetch.hints = 0;
504                    */
505                   ec->netwm.fetch.type = 1;
506                }
507              else if (atoms[i] == ECORE_X_ATOM_NET_WM_STATE)
508                {
509                   ec->netwm.fetch.state = 1;
510                }
511              else if (atoms[i] == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY)
512                ec->netwm.fetch.opacity = 1;
513           }
514         /* other misc atoms */
515         for (i = 0; i < at_num; i++)
516           {
517              /* loop to check for own atoms */
518              if (atoms[i] == E_ATOM_WINDOW_STATE)
519                {
520                   ec->e.fetch.state = 1;
521                }
522              /* loop to check for qtopia atoms */
523              if (atoms[i] == ATM__QTOPIA_SOFT_MENU)
524                ec->qtopia.fetch.soft_menu = 1;
525              else if (atoms[i] == ATM__QTOPIA_SOFT_MENUS)
526                ec->qtopia.fetch.soft_menus = 1;
527              /* loop to check for vkbd atoms */
528              else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
529                ec->vkbd.fetch.state = 1;
530              else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
531                ec->vkbd.fetch.vkbd = 1;
532              /* loop to check for illume atoms */
533              else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
534                ec->comp_data->illume.conformant.fetch.conformant = 1;
535              else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
536                ec->comp_data->illume.quickpanel.fetch.state = 1;
537              else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
538                ec->comp_data->illume.quickpanel.fetch.quickpanel = 1;
539              else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
540                ec->comp_data->illume.quickpanel.fetch.priority.major = 1;
541              else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
542                ec->comp_data->illume.quickpanel.fetch.priority.minor = 1;
543              else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
544                ec->comp_data->illume.quickpanel.fetch.zone = 1;
545              else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
546                ec->comp_data->illume.drag.fetch.locked = 1;
547              else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG)
548                ec->comp_data->illume.drag.fetch.drag = 1;
549              else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
550                ec->comp_data->illume.win_state.fetch.state = 1;
551              else if (atoms[i] == ECORE_X_ATOM_E_VIDEO_PARENT)
552                video_parent = EINA_TRUE;
553              else if (atoms[i] == ECORE_X_ATOM_E_VIDEO_POSITION)
554                video_position = EINA_TRUE;
555              /* loop to check for window profile list atom */
556              else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED)
557                ec->e.fetch.profile = 1;
558              else if (atoms[i] == ECORE_X_ATOM_E_STACK_TYPE)
559                ec->e.fetch.stack = 1;
560              else if (atoms[i] == ATM_GTK_FRAME_EXTENTS)
561                ec->comp_data->fetch_gtk_frame_extents = 1;
562              else if (atoms[i] == ATM_STEAM_GAME)
563                e_hints_window_steam_game_get(ec);
564              else if (ec->re_manage)
565                {
566                   if (atoms[i] == E_ATOM_DESKTOP_FILE)
567                     {
568                        char *path = ecore_x_window_prop_string_get(win,
569                                                              E_ATOM_DESKTOP_FILE);
570                        if (path)
571                          {
572                             ec->desktop = efreet_desktop_get(path);
573                             free(path);
574                          }
575                     }
576                   else if (atoms[i] == E_ATOM_DESK)
577                     found_desk = 1;
578                   else if (atoms[i] == E_ATOM_ZONE)
579                     found_zone = 1;
580                }
581           }
582         if (video_position && video_parent)
583           {
584              ec->e.state.video = 1;
585              ec->e.fetch.video_parent = 1;
586              ec->e.fetch.video_position = 1;
587              fprintf(stderr, "We found a video window \\o/ %x\n", win);
588           }
589         free(atoms);
590 
591         if (ec->re_manage && found_desk && found_zone)
592           {
593              E_Zone *zone = NULL;
594              E_Desk *desk = NULL;
595              unsigned int id, deskxy[2];
596              int ret;
597 
598              /* get all information from window before it is
599               * reset by e_client_new */
600              ret = ecore_x_window_prop_card32_get(win,
601                                                   E_ATOM_ZONE,
602                                                   &id, 1);
603              if (ret == 1)
604                zone = e_comp_zone_number_get(id);
605              if (!zone)
606                zone = e_zone_current_get();
607              ret = ecore_x_window_prop_card32_get(win,
608                                                   E_ATOM_DESK,
609                                                   deskxy, 2);
610              if (ret == 2)
611                desk = e_desk_at_xy_get(zone,
612                                        deskxy[0],
613                                        deskxy[1]);
614 
615              if (desk) e_client_desk_set(ec, desk);
616 
617           }
618      }
619 
620    return EINA_TRUE;
621 }
622 
623 static E_Client *
_e_comp_x_client_find_by_damage(Ecore_X_Damage damage)624 _e_comp_x_client_find_by_damage(Ecore_X_Damage damage)
625 {
626    return eina_hash_find(damages_hash, &damage);
627 }
628 
629 static E_Client *
_e_comp_x_client_find_by_window(Ecore_X_Window win)630 _e_comp_x_client_find_by_window(Ecore_X_Window win)
631 {
632    E_Client *ec;
633 
634    ec = eina_hash_find(clients_win_hash, &win);
635    if (ec && e_object_is_del(E_OBJECT(ec))) ec = NULL;
636    return ec;
637 }
638 
639 /*
640 static E_Client *
641 _e_comp_x_client_find_all_by_window(Ecore_X_Window win)
642 {
643    return eina_hash_find(clients_win_hash, &win);
644 }
645 */
646 
647 static void
_e_comp_x_add_fail_job(void * d EINA_UNUSED)648 _e_comp_x_add_fail_job(void *d EINA_UNUSED)
649 {
650    e_util_dialog_internal
651      (_("Compositor Warning"),
652       _("Your display driver does not support OpenGL, GLSL<ps/>"
653         "shaders or no OpenGL engines were compiled or installed<ps/>"
654         "for Evas or Ecore-Evas. Falling back to software engine.<ps/>"
655         "<ps/>"
656         "You will need an OpenGL 2.0 (or OpenGL ES 2.0) capable<ps/>"
657         "GPU to use OpenGL with compositing."));
658 }
659 
660 static void
_pri_adj(int pid,int set,int adj,Eina_Bool use_adj,Eina_Bool adj_children,Eina_Bool do_children)661 _pri_adj(int pid, int set, int adj, Eina_Bool use_adj, Eina_Bool adj_children, Eina_Bool do_children)
662 {
663    int newpri = set;
664 
665    if (use_adj) newpri = getpriority(PRIO_PROCESS, pid) + adj;
666    setpriority(PRIO_PROCESS, pid, newpri);
667 // shouldn't need to do this as default ionice class is "none" (0), and
668 // this inherits io priority FROM nice level
669 //        ioprio_set(IOPRIO_WHO_PROCESS, pid,
670 //                   IOPRIO_PRIO_VALUE(2, 5));
671    if (do_children)
672      {
673         Eina_List *files;
674         char *file, buf[PATH_MAX];
675         FILE *f;
676         int pid2, ppid;
677 
678         // yes - this is /proc specific... so this may not work on some
679         // os's - works on linux. too bad for others.
680         files = ecore_file_ls("/proc");
681         EINA_LIST_FREE(files, file)
682           {
683              if (isdigit(file[0]))
684                {
685                   snprintf(buf, sizeof(buf), "/proc/%s/stat", file);
686                   f = fopen(buf, "r");
687                   if (f)
688                     {
689                        pid2 = -1;
690                        ppid = -1;
691                        if (fscanf(f, "%i %*s %*s %i %*s", &pid2, &ppid) == 2)
692                          {
693                             fclose(f);
694                             if (ppid == pid)
695                               {
696                                  if (adj_children)
697                                    _pri_adj(pid2, set, adj, EINA_TRUE,
698                                             adj_children, do_children);
699                                  else
700                                    _pri_adj(pid2, set, adj, use_adj,
701                                             adj_children, do_children);
702                               }
703                          }
704                        else fclose(f);
705                     }
706                }
707              free(file);
708           }
709      }
710 }
711 
712 static E_Client *
_e_comp_x_client_find_by_alarm(Ecore_X_Sync_Alarm al)713 _e_comp_x_client_find_by_alarm(Ecore_X_Sync_Alarm al)
714 {
715    return eina_hash_find(alarm_hash, &al);
716 }
717 
718 static void
_e_comp_x_client_move_resize_send(E_Client * ec)719 _e_comp_x_client_move_resize_send(E_Client *ec)
720 {
721    if (ec->internal_elm_win)
722      ecore_evas_managed_move(e_win_ee_get(ec->internal_elm_win), ec->client.x - ec->x, ec->client.y - ec->y);
723 
724    ecore_x_icccm_move_resize_send(e_client_util_win_get(ec), ec->client.x, ec->client.y, ec->client.w, ec->client.h);
725 }
726 
727 static Eina_Bool
_e_comp_x_post_client_idler_cb(void * d EINA_UNUSED)728 _e_comp_x_post_client_idler_cb(void *d EINA_UNUSED)
729 {
730    E_Client *ec;
731 
732    //INF("POST IDLER");
733    EINA_LIST_FREE(post_clients, ec)
734      {
735         Ecore_X_Window win, twin;
736 
737         if (e_object_is_del(E_OBJECT(ec)) || (!_e_comp_x_client_data_get(ec))) continue;
738         win = _e_comp_x_client_window_get(ec);
739         if (ec->post_move)
740           {
741              E_Client *tmp;
742              Eina_List *l;
743 
744              EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
745                {
746                   twin = _e_comp_x_client_window_get(tmp);
747                   ecore_x_window_move(twin,
748                                       ec->client.x +
749                                       tmp->e.state.video_position.x,
750                                       ec->client.y +
751                                       tmp->e.state.video_position.y);
752                }
753           }
754         if (ec->e.state.video)
755           {
756              E_Client *parent;
757 
758              parent = ec->e.state.video_parent_client;
759              twin = _e_comp_x_client_window_get(parent);
760              ecore_x_window_move(twin,
761                                  parent->client.x +
762                                  ec->e.state.video_position.x,
763                                  parent->client.y +
764                                  ec->e.state.video_position.y);
765           }
766         else if (ec->shading)
767           {
768              // do nothing
769           }
770         else if ((ec->post_move) && (ec->post_resize))
771           {
772              //INF("X MVRSZ");
773              ecore_x_window_move_resize(win,
774                                         ec->client.x,
775                                         ec->client.y,
776                                         ec->client.w,
777                                         ec->client.h);
778              if (_e_comp_x_client_data_get(ec)->reparented)
779                ecore_x_window_move_resize(e_client_util_win_get(ec), 0, 0,
780                                           ec->client.w,
781                                           ec->client.h);
782           }
783         else if (ec->post_move)
784           {
785              //INF("X MV");
786              ecore_x_window_move(win, ec->client.x, ec->client.y);
787           }
788         else if (ec->post_resize)
789           {
790              //INF("X RSZ: %dx%d (REAL: %dx%d)", ec->client.w, ec->client.h, ec->w, ec->h);
791              ecore_x_window_resize(win,
792                                    ec->client.w, ec->client.h);
793              if (_e_comp_x_client_data_get(ec)->reparented)
794                ecore_x_window_move_resize(e_client_util_win_get(ec), 0, 0,
795                                           ec->client.w, ec->client.h);
796           }
797         if ((!ec->shading) && (!ec->shaded))
798           {
799              if (ec->post_resize)
800                {
801                   if (ec->netwm.sync.request && (e_comp->comp_type == E_PIXMAP_TYPE_X))
802                     {
803                        //INF("NETWM SYNC: %p", ec);
804                        ec->netwm.sync.wait++;
805                        ecore_x_netwm_sync_request_send(e_client_util_win_get(ec),
806                                                        ec->netwm.sync.serial++);
807                     }
808                }
809 
810              if (ec->post_move || ec->post_resize)
811                _e_comp_x_client_move_resize_send(ec);
812           }
813 
814         if (ec->e.state.video)
815           {
816              fprintf(stderr, "VIDEO %p: [%i, %i] [%i, %i]\n",
817                      ec,
818                      ec->e.state.video_parent_client->client.x +
819                      ec->e.state.video_position.x,
820                      ec->e.state.video_parent_client->client.y +
821                      ec->e.state.video_position.y,
822                      ec->w, ec->h);
823           }
824         if (ec->netwm.opacity_changed)
825           {
826              unsigned int opacity;
827              int op;
828 
829              evas_object_color_get(ec->frame, NULL, NULL, NULL, &op);
830              ec->netwm.opacity = op;
831              opacity = (op << 24) | (op << 16) | (op << 8) | op;
832              ecore_x_window_prop_card32_set(e_client_util_win_get(ec), ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, &opacity, 1);
833              /* flag gets unset in property cb to avoid fetching opacity after we just set it */
834           }
835         if (e_pixmap_is_x(ec->pixmap) && ec->post_resize)
836           {
837              e_pixmap_dirty(ec->pixmap);
838              e_comp_object_render_update_del(ec->frame);
839              if (!ec->internal)
840                {
841                   _e_comp_x_client_data_get(ec)->pw = ec->client.w;
842                   _e_comp_x_client_data_get(ec)->ph = ec->client.h;
843                }
844           }
845         ec->post_move = 0;
846         ec->post_resize = 0;
847      }
848    if (e_comp_x->restack && (!e_comp->new_clients))
849      {
850         e_hints_client_stacking_set();
851         e_comp_x->restack = 0;
852      }
853    _e_comp_x_post_client_idler = NULL;
854    return EINA_FALSE;
855 }
856 
857 static void
_e_comp_x_post_client_idler_add(E_Client * ec)858 _e_comp_x_post_client_idler_add(E_Client *ec)
859 {
860    if (!_e_comp_x_post_client_idler)
861      _e_comp_x_post_client_idler = ecore_idle_enterer_add(_e_comp_x_post_client_idler_cb, NULL);
862    if (!ec) CRI("ACK!");
863    //INF("POST IDLE: %p", ec);
864    if (!eina_list_data_find(post_clients, ec))
865      post_clients = eina_list_append(post_clients, ec);
866 }
867 
868 static void
_e_comp_x_client_stack(E_Client * ec)869 _e_comp_x_client_stack(E_Client *ec)
870 {
871    E_Client *ec2;
872    Ecore_X_Window_Stack_Mode mode = ECORE_X_WINDOW_STACK_BELOW;
873    Ecore_X_Window cwin, win = 0;
874    Eina_List *l;
875 
876    if (ec->override && (!ec->internal)) return; //can't restack these
877    if (e_client_is_stacking(ec)) return;
878    if (!_e_comp_x_client_data_get(ec)) return;
879    if (_e_comp_x_client_data_get(ec)->unredirected_single) return;
880 
881    cwin = _e_comp_x_client_window_get(ec);
882 
883    ecore_x_window_shadow_tree_flush();
884 
885    /* try stacking below */
886    if (e_comp->nocomp_ec && e_comp->nocomp_ec->comp_data && (ec != e_comp->nocomp_ec))
887      win = _e_comp_x_client_window_get(e_comp->nocomp_ec);
888    else
889      {
890         ec2 = ec;
891         do
892           {
893              ec2 = e_client_above_get(ec2);
894              if (ec2 && e_client_has_xwindow(ec2) && ec2->comp_data && (!ec2->new_client) &&
895                  (e_client_is_stacking(ec2) || ((!ec2->override) || ec2->internal)))
896                {
897                   if (ec2->layer != ec->layer) break;
898                   if (_e_comp_x_client_data_get(ec2)->need_reparent && (!_e_comp_x_client_data_get(ec2)->reparented)) continue;
899                   win = _e_comp_x_client_window_get(ec2);
900                }
901           } while (ec2 && (!win));
902      }
903 
904    /* try stacking above */
905    if (!win)
906      {
907         ec2 = ec;
908         do
909           {
910              ec2 = e_client_below_get(ec2);
911              if (ec2 && e_client_has_xwindow(ec2) && ec2->comp_data && (!ec2->new_client) &&
912                  (e_client_is_stacking(ec2) || ((!ec2->override) || ec2->internal)))
913                {
914                   if (ec2->layer != ec->layer) break;
915                   if (_e_comp_x_client_data_get(ec2)->need_reparent && (!_e_comp_x_client_data_get(ec2)->reparented)) continue;
916                   win = _e_comp_x_client_window_get(ec2);
917                   mode = ECORE_X_WINDOW_STACK_ABOVE;
918                }
919           } while (ec2 && (!win));
920      }
921 
922    /* just layer stack */
923    if (!win)
924      {
925         win = e_comp->layers[e_comp_canvas_layer_map(ec->layer)].win;
926         mode = ECORE_X_WINDOW_STACK_BELOW;
927      }
928    ecore_x_window_configure(cwin,
929                             ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
930                             ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
931                             0, 0, 0, 0, 0, win, mode);
932    _e_comp_x_post_client_idler_add(ec);
933    e_comp_x->restack = 1;
934    EINA_LIST_FOREACH(ec->e.state.video_child, l, ec2)
935      evas_object_stack_below(ec2->frame, ec->frame);
936 }
937 
938 static E_Client *
_e_comp_x_client_new(Ecore_X_Window win,Eina_Bool first)939 _e_comp_x_client_new(Ecore_X_Window win, Eina_Bool first)
940 {
941    E_Pixmap *cp;
942    E_Client *ec;
943 
944    cp = e_pixmap_new(E_PIXMAP_TYPE_X, win);
945    EINA_SAFETY_ON_NULL_RETURN_VAL(cp, NULL);
946 
947    ec = e_client_new(cp, first, 0);
948    return ec;
949 }
950 
951 static void
_e_comp_x_client_pri_raise(E_Client * ec)952 _e_comp_x_client_pri_raise(E_Client *ec)
953 {
954    if (ec->netwm.pid <= 0) return;
955    if (ec->netwm.pid == getpid()) return;
956    _pri_adj(ec->netwm.pid,
957             e_config->priority - 1, -1, EINA_FALSE,
958 //            EINA_TRUE, EINA_TRUE);
959             EINA_TRUE, EINA_FALSE);
960 //   printf("WIN: pid %i, title %s (HI!!!!!!!!!!!!!!!!!!)\n",
961 //          ec->netwm.pid, e_client_util_name_get(ec));
962 }
963 
964 static void
_e_comp_x_client_pri_norm(E_Client * ec)965 _e_comp_x_client_pri_norm(E_Client *ec)
966 {
967    if (ec->netwm.pid <= 0) return;
968    if (ec->netwm.pid == getpid()) return;
969    _pri_adj(ec->netwm.pid,
970             e_config->priority, 1, EINA_FALSE,
971 //            EINA_TRUE, EINA_TRUE);
972             EINA_TRUE, EINA_FALSE);
973 //   printf("WIN: pid %i, title %s (NORMAL)\n",
974 //          ec->netwm.pid, e_client_util_name_get(ec));
975 }
976 
977 static void
_e_comp_x_client_shape_input_rectangle_set(E_Client * ec)978 _e_comp_x_client_shape_input_rectangle_set(E_Client *ec)
979 {
980    Ecore_X_Window win = e_client_util_pwin_get(ec);
981 
982    if (ec->override || (!_e_comp_x_client_data_get(ec)->reparented)) return;
983 
984    if (ec->visible && (!ec->comp_hidden))
985      ecore_x_composite_window_events_enable(win);
986    else
987      ecore_x_composite_window_events_disable(win);
988 }
989 
990 static void
_e_comp_x_evas_color_set_cb(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)991 _e_comp_x_evas_color_set_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
992 {
993    E_Client *ec = data;
994    int a;
995 
996    if (!_e_comp_x_client_data_get(ec)) return;
997    evas_object_color_get(obj, NULL, NULL, NULL, &a);
998    if (a == ec->netwm.opacity) return;
999    ec->netwm.opacity_changed = 1;
1000    _e_comp_x_post_client_idler_add(ec);
1001 }
1002 
1003 static void
_e_comp_x_evas_ping_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1004 _e_comp_x_evas_ping_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1005 {
1006    E_Client *ec = data;
1007 
1008    if (!_e_comp_x_client_data_get(ec)) return;
1009    ecore_x_netwm_ping_send(e_client_util_win_get(ec));
1010 }
1011 
1012 static void
_e_comp_x_evas_kill_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1013 _e_comp_x_evas_kill_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1014 {
1015    E_Client *ec = data;
1016 
1017    if (!_e_comp_x_client_data_get(ec)) return;
1018    ecore_x_kill(e_client_util_win_get(ec));
1019 }
1020 
1021 static void
_e_comp_x_evas_delete_request_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1022 _e_comp_x_evas_delete_request_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1023 {
1024    E_Client *ec = data;
1025 
1026    if (!_e_comp_x_client_data_get(ec)) return;
1027    if (ec->netwm.ping)
1028      e_client_ping(ec);
1029    ecore_x_window_delete_request_send(e_client_util_win_get(ec));
1030 }
1031 
1032 static void
_e_comp_x_evas_comp_hidden_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1033 _e_comp_x_evas_comp_hidden_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1034 {
1035    E_Client *tmp, *ec = data;
1036    Eina_List *l;
1037    Ecore_X_Window win;
1038 
1039    if (!_e_comp_x_client_data_get(ec)) return;
1040    if (_e_comp_x_client_data_get(ec)->need_reparent) return;
1041    win = _e_comp_x_client_window_get(ec);
1042 
1043    EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
1044      {
1045         Ecore_X_Window cwin;
1046 
1047         cwin = _e_comp_x_client_window_get(tmp);
1048         if (ec->comp_hidden)
1049           ecore_x_window_hide(cwin);
1050         else
1051           ecore_x_window_show(cwin);
1052      }
1053 
1054    if ((ec->internal) && (win == e_client_util_win_get(ec))) return;
1055    if (ec->comp_hidden)
1056      ecore_x_composite_window_events_disable(win);
1057    else
1058      ecore_x_composite_window_events_enable(win);
1059     ecore_x_window_ignore_set(win, ec->comp_hidden);
1060 }
1061 
1062 static void
_e_comp_x_evas_shade_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1063 _e_comp_x_evas_shade_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1064 {
1065    E_Client *ec = data;
1066    Eina_List *l;
1067    E_Client *tmp;
1068 
1069    if (!_e_comp_x_client_data_get(ec)) return;
1070    EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
1071      ecore_x_window_hide(e_client_util_pwin_get(tmp));
1072 
1073    ecore_x_window_shadow_tree_flush();
1074 }
1075 
1076 static void
_e_comp_x_evas_frame_recalc_cb(void * data,Evas_Object * obj,void * event_info)1077 _e_comp_x_evas_frame_recalc_cb(void *data, Evas_Object *obj, void *event_info)
1078 {
1079    E_Client *ec = data;
1080    E_Comp_Object_Frame *fr = event_info;
1081 
1082    if (!_e_comp_x_client_data_get(ec)) return;
1083    if (evas_object_visible_get(obj))
1084      _e_comp_x_client_frame_update(ec, fr->l, fr->r, fr->t, fr->b);
1085    else
1086      _e_comp_x_client_data_get(ec)->frame_update = 1;
1087    ec->post_move = ec->post_resize = 1;
1088    _e_comp_x_post_client_idler_add(ec);
1089 }
1090 
1091 static void
_e_comp_x_evas_move_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1092 _e_comp_x_evas_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1093 {
1094    E_Client *ec = data;
1095 
1096    if (!_e_comp_x_client_data_get(ec)) return;
1097    if (_e_comp_x_client_data_get(ec)->moving && (!_e_comp_x_client_data_get(ec)->unredirected_single))
1098      {
1099         if (_e_comp_x_client_data_get(ec)->move_counter++ < MOVE_COUNTER_LIMIT) return;
1100         _e_comp_x_client_data_get(ec)->move_counter = 0;
1101      }
1102 
1103    ecore_x_window_shadow_tree_flush();
1104    ec->post_move = 1;
1105    _e_comp_x_post_client_idler_add(ec);
1106 }
1107 
1108 static void
_e_comp_x_evas_resize_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1109 _e_comp_x_evas_resize_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1110 {
1111    E_Client *ec = data;
1112 
1113    if (!_e_comp_x_client_data_get(ec)) return;
1114    if (ec->shading || ec->shaded) return;
1115    if (!e_pixmap_size_changed(ec->pixmap, ec->client.w, ec->client.h)) return;
1116 
1117    ecore_x_window_shadow_tree_flush();
1118 
1119    if (ec->e.state.video)
1120      {
1121         if (ec->e.state.video_position.updated)
1122           {
1123              ecore_x_window_move(e_client_util_pwin_get(ec),
1124                                  ec->e.state.video_parent_client->client.x +
1125                                  ec->e.state.video_position.x,
1126                                  ec->e.state.video_parent_client->client.y +
1127                                  ec->e.state.video_position.y);
1128              ec->e.state.video_position.updated = 0;
1129           }
1130      }
1131    else if (ec->changes.pos)
1132      {
1133         E_Client *tmp;
1134         Eina_List *l;
1135 
1136         EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
1137           ecore_x_window_move(e_client_util_pwin_get(tmp),
1138                               ec->client.x + tmp->e.state.video_position.x,
1139                               ec->client.y + tmp->e.state.video_position.y);
1140      }
1141 
1142    ec->post_resize = 1;
1143    if (e_pixmap_is_x(ec->pixmap))
1144      e_comp_object_render_update_del(ec->frame);
1145    _e_comp_x_post_client_idler_add(ec);
1146 }
1147 
1148 static void
_e_comp_x_client_hide(E_Client * ec)1149 _e_comp_x_client_hide(E_Client *ec)
1150 {
1151    unsigned int visible = 0;
1152 
1153    ecore_x_window_shadow_tree_flush();
1154    if ((!ec->iconic) && (!ec->override))
1155      ecore_x_window_prop_card32_set(e_client_util_win_get(ec), E_ATOM_MAPPED, &visible, 1);
1156 
1157    _e_comp_x_client_data_get(ec)->iconic = ec->iconic && (!e_comp_object_mirror_visibility_check(ec->frame));
1158    if (ec->unredirected_single || _e_comp_x_client_data_get(ec)->iconic)
1159      ecore_x_window_hide(_e_comp_x_client_window_get(ec));
1160    if (_e_comp_x_client_data_get(ec)->iconic)
1161      e_hints_window_iconic_set(ec);
1162 }
1163 
1164 static void
_e_comp_x_evas_hide_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1165 _e_comp_x_evas_hide_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1166 {
1167    E_Client *ec = data, *tmp;
1168    Eina_List *l;
1169 
1170    if (ec == mouse_client)
1171      {
1172         mouse_client = NULL;
1173         E_FREE_FUNC(mouse_in_job, ecore_job_del);
1174      }
1175 
1176    if (!_e_comp_x_client_data_get(ec)) return; // already deleted, happens with internal wins
1177    _e_comp_x_client_hide(ec);
1178 
1179    EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
1180      evas_object_hide(tmp->frame);
1181 
1182    if (e_comp_config_get()->send_flush)
1183      ecore_x_e_comp_flush_send(e_client_util_win_get(ec));
1184    if (e_comp_config_get()->send_dump)
1185      ecore_x_e_comp_dump_send(e_client_util_win_get(ec));
1186 }
1187 
1188 static void
_e_comp_x_client_show(E_Client * ec)1189 _e_comp_x_client_show(E_Client *ec)
1190 {
1191    unsigned int visible = 1;
1192    Ecore_X_Window win;
1193 
1194    win = e_client_util_win_get(ec);
1195    ecore_x_window_shadow_tree_flush();
1196    if ((!_e_comp_x_client_data_get(ec)->need_reparent) && (!ec->override))
1197      ecore_x_window_show(win);
1198    if (ec->unredirected_single || _e_comp_x_client_data_get(ec)->iconic)
1199      {
1200         e_pixmap_clear(ec->pixmap);
1201         ecore_x_window_show(_e_comp_x_client_window_get(ec));
1202         _e_comp_x_client_data_get(ec)->iconic = 0;
1203      }
1204    if (!ec->override)
1205      e_hints_window_visible_set(ec);
1206 
1207    ecore_x_window_prop_card32_set(win, E_ATOM_MAPPED, &visible, 1);
1208    ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &visible, 1);
1209 }
1210 
1211 static void
_e_comp_x_evas_show_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1212 _e_comp_x_evas_show_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1213 {
1214    E_Client *ec = data, *tmp;
1215    Eina_List *l;
1216 
1217    if (!_e_comp_x_client_data_get(ec)) return;
1218    _e_comp_x_client_show(ec);
1219 
1220    if (_e_comp_x_client_data_get(ec)->frame_update)
1221      {
1222         int ll, r, t, b;
1223 
1224         e_comp_object_frame_geometry_get(obj, &ll, &r, &t, &b);
1225         _e_comp_x_client_frame_update(ec, ll, r, t, b);
1226      }
1227 
1228    EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
1229      {
1230         evas_object_show(tmp->frame);
1231         ecore_x_window_show(e_client_util_pwin_get(tmp));
1232      }
1233 }
1234 
1235 static void
_e_comp_x_evas_stack_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1236 _e_comp_x_evas_stack_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1237 {
1238    if (evas_object_data_get(obj, "client_restack"))
1239      _e_comp_x_client_stack(data);
1240 }
1241 
1242 static void
_e_comp_x_evas_unfullscreen_zoom_cb(void * data EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1243 _e_comp_x_evas_unfullscreen_zoom_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1244 {
1245    if ((screen_size.width != -1) && (screen_size.height != -1))
1246      {
1247         ecore_x_randr_screen_primary_output_size_set(e_comp->root,
1248                                                      screen_size_index);
1249         screen_size.width = -1;
1250         screen_size.height = -1;
1251      }
1252 }
1253 
1254 static void
_e_comp_x_evas_fullscreen_zoom_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1255 _e_comp_x_evas_fullscreen_zoom_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1256 {
1257    E_Client *ec = data;
1258    Ecore_X_Randr_Screen_Size_MM *sizes;
1259    int num_sizes, i, best_size_index = 0;
1260 
1261    ecore_x_randr_screen_primary_output_current_size_get(e_comp->root,
1262                                                         &screen_size.width,
1263                                                         &screen_size.height,
1264                                                         NULL, NULL, NULL);
1265    sizes = ecore_x_randr_screen_primary_output_sizes_get(e_comp->root,
1266                                                          &num_sizes);
1267    if (sizes)
1268      {
1269         Ecore_X_Randr_Screen_Size best_size = { -1, -1 };
1270         int best_dist = INT_MAX, dist;
1271 
1272         for (i = 0; i < num_sizes; i++)
1273           {
1274              if ((sizes[i].width > ec->w) && (sizes[i].height > ec->h))
1275                {
1276                   dist = (sizes[i].width * sizes[i].height) - (ec->w * ec->h);
1277                   if (dist < best_dist)
1278                     {
1279                        best_size.width = sizes[i].width;
1280                        best_size.height = sizes[i].height;
1281                        best_dist = dist;
1282                        best_size_index = i;
1283                     }
1284                }
1285           }
1286         if (((best_size.width != -1) && (best_size.height != -1)) &&
1287             ((best_size.width != screen_size.width) ||
1288              (best_size.height != screen_size.height)))
1289           {
1290              if (ecore_x_randr_screen_primary_output_size_set(e_comp->root,
1291                                                               best_size_index))
1292                screen_size_index = best_size_index;
1293              evas_object_geometry_set(ec->frame, 0, 0, best_size.width, best_size.height);
1294           }
1295         else
1296           {
1297              screen_size.width = -1;
1298              screen_size.height = -1;
1299              evas_object_geometry_set(ec->frame, 0, 0, ec->zone->w, ec->zone->h);
1300           }
1301         free(sizes);
1302      }
1303    else
1304      {
1305         evas_object_geometry_set(ec->frame, ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h);
1306      }
1307 }
1308 
1309 static Eina_Bool
_e_comp_x_destroy(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Destroy * ev)1310 _e_comp_x_destroy(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Destroy *ev)
1311 {
1312    E_Client *ec;
1313 
1314    //INF("X DESTROY: %u", ev->win);
1315    e_comp_ignore_win_del(E_PIXMAP_TYPE_X, ev->win);
1316    ec = _e_comp_x_client_find_by_window(ev->win);
1317    if (!ec)
1318      {
1319         if (!e_comp_x->retry_clients) return ECORE_CALLBACK_RENEW;
1320         e_comp_x->retry_clients = eina_list_remove(e_comp_x->retry_clients, (uintptr_t*)(unsigned long)ev->win);
1321         if (!e_comp_x->retry_clients)
1322           E_FREE_FUNC(e_comp_x->retry_timer, ecore_timer_del);
1323         return ECORE_CALLBACK_PASS_ON;
1324      }
1325    if (_e_comp_x_client_data_get(ec))
1326      {
1327         if (_e_comp_x_client_data_get(ec)->reparented)
1328           e_client_comp_hidden_set(ec, 1);
1329         evas_object_pass_events_set(ec->frame, 1);
1330         evas_object_hide(ec->frame);
1331         _e_comp_x_client_data_get(ec)->deleted = 1;
1332         DELD(ec, 2);
1333         e_object_del(E_OBJECT(ec));
1334      }
1335    return ECORE_CALLBACK_PASS_ON;
1336 }
1337 
1338 static Eina_Bool
_e_comp_x_resize_request(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Resize_Request * ev)1339 _e_comp_x_resize_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Resize_Request *ev)
1340 {
1341    E_Client *ec;
1342    int w, h;
1343 
1344    ec = _e_comp_x_client_find_by_window(ev->win);
1345    if (!ec)
1346      {
1347         if (!e_comp_find_by_window(ev->win)) ecore_x_window_resize(ev->win, ev->w, ev->h);
1348         return ECORE_CALLBACK_PASS_ON;
1349      }
1350    w = ev->w, h = ev->h;
1351    if (ec->zone && (e_config->geometry_auto_resize_limit == 1))
1352      {
1353         int zx, zy, zw, zh;
1354 
1355         e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
1356         if (w > zw)
1357           w = zw;
1358 
1359         if (h > zh)
1360           h = zh;
1361      }
1362    if ((w != ec->w) || (h != ec->h))
1363      {
1364         evas_object_resize(ec->frame, w, h);
1365      }
1366    return ECORE_CALLBACK_RENEW;
1367 }
1368 
1369 static void
_e_comp_x_evas_mirror_hidden(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1370 _e_comp_x_evas_mirror_hidden(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1371 {
1372    E_Client *ec = data;
1373 
1374    if (!_e_comp_x_client_data_get(ec)) return;
1375    if ((!ec->iconic) || (!_e_comp_x_client_data_get(ec)->iconic)) return;
1376    _e_comp_x_client_hide(ec);
1377 }
1378 
1379 static void
_e_comp_x_evas_mirror_visible(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1380 _e_comp_x_evas_mirror_visible(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1381 {
1382    E_Client *ec = data;
1383 
1384    if (!_e_comp_x_client_data_get(ec)) return;
1385    if ((!ec->iconic) || _e_comp_x_client_data_get(ec)->iconic) return;
1386    _e_comp_x_client_show(ec);
1387 }
1388 
1389 static void
_e_comp_x_client_evas_init(E_Client * ec)1390 _e_comp_x_client_evas_init(E_Client *ec)
1391 {
1392    if (_e_comp_x_client_data_get(ec)->evas_init) return;
1393    _e_comp_x_client_data_get(ec)->evas_init = 1;
1394    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESTACK, _e_comp_x_evas_stack_cb, ec);
1395    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW, _e_comp_x_evas_show_cb, ec);
1396    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_HIDE, _e_comp_x_evas_hide_cb, ec);
1397    if (!ec->override)
1398      {
1399         evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOVE, _e_comp_x_evas_move_cb, ec);
1400         evas_object_smart_callback_add(ec->frame, "client_resize", _e_comp_x_evas_resize_cb, ec);
1401      }
1402    evas_object_smart_callback_add(ec->frame, "frame_recalc_done", _e_comp_x_evas_frame_recalc_cb, ec);
1403    evas_object_smart_callback_add(ec->frame, "shade_done", _e_comp_x_evas_shade_cb, ec);
1404    evas_object_smart_callback_add(ec->frame, "comp_hidden", _e_comp_x_evas_comp_hidden_cb, ec);
1405    evas_object_smart_callback_add(ec->frame, "delete_request", _e_comp_x_evas_delete_request_cb, ec);
1406    evas_object_smart_callback_add(ec->frame, "kill_request", _e_comp_x_evas_kill_cb, ec);
1407    evas_object_smart_callback_add(ec->frame, "ping", _e_comp_x_evas_ping_cb, ec);
1408    evas_object_smart_callback_add(ec->frame, "color_set", _e_comp_x_evas_color_set_cb, ec);
1409    evas_object_smart_callback_add(ec->frame, "fullscreen_zoom", _e_comp_x_evas_fullscreen_zoom_cb, ec);
1410    evas_object_smart_callback_add(ec->frame, "unfullscreen_zoom", _e_comp_x_evas_unfullscreen_zoom_cb, ec);
1411    evas_object_smart_callback_add(ec->frame, "visibility_force", _e_comp_x_evas_mirror_visible, ec);
1412    evas_object_smart_callback_add(ec->frame, "visibility_normal", _e_comp_x_evas_mirror_hidden, ec);
1413    /* force apply this since we haven't set up our smart cb previously */
1414    _e_comp_x_evas_comp_hidden_cb(ec, NULL, NULL);
1415 }
1416 
1417 static Eina_Bool
_e_comp_x_object_add(void * d EINA_UNUSED,int t EINA_UNUSED,E_Event_Comp_Object * ev)1418 _e_comp_x_object_add(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Comp_Object *ev)
1419 {
1420    E_Client *ec;
1421 
1422    ec = e_comp_object_client_get(ev->comp_object);
1423    if ((!ec) || e_object_is_del(E_OBJECT(ec)) || ec->re_manage) return ECORE_CALLBACK_RENEW;
1424    E_COMP_X_PIXMAP_CHECK ECORE_CALLBACK_RENEW;
1425    _e_comp_x_client_evas_init(ec);
1426    _e_comp_x_client_stack(ec);
1427    return ECORE_CALLBACK_RENEW;
1428 }
1429 
1430 static Eina_Bool
_e_comp_x_show_request(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Show_Request * ev)1431 _e_comp_x_show_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Show_Request *ev)
1432 {
1433    E_Client *ec;
1434 
1435    //INF("X SHOW REQ: %u", ev->win);
1436    ec = _e_comp_x_client_find_by_window(ev->win);
1437    if (e_comp_ignore_win_find(ev->win) ||
1438      (ec && (ec->ignored || ec->override)) ||
1439      (!e_comp_find_by_window(ev->parent)) ||
1440      (ev->parent != e_comp->root))
1441      {
1442         if ((!ec) && (!eina_hash_find(dead_wins, &ev->parent)))
1443           {
1444              ecore_x_window_show(ev->win);
1445              return ECORE_CALLBACK_RENEW;
1446           }
1447      }
1448    if (!ec)
1449      ec = _e_comp_x_client_new(ev->win, 0);
1450    if (!ec)
1451      {
1452         ecore_x_window_show(ev->win);
1453         return ECORE_CALLBACK_RENEW;
1454      }
1455    if ((e_comp->comp_type != E_PIXMAP_TYPE_X) && ec->ignored)
1456      {
1457         ec->visible = 1;
1458         if (ec->comp_data->need_reparent)
1459           _e_comp_x_hook_client_pre_frame_assign(NULL, ec);
1460         else
1461           ecore_x_window_show(ev->win);
1462         return ECORE_CALLBACK_RENEW;
1463      }
1464 
1465    if ((!_e_comp_x_client_data_get(ec)->reparented) && (!e_client_util_ignored_get(ec)))
1466      {
1467         if (!ec->override)
1468           _e_comp_x_client_data_get(ec)->need_reparent = 1;
1469         ec->visible = 1;
1470         EC_CHANGED(ec);
1471         return ECORE_CALLBACK_RENEW;
1472      }
1473    if (ec->iconic)
1474      {
1475         if (!ec->lock_client_iconify)
1476           e_client_uniconify(ec);
1477      }
1478    else
1479      {
1480         /* FIXME: make client "urgent" for a bit - it wants attention */
1481         /*	e_client_show(ec); */
1482         if (!ec->lock_client_stacking)
1483           evas_object_raise(ec->frame);
1484      }
1485    return ECORE_CALLBACK_RENEW;
1486 }
1487 
1488 static void
_e_comp_x_show_helper(E_Client * ec)1489 _e_comp_x_show_helper(E_Client *ec)
1490 {
1491    if ((!ec->override) && (!ec->re_manage) && (!_e_comp_x_client_data_get(ec)->first_map) &&
1492        (!_e_comp_x_client_data_get(ec)->reparented) && (!_e_comp_x_client_data_get(ec)->need_reparent))
1493      {
1494         /* this is most likely an internal window */
1495         _e_comp_x_client_data_get(ec)->need_reparent = 1;
1496         ec->visible = 1;
1497         if (ec->internal_elm_win)
1498           ec->take_focus = 1;
1499         EC_CHANGED(ec);
1500      }
1501    else if (ec->override)
1502      {
1503         if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
1504           {
1505              ec->visible = 1;
1506              return;
1507           }
1508         ec->redirected = !ec->input_only;
1509         ec->changes.visible = ec->visible = 1;
1510         EC_CHANGED(ec);
1511         if (!_e_comp_x_client_data_get(ec)->first_map)
1512           _e_comp_x_client_evas_init(ec);
1513      }
1514    if (!ec->input_only)
1515      _e_comp_x_client_damage_add(ec);
1516    if (!_e_comp_x_client_data_get(ec)->need_reparent)
1517      {
1518         e_pixmap_usable_set(ec->pixmap, 1);
1519         if (ec->hidden || ec->iconic)
1520           {
1521              evas_object_hide(ec->frame);
1522              e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
1523           }
1524         else if (ec->override || (ec->icccm.state == ECORE_X_WINDOW_STATE_HINT_NORMAL))
1525           evas_object_show(ec->frame);
1526         _e_comp_x_client_data_get(ec)->first_map = 1;
1527         if (ec->internal_elm_win)
1528           {
1529              _e_comp_x_post_client_idler_add(ec);
1530              ec->post_move = 1;
1531              ec->post_resize = 1;
1532              e_comp_x->restack = 1;
1533           }
1534      }
1535 }
1536 
1537 static Eina_Bool
_e_comp_x_show_retry(void * data EINA_UNUSED)1538 _e_comp_x_show_retry(void *data EINA_UNUSED)
1539 {
1540    uintptr_t *win;
1541 
1542    EINA_LIST_FREE(e_comp_x->retry_clients, win)
1543      {
1544         E_Client *ec;
1545 
1546         ec = _e_comp_x_client_new((Ecore_X_Window)(uintptr_t)win, 0);
1547         if (ec) _e_comp_x_show_helper(ec);
1548      }
1549 
1550    e_comp_x->retry_timer = NULL;
1551    return EINA_FALSE;
1552 }
1553 
1554 static Eina_Bool
_e_comp_x_show(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Show * ev)1555 _e_comp_x_show(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Show *ev)
1556 {
1557    E_Client *ec;
1558 
1559    //INF("X SHOW: %u", ev->win);
1560    ec = _e_comp_x_client_find_by_window(ev->win);
1561    if (!ec)
1562      {
1563         E_Comp *c;
1564 
1565         if (e_comp_ignore_win_find(ev->win)) return ECORE_CALLBACK_RENEW;
1566         c = e_comp_find_by_window(ev->event_win);
1567         if (!c) return ECORE_CALLBACK_RENEW;
1568         if (ev->event_win != e_comp->root) return ECORE_CALLBACK_RENEW;
1569         if ((c->win == ev->win) || (c->ee_win == ev->win) ||
1570             (c->root == ev->win) || (c->cm_selection == ev->win)) return ECORE_CALLBACK_RENEW;
1571         /* some window which we haven't made a client for yet but need to */
1572         ec = _e_comp_x_client_new(ev->win, 0);
1573         if (!ec)
1574           {
1575              if (c->x_comp_data->retry_timer)
1576                ecore_timer_loop_reset(c->x_comp_data->retry_timer);
1577              else
1578                c->x_comp_data->retry_timer = ecore_timer_loop_add(0.02, _e_comp_x_show_retry, c);
1579              c->x_comp_data->retry_clients = eina_list_append(c->x_comp_data->retry_clients, (uintptr_t*)(unsigned long)ev->win);
1580              return ECORE_CALLBACK_RENEW;
1581           }
1582      }
1583    else if (e_object_is_del(E_OBJECT(ec)) || ec->already_unparented)
1584      return ECORE_CALLBACK_RENEW;
1585    _e_comp_x_show_helper(ec);
1586    if (ec->internal || (!ec->override))
1587      _e_comp_x_client_stack(ec);
1588    return ECORE_CALLBACK_RENEW;
1589 }
1590 
1591 static Eina_Bool
_e_comp_x_hide(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Hide * ev)1592 _e_comp_x_hide(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Hide *ev)
1593 {
1594    E_Client *ec;
1595    Eina_Bool hid = EINA_FALSE;
1596 
1597    //INF("X HIDE: %u", ev->win);
1598    ec = _e_comp_x_client_find_by_window(ev->win);
1599    if (!ec)
1600      {
1601         if (!e_comp_x->retry_clients) return ECORE_CALLBACK_RENEW;
1602         e_comp_x->retry_clients = eina_list_remove(e_comp_x->retry_clients, (uintptr_t*)(unsigned long)ev->win);
1603         if (!e_comp_x->retry_clients)
1604           E_FREE_FUNC(e_comp_x->retry_timer, ecore_timer_del);
1605         return ECORE_CALLBACK_PASS_ON;
1606      }
1607    if ((!ec->visible) || (ec->hidden && ec->unredirected_single))
1608      {
1609         //INF("IGNORED");
1610         return ECORE_CALLBACK_PASS_ON;
1611      }
1612 
1613    if (ev->win != ev->event_win)
1614      {
1615         if ((!ec->override) && (!ev->send_event)) return ECORE_CALLBACK_PASS_ON;
1616      }
1617    if (ec->ignore_first_unmap > 0)
1618      {
1619         ec->ignore_first_unmap--;
1620         return ECORE_CALLBACK_PASS_ON;
1621      }
1622    /* Don't delete hidden or iconified windows */
1623    if (ec->iconic)
1624      {
1625         /* Only hide the border if it is visible */
1626         hid = EINA_TRUE;
1627         evas_object_hide(ec->frame);
1628      }
1629    else
1630      {
1631         hid = EINA_TRUE;
1632         evas_object_hide(ec->frame);
1633         if (ec->internal)
1634           e_hints_window_hidden_set(ec);
1635         else
1636           {
1637              if (ec->exe_inst && ec->exe_inst->exe)
1638                ec->exe_inst->phony = 0;
1639              DELD(ec, 3);
1640              e_object_del(E_OBJECT(ec));
1641           }
1642      }
1643    if (hid)
1644      _e_comp_x_focus_check();
1645    return ECORE_CALLBACK_PASS_ON;
1646 }
1647 
1648 static Eina_Bool
_e_comp_x_reparent(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Reparent * ev)1649 _e_comp_x_reparent(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Reparent *ev)
1650 {
1651    E_Client *ec;
1652 
1653    ec = _e_comp_x_client_find_by_window(ev->win);
1654    if ((!ec) || (ev->win == e_client_util_pwin_get(ec))) return ECORE_CALLBACK_PASS_ON;
1655    DBG("== repar [%u] to [%u]", ev->win, ev->parent);
1656    /* FIXME: this is almost definitely wrong */
1657    if (ev->parent != e_client_util_pwin_get(ec))
1658      {
1659         e_pixmap_parent_window_set(ec->pixmap, ev->parent);
1660         if (!e_object_is_del(E_OBJECT(ec)))
1661           e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
1662      }
1663    return ECORE_CALLBACK_PASS_ON;
1664 }
1665 
1666 static Eina_Bool
_e_comp_x_configure(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Configure * ev)1667 _e_comp_x_configure(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Configure *ev)
1668 {
1669    E_Client *ec;
1670    Eina_Bool move, resize;
1671 
1672    if (e_comp_find_by_window(ev->win))
1673      {
1674         // do not handle this here - use randr events
1675         //e_comp_canvas_resize(ev->w, ev->h);
1676         return ECORE_CALLBACK_RENEW;
1677      }
1678    ec = _e_comp_x_client_find_by_window(ev->win);
1679    if ((!ec) || (!ec->override) || (!ev->override) || e_client_is_stacking(ec)) return ECORE_CALLBACK_PASS_ON;
1680 
1681    //INF("configure %p: %d,%d %dx%d", ec, ev->x, ev->y, ev->w, ev->h);
1682    if (ev->abovewin == 0)
1683      {
1684         if (e_client_below_get(ec))
1685           evas_object_lower(ec->frame);
1686      }
1687    else
1688      {
1689         E_Client *ec2 = _e_comp_x_client_find_by_window(ev->abovewin);
1690 
1691         if (ec2)
1692           {
1693              /* client(ec) wants to be above a layer client(ec2) */
1694              if (e_client_is_stacking(ec2)) //is it a stacking placeholder window?
1695                {
1696                   E_Client *ec3;
1697 
1698                   ec3 = e_client_above_get(ec2);
1699                   /* stack under next client(ec3) */
1700                   if (ec3)
1701                     {
1702                        evas_object_layer_set(ec->frame, ec3->layer);
1703                        if (!e_client_is_stacking(ec3))
1704                          evas_object_stack_below(ec->frame, ec3->frame);
1705                     }
1706                   else //force override to obey our stacking
1707                     evas_object_layer_set(ec->frame, ec2->layer);
1708                }
1709              else
1710                {
1711                   evas_object_layer_set(ec->frame, ec2->layer);
1712                   evas_object_stack_above(ec->frame, ec2->frame);
1713                }
1714           }
1715         else
1716           evas_object_layer_set(ec->frame, E_LAYER_CLIENT_PRIO);
1717      }
1718    move = (ec->client.x != ev->x) || (ec->client.y != ev->y);
1719    resize = (ec->client.w != ev->w) || (ec->client.h != ev->h);
1720    if (!ec->internal)
1721      _e_comp_x_client_data_get(ec)->pw = ev->w, _e_comp_x_client_data_get(ec)->ph = ev->h;
1722    EINA_RECTANGLE_SET(&ec->client, ev->x, ev->y, ev->w, ev->h);
1723    if (move)
1724      evas_object_move(ec->frame, ev->x, ev->y);
1725    if (resize && e_pixmap_is_x(ec->pixmap))
1726      {
1727         e_pixmap_dirty(ec->pixmap);
1728         evas_object_resize(ec->frame, ev->w, ev->h);
1729      }
1730    return ECORE_CALLBACK_RENEW;
1731 }
1732 
1733 static Eina_Bool
_e_comp_x_configure_request_timer(void * d)1734 _e_comp_x_configure_request_timer(void *d)
1735 {
1736    Pending_Configure *pc = d;
1737    eina_hash_list_remove(pending_configures, &pc->win, pc);
1738    free(pc);
1739    return EINA_FALSE;
1740 }
1741 
1742 static Eina_Bool
_e_comp_x_configure_request(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Configure_Request * ev)1743 _e_comp_x_configure_request(void *data  EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Configure_Request *ev)
1744 {
1745    E_Client *ec;
1746    Eina_Bool move = EINA_FALSE, resize = EINA_FALSE;
1747    int ox, oy, ow, oh;
1748    int x, y, w, h;
1749 
1750 //   printf("configure request {0x%08x}  %4i,%4i %4ix%4i b=%i [%c%c%c%c]\n",
1751 //          ev->win, ev->x, ev->y, ev->w, ev->h, ev->border,
1752 //          ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X ? 'x' : ' ',
1753 //          ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y ? 'y' : ' ',
1754 //          ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W ? 'w' : ' ',
1755 //          ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H ? 'h' : ' ');
1756    if (e_comp_find_by_window(ev->win)) return ECORE_CALLBACK_RENEW;
1757    ec = _e_comp_x_client_find_by_window(ev->win);
1758 
1759    /* pass through requests for windows we haven't/won't reparent yet */
1760    if (ec && (!_e_comp_x_client_data_get(ec)->need_reparent) && (!_e_comp_x_client_data_get(ec)->reparented))
1761      {
1762         if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
1763           _e_comp_x_client_data_get(ec)->initial_attributes.x = ev->x;
1764         if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
1765           _e_comp_x_client_data_get(ec)->initial_attributes.y = ev->y;
1766         if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
1767           ec->w = ec->client.w = _e_comp_x_client_data_get(ec)->initial_attributes.w = ev->w;
1768         if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
1769           ec->h = ec->client.h = _e_comp_x_client_data_get(ec)->initial_attributes.h = ev->h;
1770         ec->border_size = ev->border;
1771         ec->changes.size = 1;
1772         ec = NULL;
1773      }
1774    if (!ec)
1775      {
1776         if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
1777             (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
1778           {
1779              Pending_Configure *pc = E_NEW(Pending_Configure, 1);
1780              pc->point.x = ev->x;
1781              pc->point.y = ev->y;
1782              pc->timer = ecore_timer_loop_add(5.0, _e_comp_x_configure_request_timer, pc);
1783              pc->win = ev->win;
1784              eina_hash_list_append(pending_configures, &ev->win, pc);
1785           }
1786         ecore_x_window_configure(ev->win, ev->value_mask,
1787                                  ev->x, ev->y, ev->w, ev->h, ev->border,
1788                                  ev->abovewin, ev->detail);
1789         return ECORE_CALLBACK_PASS_ON;
1790      }
1791 
1792    x = ox = ec->client.x;
1793    y = oy = ec->client.y;
1794    w = ow = ec->client.w;
1795    h = oh = ec->client.h;
1796 
1797    if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
1798        (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
1799      {
1800         int zx, zy, zw, zh;
1801 
1802         e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
1803         if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
1804           {
1805              _e_comp_x_client_data_get(ec)->initial_attributes.x = ev->x;
1806              if (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE)
1807                x = E_CLAMP(ev->x, zx, zx + zw - ec->w);
1808              else
1809                x = ev->x;
1810           }
1811         if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
1812           {
1813              _e_comp_x_client_data_get(ec)->initial_attributes.y = ev->y;
1814              if (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE)
1815                y = E_CLAMP(ev->y, zy, zy + zh - ec->h);
1816              else
1817                y = ev->y;
1818           }
1819      }
1820 
1821    if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
1822        (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
1823      {
1824         if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
1825           w = ev->w, _e_comp_x_client_data_get(ec)->initial_attributes.w = ev->w;
1826         if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
1827           h = ev->h, _e_comp_x_client_data_get(ec)->initial_attributes.h = ev->h;
1828      }
1829 
1830    e_comp_object_frame_xy_adjust(ec->frame, x, y, &x, &y);
1831    e_comp_object_frame_wh_adjust(ec->frame, w, h, &w, &h);
1832 
1833    if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
1834        (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
1835      move = (x != ec->x) || (y != ec->y);
1836    if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
1837        (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
1838      resize = (w != ec->w) || (h != ec->h);
1839 
1840    if (move && (!ec->lock_client_location))
1841      {
1842         if ((ec->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
1843           {
1844              E_Zone *zone;
1845 
1846              e_comp_object_frame_xy_unadjust(ec->frame, x, y, &ec->saved.x, &ec->saved.y);
1847 
1848              zone = e_comp_zone_xy_get(x, y);
1849              if (zone && (zone->x || zone->y))
1850                {
1851                   ec->saved.x -= zone->x;
1852                   ec->saved.y -= zone->y;
1853                }
1854           }
1855         else if (!ec->maximize_override)
1856           {
1857              /* client is completely outside the screen, policy does not allow */
1858              if (((!E_INTERSECTS(x, y, ec->w, ec->h, 0, 0, e_comp->w - 5, e_comp->h - 5)) &&
1859                  (e_config->screen_limits != E_CLIENT_OFFSCREEN_LIMIT_ALLOW_FULL)) ||
1860                  /* client is partly outside the zone, policy does not allow */
1861                  (((!E_INSIDE(x, y, 0, 0, e_comp->w - 5, e_comp->h - 5)) &&
1862                   (!E_INSIDE(x + ec->w, y, 0, 0, e_comp->w - 5, e_comp->h - 5)) &&
1863                   (!E_INSIDE(x, y + ec->h, 0, 0, e_comp->w - 5, e_comp->h - 5)) &&
1864                   (!E_INSIDE(x + ec->w, y + ec->h, 0, 0, e_comp->w - 5, e_comp->h - 5))) &&
1865                   (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE))
1866                 )
1867                e_comp_object_util_center(ec->frame);
1868              else
1869                {
1870                   evas_object_move(ec->frame, x, y);
1871                }
1872           }
1873      }
1874 
1875    if (resize && (!ec->lock_client_size) && (move || ((!ec->maximized) && (!ec->fullscreen))))
1876      {
1877         if (ec->shaded || ((ec->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE))
1878           e_comp_object_frame_wh_unadjust(ec->frame, w, h, &ec->saved.w, &ec->saved.h);
1879         else if (!ec->maximize_override)
1880           {
1881              evas_object_resize(ec->frame, w, h);
1882           }
1883      }
1884    if (!ec->lock_client_stacking)
1885      {
1886         if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE) &&
1887             (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING))
1888           {
1889              E_Client *oec;
1890 
1891              if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE)
1892                {
1893                   oec = _e_comp_x_client_find_by_window(ev->abovewin);
1894                   if (oec)
1895                     {
1896                        evas_object_stack_above(ec->frame, oec->frame);
1897                     }
1898                   else
1899                     {
1900                        ecore_x_window_configure(e_client_util_pwin_get(ec),
1901                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
1902                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
1903                                                 0, 0, 0, 0, 0,
1904                                                 ev->abovewin, ECORE_X_WINDOW_STACK_ABOVE);
1905                     }
1906                }
1907              else if (ev->detail == ECORE_X_WINDOW_STACK_BELOW)
1908                {
1909                   oec = _e_comp_x_client_find_by_window(ev->abovewin);
1910                   if (oec)
1911                     {
1912                        evas_object_stack_below(ec->frame, oec->frame);
1913                     }
1914                   else
1915                     {
1916                        ecore_x_window_configure(e_client_util_pwin_get(ec),
1917                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
1918                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
1919                                                 0, 0, 0, 0, 0,
1920                                                 ev->abovewin, ECORE_X_WINDOW_STACK_BELOW);
1921                     }
1922                }
1923              else if (ev->detail == ECORE_X_WINDOW_STACK_TOP_IF)
1924                {
1925                   /* FIXME: do */
1926                }
1927              else if (ev->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
1928                {
1929                   /* FIXME: do */
1930                }
1931              else if (ev->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
1932                {
1933                   /* FIXME: do */
1934                }
1935           }
1936         else if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE)
1937           {
1938              if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE)
1939                {
1940                   evas_object_raise(ec->frame);
1941                }
1942              else if (ev->detail == ECORE_X_WINDOW_STACK_BELOW)
1943                {
1944                   evas_object_lower(ec->frame);
1945                }
1946              else if (ev->detail == ECORE_X_WINDOW_STACK_TOP_IF)
1947                {
1948                   /* FIXME: do */
1949                }
1950              else if (ev->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
1951                {
1952                   /* FIXME: do */
1953                }
1954              else if (ev->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
1955                {
1956                   /* FIXME: do */
1957                }
1958           }
1959      }
1960 
1961    /* FIXME: need to send synthetic stacking event to, as well as move/resize */
1962    if ((((ec->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE) && (move || resize)) ||
1963        ((!move) && (!resize)))
1964      {
1965         _e_comp_x_client_move_resize_send(ec);
1966      }
1967    return ECORE_CALLBACK_PASS_ON;
1968 }
1969 
1970 static Eina_Bool
_e_comp_x_stack_request(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Stack_Request * ev)1971 _e_comp_x_stack_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Stack_Request *ev)
1972 {
1973    E_Client *ec;
1974 
1975    ec = _e_comp_x_client_find_by_window(ev->win);
1976    if (!ec) return ECORE_CALLBACK_RENEW;
1977    if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE)
1978      evas_object_raise(ec->frame);
1979    else if (ev->detail == ECORE_X_WINDOW_STACK_BELOW)
1980      evas_object_lower(ec->frame);
1981    return ECORE_CALLBACK_PASS_ON;
1982 }
1983 
1984 static Eina_Bool
_e_comp_x_stack(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Stack * ev)1985 _e_comp_x_stack(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Stack *ev)
1986 {
1987    E_Client *ec = _e_comp_x_client_find_by_window(ev->win);
1988    if (!ec) return ECORE_CALLBACK_PASS_ON;
1989    if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE) evas_object_raise(ec->frame);
1990    else evas_object_lower(ec->frame);
1991    return ECORE_CALLBACK_PASS_ON;
1992 }
1993 
1994 static Eina_Bool
_e_comp_x_property(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Property * ev)1995 _e_comp_x_property(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Property *ev)
1996 {
1997    E_Client *ec;
1998 
1999    ec = _e_comp_x_client_find_by_window(ev->win);
2000    if (!ec) return ECORE_CALLBACK_RENEW;
2001 
2002    if (ev->atom == ECORE_X_ATOM_WM_NAME)
2003      {
2004         if ((!ec->netwm.name) &&
2005             (!ec->netwm.fetch.name))
2006           {
2007              ec->icccm.fetch.title = 1;
2008              EC_CHANGED(ec);
2009           }
2010      }
2011    else if (ev->atom == ECORE_X_ATOM_NET_WM_NAME)
2012      {
2013         ec->netwm.fetch.name = 1;
2014         EC_CHANGED(ec);
2015      }
2016    else if (ev->atom == ECORE_X_ATOM_WM_CLASS)
2017      {
2018         ec->icccm.fetch.name_class = 1;
2019         EC_CHANGED(ec);
2020      }
2021    else if (ev->atom == ECORE_X_ATOM_WM_ICON_NAME)
2022      {
2023         if ((!ec->netwm.icon_name) &&
2024             (!ec->netwm.fetch.icon_name))
2025           {
2026              ec->icccm.fetch.icon_name = 1;
2027              EC_CHANGED(ec);
2028           }
2029      }
2030    else if (ev->atom == ECORE_X_ATOM_NET_WM_ICON_NAME)
2031      {
2032         ec->netwm.fetch.icon_name = 1;
2033         EC_CHANGED(ec);
2034      }
2035    else if (ev->atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
2036      {
2037         ec->icccm.fetch.machine = 1;
2038         EC_CHANGED(ec);
2039      }
2040    else if (ev->atom == ECORE_X_ATOM_WM_PROTOCOLS)
2041      {
2042         ec->icccm.fetch.protocol = 1;
2043         EC_CHANGED(ec);
2044      }
2045    else if (ev->atom == ECORE_X_ATOM_WM_HINTS)
2046      {
2047         ec->icccm.fetch.hints = 1;
2048         EC_CHANGED(ec);
2049         if (ec->icccm.state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
2050           ec->ignored = 0;
2051      }
2052    else if (ev->atom == ECORE_X_ATOM_WM_NORMAL_HINTS)
2053      {
2054         if (_e_comp_x_client_data_get(ec)->internal_props_set)
2055           _e_comp_x_client_data_get(ec)->internal_props_set--;
2056         else
2057           {
2058              ec->icccm.fetch.size_pos_hints = 1;
2059              EC_CHANGED(ec);
2060           }
2061      }
2062    else if (ev->atom == ECORE_X_ATOM_MOTIF_WM_HINTS)
2063      {
2064         /*
2065            if ((ec->netwm.type == E_WINDOW_TYPE_UNKNOWN) &&
2066             (!ec->netwm.fetch.type))
2067            {
2068          */
2069         ec->mwm.fetch.hints = 1;
2070         EC_CHANGED(ec);
2071         /*
2072            }
2073          */
2074      }
2075    else if (ev->atom == ECORE_X_ATOM_WM_TRANSIENT_FOR)
2076      {
2077         ec->icccm.fetch.transient_for = 1;
2078         EC_CHANGED(ec);
2079      }
2080    else if (ev->atom == ECORE_X_ATOM_WM_CLIENT_LEADER)
2081      {
2082         ec->icccm.fetch.client_leader = 1;
2083         EC_CHANGED(ec);
2084      }
2085    else if (ev->atom == ECORE_X_ATOM_WM_WINDOW_ROLE)
2086      {
2087         ec->icccm.fetch.window_role = 1;
2088         EC_CHANGED(ec);
2089      }
2090    else if (ev->atom == ECORE_X_ATOM_NET_WM_ICON)
2091      {
2092         ec->netwm.fetch.icon = 1;
2093         EC_CHANGED(ec);
2094      }
2095    else if (ev->atom == ATM__QTOPIA_SOFT_MENU)
2096      {
2097         ec->qtopia.fetch.soft_menu = 1;
2098         EC_CHANGED(ec);
2099      }
2100    else if (ev->atom == ATM__QTOPIA_SOFT_MENUS)
2101      {
2102         ec->qtopia.fetch.soft_menus = 1;
2103         EC_CHANGED(ec);
2104      }
2105    else if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
2106      {
2107         ec->vkbd.fetch.state = 1;
2108         EC_CHANGED(ec);
2109      }
2110    else if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
2111      {
2112         ec->vkbd.fetch.vkbd = 1;
2113         EC_CHANGED(ec);
2114      }
2115    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
2116      {
2117         _e_comp_x_client_data_get(ec)->illume.conformant.fetch.conformant = 1;
2118         EC_CHANGED(ec);
2119      }
2120    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
2121      {
2122         _e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.state = 1;
2123         EC_CHANGED(ec);
2124      }
2125    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
2126      {
2127         _e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.quickpanel = 1;
2128         EC_CHANGED(ec);
2129      }
2130    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
2131      {
2132         _e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.priority.major = 1;
2133         EC_CHANGED(ec);
2134      }
2135    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
2136      {
2137         _e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.priority.minor = 1;
2138         EC_CHANGED(ec);
2139      }
2140    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
2141      {
2142         _e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.zone = 1;
2143         EC_CHANGED(ec);
2144      }
2145    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
2146      {
2147         _e_comp_x_client_data_get(ec)->illume.drag.fetch.locked = 1;
2148         EC_CHANGED(ec);
2149      }
2150    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_DRAG)
2151      {
2152         _e_comp_x_client_data_get(ec)->illume.drag.fetch.drag = 1;
2153         EC_CHANGED(ec);
2154      }
2155    else if (ev->atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
2156      {
2157         _e_comp_x_client_data_get(ec)->illume.win_state.fetch.state = 1;
2158         EC_CHANGED(ec);
2159      }
2160    /*
2161       else if (ev->atom == ECORE_X_ATOM_NET_WM_USER_TIME)
2162       {
2163         ec->netwm.fetch.user_time = 1;
2164         EC_CHANGED(ec);
2165       }
2166       else if (ev->atom == ECORE_X_ATOM_NET_WM_STRUT)
2167       {
2168         ec->netwm.fetch.strut = 1;
2169         EC_CHANGED(ec);
2170       }
2171       else if (ev->atom == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
2172       {
2173         ec->netwm.fetch.strut = 1;
2174         EC_CHANGED(ec);
2175       }
2176     */
2177    else if (ev->atom == ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER)
2178      {
2179         //printf("ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER\n");
2180      }
2181    else if (ev->atom == ECORE_X_ATOM_E_VIDEO_POSITION)
2182      {
2183         ec->e.fetch.video_position = 1;
2184         EC_CHANGED(ec);
2185      }
2186    else if (ev->atom == ECORE_X_ATOM_E_VIDEO_PARENT)
2187      {
2188         ec->e.fetch.video_parent = 1;
2189         EC_CHANGED(ec);
2190      }
2191    else if (ev->atom == ECORE_X_ATOM_NET_WM_STATE)
2192      {
2193         ec->netwm.fetch.state = 1;
2194         EC_CHANGED(ec);
2195      }
2196    else if (ev->atom == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY)
2197      {
2198         if (ec->netwm.opacity_changed)
2199           ec->netwm.opacity_changed = 0;
2200         else
2201           {
2202              ec->netwm.fetch.opacity = 1;
2203              EC_CHANGED(ec);
2204           }
2205      }
2206    else if (ev->atom == ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED)
2207      {
2208         ec->e.fetch.profile = 1;
2209         EC_CHANGED(ec);
2210      }
2211    else if (ev->atom == ECORE_X_ATOM_E_WINDOW_PROFILE_AVAILABLE_LIST)
2212      {
2213         ec->e.fetch.profile = 1;
2214         EC_CHANGED(ec);
2215      }
2216    else if (ev->atom == ATM_GTK_FRAME_EXTENTS)
2217      {
2218         _e_comp_x_client_data_get(ec)->fetch_gtk_frame_extents = 1;
2219         EC_CHANGED(ec);
2220      }
2221    else if (ev->atom == ATM_STEAM_GAME)
2222      {
2223         e_hints_window_steam_game_get(ec);
2224         ec->changes.icon = 1;
2225         EC_CHANGED(ec);
2226      }
2227 
2228    return ECORE_CALLBACK_RENEW;
2229 }
2230 
2231 static Eina_Bool
_e_comp_x_message(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Client_Message * ev)2232 _e_comp_x_message(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Client_Message *ev)
2233 {
2234    E_Client *ec;
2235 
2236    ec = _e_comp_x_client_find_by_window(ev->win);
2237    if (!ec)
2238      {
2239         char *name;
2240 
2241         if (!eina_log_domain_level_check(e_log_dom, EINA_LOG_LEVEL_DBG)) return ECORE_CALLBACK_RENEW;
2242         name = ecore_x_atom_name_get(ev->message_type);
2243         DBG("missed client message '%s' for %u", name, ev->win);
2244         free(name);
2245         return ECORE_CALLBACK_RENEW;
2246      }
2247    if (ev->message_type == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY)
2248      {
2249         ec->netwm.fetch.opacity = 1;
2250         EC_CHANGED(ec);
2251      }
2252    else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE)
2253      {
2254         if (ec->e.state.profile.use)
2255           {
2256              char *p = ecore_x_atom_name_get(ev->data.l[1]);
2257              if (e_client_desk_window_profile_available_check(ec, p))
2258                {
2259                   if (e_util_strcmp(p, ec->desk->window_profile))
2260                     {
2261                        E_Desk *old_desk = ec->desk;
2262                        E_Desk *desk = e_comp_desk_window_profile_get(p);
2263                        Eina_Bool was_focused = e_client_stack_focused_get(ec);
2264 
2265                        if ((desk) && (desk != old_desk))
2266                          {
2267                             e_client_desk_set(ec, desk);
2268                             if (was_focused)
2269                               e_desk_last_focused_focus(old_desk);
2270                          }
2271                     }
2272                }
2273              free(p);
2274           }
2275      }
2276    else if (ev->message_type == ECORE_X_ATOM_NET_ACTIVE_WINDOW)
2277      {
2278 #if 0 /* notes */
2279         if (e->data.l[0] == 0 /* 0 == old, 1 == client, 2 == pager */)
2280           {
2281           }
2282         timestamp = e->data.l[1];
2283         requestor_id e->data.l[2];
2284 #endif
2285         switch (e_config->window_activehint_policy)
2286           {
2287            case 0: break;
2288 
2289            case 1:
2290              e_client_urgent_set(ec, 1);
2291              break;
2292 
2293            default:
2294              if (e_client_action_get() || e_comp->nocomp)
2295                {
2296                   /* be helpful and ignore activates during window actions, but still set urgent */
2297                   e_client_urgent_set(ec, 1);
2298                   break;
2299                }
2300              if ((!starting) && (!ec->focused))
2301                {
2302                   if ((e_config->window_activehint_policy == E_ACTIVEHINT_POLICY_ACTIVATE_EXCLUDE) &&
2303                       (!ec->desk->visible))
2304                     e_client_urgent_set(ec, 1);
2305                   else
2306                     {
2307                        /* some apps, eg. libreoffice, create "modal" windows which
2308                         * do not have the netwm modal state set. instead, attempting to
2309                         * focus the parent window results in the app immediately trying to
2310                         * activate the "modal" window, triggering an infinite loop.
2311                         *
2312                         * by treating this "modal" window as a genuine modal window,
2313                         * we (eventually) can ignore this type of bad behavior and
2314                         * give the application/user the expected behavior
2315                         */
2316                        if (ec->parent && (!ec->parent->modal) && (e_client_focused_get() == ec->parent) &&
2317                            (ev->time - focus_time < PARENT_ACTIVATE_TIME))
2318                          {
2319                             E_Comp_X_Client_Data *cd;
2320 
2321                             cd = _e_comp_x_client_data_get(ec);
2322                             if (cd)
2323                               {
2324                                  cd->parent_activate_count++;
2325                                  if (cd->parent_activate_count >= PARENT_ACTIVATE_LIMIT)
2326                                    _e_comp_x_client_modal_setup(ec);
2327                               }
2328                          }
2329                        e_client_activate(ec, EINA_TRUE);
2330                     }
2331                }
2332              else
2333                evas_object_raise(ec->frame);
2334           }
2335      }
2336    else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE_DONE)
2337      {
2338         if ((ec->e.state.profile.use) &&
2339             (ec->e.state.profile.wait_for_done))
2340           {
2341              char *p = ecore_x_atom_name_get(ev->data.l[1]);
2342              if (!e_util_strcmp(ec->e.state.profile.wait, p))
2343                {
2344                   E_Desk *old_desk = ec->desk;
2345                   E_Desk *desk = ec->e.state.profile.wait_desk;
2346                   Eina_Bool was_focused = e_client_stack_focused_get(ec);
2347 
2348                   eina_stringshare_replace(&ec->e.state.profile.wait, NULL);
2349                   ec->e.state.profile.wait_for_done = 0;
2350                   if ((desk) && (desk != old_desk))
2351                     {
2352                        eina_stringshare_replace(&ec->e.state.profile.name,
2353                                                 desk->window_profile);
2354                        e_client_desk_set(ec, desk);
2355                        if (was_focused)
2356                          e_desk_last_focused_focus(old_desk);
2357                     }
2358                   e_client_desk_window_profile_wait_desk_set(ec, NULL);
2359                }
2360              free(p);
2361           }
2362      }
2363    else if (ev->message_type == ATM_NETWM_SHOW_WINDOW_MENU)
2364      {
2365        /*
2366          message_type = _NET_WM_SHOW_WINDOW_MENU
2367          window = window for which the menu should be shown
2368          format = 32
2369          data.l[0] = xinput2_device_id
2370          data.l[1] = root_x
2371          data.l[2] = root_y
2372          other data.l[] elements = 0
2373         */
2374 
2375         int x, y;
2376 
2377         x = ev->data.l[1];
2378         y = ev->data.l[2];
2379         e_int_client_menu_show(ec,
2380           e_comp_canvas_x_root_adjust(x),
2381           e_comp_canvas_y_root_adjust(y),
2382           0, 0);
2383      }
2384    else if (ev->message_type == ATM_NETWM_PERFORM_BUTTON_ACTION)
2385      {
2386         char emission[128];
2387        /*
2388          message_type = _NET_WM_PERFORM_BUTTON_ACTION
2389          window = window for which the action should be performed
2390          format = 32
2391          data.l[0] = xinput2_device_id
2392          data.l[1] = root_x
2393          data.l[2] = root_y
2394          data.l[3] = button
2395          data.l[4] = timestamp
2396         */
2397         if (e_dnd_active() || ec->iconic) return ECORE_CALLBACK_RENEW;
2398         switch (ev->data.l[3])
2399           {
2400            case 1:
2401            case 2:
2402            case 3:
2403              snprintf(emission, sizeof(emission), "mouse,down,%d", (int)ev->data.l[3]);
2404              e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(ec), emission, "e.event.titlebar");
2405              break;
2406            case 4:
2407              e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(ec), "mouse,wheel,?,-1", "e.event.titlebar");
2408              break;
2409            case 5:
2410              e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(ec), "mouse,wheel,?,1", "e.event.titlebar");
2411              break;
2412           }
2413      }
2414 #ifdef HAVE_WAYLAND
2415    else if (ev->message_type == WL_SURFACE_ID)
2416      {
2417         void *res;
2418         E_Client *wc = NULL;
2419 
2420         if (e_comp->comp_type != E_PIXMAP_TYPE_WL) return ECORE_CALLBACK_RENEW;
2421         res = wl_client_get_object(e_comp_wl->xwl_client, ev->data.l[0]);
2422         if (res)
2423           wc = wl_resource_get_user_data(res);
2424         if (wc)
2425           {
2426              if (wc->internal)
2427                {
2428                   e_object_del(E_OBJECT(wc));
2429                   e_object_del(E_OBJECT(ec));
2430                   /* this is an xwayland bug. somehow the wrong surface is being passed
2431                    * and it's an internal surface--internal surfaces are NEVER
2432                    * xwayland clients.
2433                    *
2434                    * ever.
2435                    */
2436                   return ECORE_CALLBACK_RENEW;
2437                }
2438              e_comp_x_xwayland_client_setup(ec, wc);
2439           }
2440         else
2441           {
2442              ec->comp_data->surface_id = ev->data.l[0];
2443              e_comp_wl_xwayland_client_queue(ec);
2444           }
2445      }
2446 #endif
2447    else
2448      {
2449         char *name;
2450 
2451         if (!eina_log_domain_level_check(e_log_dom, EINA_LOG_LEVEL_DBG)) return ECORE_CALLBACK_RENEW;
2452         name = ecore_x_atom_name_get(ev->message_type);
2453         DBG("missed client message '%s' for %u", name, ev->win);
2454         free(name);
2455      }
2456    return ECORE_CALLBACK_PASS_ON;
2457 }
2458 
2459 static Eina_Bool
_e_comp_x_state_request(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_State_Request * ev)2460 _e_comp_x_state_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_State_Request *ev)
2461 {
2462    int i;
2463    E_Client *ec;
2464    int max;
2465 
2466    ec = _e_comp_x_client_find_by_window(ev->win);
2467    if (!ec) return ECORE_CALLBACK_RENEW;
2468 
2469    max = (1 << ev->state[0]) | (1 << ev->state[1]);
2470    if ((max & (1 << ECORE_X_WINDOW_STATE_MAXIMIZED_VERT)) &&
2471        (max & (1 << ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ)))
2472      e_hints_window_state_update(ec, INT_MAX, ev->action);
2473    else
2474      {
2475         for (i = 0; i < 2; i++)
2476           e_hints_window_state_update(ec, ev->state[i], ev->action);
2477      }
2478 
2479    return ECORE_CALLBACK_RENEW;
2480 }
2481 
2482 static Eina_Bool
_e_comp_x_mapping_change(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Mapping_Change * ev EINA_UNUSED)2483 _e_comp_x_mapping_change(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Mapping_Change *ev EINA_UNUSED)
2484 {
2485    const Eina_List *l;
2486    E_Client *ec;
2487 
2488    if (_e_comp_x_mapping_change_disabled) return ECORE_CALLBACK_RENEW;
2489    e_comp_canvas_keys_ungrab();
2490    EINA_LIST_FOREACH(e_comp->clients, l, ec)
2491      {
2492         if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_X) continue;
2493         if ((!_e_comp_x_client_data_get(ec)->first_map) || (!_e_comp_x_client_data_get(ec)->reparented)) continue;
2494         if (ec->focused)
2495           {
2496              _e_comp_x_focus_setup(ec);
2497              _e_comp_x_focus_setdown(ec);
2498           }
2499         else
2500           {
2501              _e_comp_x_focus_setdown(ec);
2502              _e_comp_x_focus_setup(ec);
2503              e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, e_client_util_pwin_get(ec));
2504              e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, e_client_util_pwin_get(ec));
2505           }
2506      }
2507    e_comp_canvas_keys_grab();
2508    return ECORE_CALLBACK_PASS_ON;
2509 }
2510 
2511 static void
_e_comp_x_mouse_in_job(void * d EINA_UNUSED)2512 _e_comp_x_mouse_in_job(void *d EINA_UNUSED)
2513 {
2514    if (mouse_client)
2515      e_client_mouse_in(mouse_client, e_comp_canvas_x_root_adjust(mouse_in_coords.x), e_comp_canvas_y_root_adjust(mouse_in_coords.y));
2516    mouse_in_job = NULL;
2517 }
2518 
2519 static Eina_Bool
_e_comp_x_mouse_in_fix_check_timer_cb(void * data EINA_UNUSED)2520 _e_comp_x_mouse_in_fix_check_timer_cb(void *data EINA_UNUSED)
2521 {
2522    E_Client *ec = NULL, *cec;
2523    int x, y;
2524 
2525    mouse_in_fix_check_timer = NULL;
2526    if (e_grabinput_key_win_get() || e_grabinput_mouse_win_get())
2527      return EINA_FALSE;
2528    ecore_evas_pointer_xy_get(e_comp->ee, &x, &y);
2529    E_CLIENT_REVERSE_FOREACH(cec)
2530      {
2531         /* If a border was specified which should be excluded from the list
2532          * (because it will be closed shortly for example), skip */
2533         if ((!e_client_util_desk_visible(cec, e_desk_current_get(e_zone_current_get())))) continue;
2534         if (!evas_object_visible_get(cec->frame)) continue;
2535         if (!E_INSIDE(x, y, cec->x, cec->y, cec->w, cec->h))
2536           continue;
2537         /* If the layer is higher, the position of the window is higher
2538          * (always on top vs always below) */
2539         if (!ec || (cec->layer > ec->layer))
2540           ec = cec;
2541      }
2542    if (ec)
2543      {
2544         mouse_client = ec;
2545         if (mouse_in_job) ecore_job_del(mouse_in_job);
2546         mouse_in_job = ecore_job_add(_e_comp_x_mouse_in_job, NULL);
2547      }
2548    return EINA_FALSE;
2549 }
2550 
2551 static Eina_Bool
_e_comp_x_mouse_in(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Mouse_In * ev)2552 _e_comp_x_mouse_in(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Mouse_In *ev)
2553 {
2554    E_Client *ec;
2555 
2556    if (e_comp->comp_type != E_PIXMAP_TYPE_X) return ECORE_CALLBACK_RENEW;
2557    ec = _e_comp_x_client_find_by_window(ev->win);
2558    if (!ec) goto done;
2559    if (ev->mode == ECORE_X_EVENT_MODE_NORMAL)
2560      {
2561         if (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
2562           {
2563              if (ev->win != e_client_util_pwin_get(ec)) goto done;
2564              if (ev->event_win != e_client_util_win_get(ec)) goto done;
2565           }
2566         if (ev->detail == ECORE_X_EVENT_DETAIL_VIRTUAL)
2567           {
2568              if (ev->win != e_client_util_win_get(ec)) goto done;
2569              if (ev->event_win != e_client_util_pwin_get(ec)) goto done;
2570           }
2571         if (!evas_object_visible_get(ec->frame)) goto done;
2572      }
2573    if (_e_comp_x_client_data_get(ec)->deleted) goto done;
2574    mouse_client = ec;
2575    if (mouse_in_job) ecore_job_del(mouse_in_job);
2576    mouse_in_job = ecore_job_add(_e_comp_x_mouse_in_job, NULL);
2577    mouse_in_coords.x = ev->root.x;
2578    mouse_in_coords.y = ev->root.y;
2579 done:
2580    E_FREE_FUNC(mouse_in_fix_check_timer, ecore_timer_del);
2581    if ((!e_grabinput_mouse_win_get()) && (!e_grabinput_key_win_get()))
2582      mouse_in_fix_check_timer =
2583        ecore_timer_add(0.1, _e_comp_x_mouse_in_fix_check_timer_cb, NULL);
2584    return ECORE_CALLBACK_RENEW;
2585 }
2586 
2587 static Eina_Bool
_e_comp_x_mouse_out(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Mouse_In * ev)2588 _e_comp_x_mouse_out(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Mouse_In *ev)
2589 {
2590    E_Client *ec;
2591 
2592    if (e_comp->comp_type != E_PIXMAP_TYPE_X) return ECORE_CALLBACK_RENEW;
2593    if ((ev->mode == ECORE_X_EVENT_MODE_UNGRAB) &&
2594        (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
2595      return ECORE_CALLBACK_PASS_ON;
2596    if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
2597      return ECORE_CALLBACK_PASS_ON;
2598    if ((ev->mode == ECORE_X_EVENT_MODE_NORMAL) &&
2599        (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
2600      return ECORE_CALLBACK_PASS_ON;
2601    ec = _e_comp_x_client_find_by_window(ev->win);
2602    if (!ec) return ECORE_CALLBACK_RENEW;
2603    if (_e_comp_x_client_data_get(ec)->deleted) return ECORE_CALLBACK_RENEW;
2604    if (mouse_client == ec)
2605      {
2606         mouse_client = NULL;
2607         E_FREE_FUNC(mouse_in_job, ecore_job_del);
2608      }
2609    if (ec->mouse.in)
2610      e_client_mouse_out(ec, e_comp_canvas_x_root_adjust(ev->root.x), e_comp_canvas_y_root_adjust(ev->root.y));
2611    return ECORE_CALLBACK_RENEW;
2612 }
2613 
2614 static Eina_Bool
_e_comp_x_mouse_wheel(void * d EINA_UNUSED,int t EINA_UNUSED,Ecore_Event_Mouse_Wheel * ev)2615 _e_comp_x_mouse_wheel(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Wheel *ev)
2616 {
2617    E_Client *ec;
2618    E_Binding_Event_Wheel ev2;
2619 
2620    if (e_comp->comp_type != E_PIXMAP_TYPE_X) return ECORE_CALLBACK_RENEW;
2621    //if (action_input_win)
2622      //ec = action_border;
2623    //else
2624      {
2625         ec = _e_comp_x_client_find_by_window(ev->window);
2626         if ((!ec) && (ev->window != ev->event_window))
2627           ec = _e_comp_x_client_find_by_window(ev->event_window);
2628         if (!ec) return ECORE_CALLBACK_RENEW;
2629      }
2630    if (_e_comp_x_client_data_get(ec)->deleted) return ECORE_CALLBACK_RENEW;
2631    e_bindings_ecore_event_mouse_wheel_convert(ev, &ev2);
2632    e_client_mouse_wheel(ec, (Evas_Point*)&ev->root, &ev2);
2633    return ECORE_CALLBACK_RENEW;
2634 }
2635 
2636 
2637 static Eina_Bool
_e_comp_x_mouse_up(void * d EINA_UNUSED,int t EINA_UNUSED,Ecore_Event_Mouse_Button * ev)2638 _e_comp_x_mouse_up(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
2639 {
2640    E_Client *ec;
2641    E_Binding_Event_Mouse_Button ev2;
2642 
2643    if (e_comp->comp_type != E_PIXMAP_TYPE_X) return ECORE_CALLBACK_RENEW;
2644    //if (action_input_win)
2645      //ec = action_border;
2646    //else
2647      {
2648         ec = _e_comp_x_client_find_by_window(ev->window);
2649         if ((!ec) && (ev->window != ev->event_window))
2650           ec = _e_comp_x_client_find_by_window(ev->event_window);
2651         if (!ec)
2652           {
2653              if (e_client_comp_grabbed_get())
2654                ec = e_client_action_get();
2655              if (!ec) return ECORE_CALLBACK_RENEW;
2656           }
2657         if ((!ec) || e_client_util_ignored_get(ec)) return ECORE_CALLBACK_RENEW;
2658      }
2659    if (_e_comp_x_client_data_get(ec)->deleted) return ECORE_CALLBACK_RENEW;
2660    e_bindings_ecore_event_mouse_button_convert(ev, &ev2);
2661    e_client_mouse_up(ec, ev->buttons, (Evas_Point*)&ev->root, &ev2);
2662    return ECORE_CALLBACK_RENEW;
2663 }
2664 
2665 static Eina_Bool
_e_comp_x_mouse_down(void * d EINA_UNUSED,int t EINA_UNUSED,Ecore_Event_Mouse_Button * ev)2666 _e_comp_x_mouse_down(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
2667 {
2668    E_Client *ec;
2669    E_Binding_Event_Mouse_Button ev2;
2670 
2671    if (e_comp->comp_type != E_PIXMAP_TYPE_X) return ECORE_CALLBACK_RENEW;
2672    if (e_client_action_get()) return ECORE_CALLBACK_RENEW; //block extra mouse buttons during action
2673    //if (action_input_win)
2674      //ec = action_border;
2675    //else
2676      {
2677         ec = _e_comp_x_client_find_by_window(ev->window);
2678         if ((!ec) && (ev->window != ev->event_window))
2679           ec = _e_comp_x_client_find_by_window(ev->event_window);
2680         if ((!ec) || e_client_util_ignored_get(ec)) return ECORE_CALLBACK_RENEW;
2681      }
2682    if (_e_comp_x_client_data_get(ec)->deleted) return ECORE_CALLBACK_RENEW;
2683    e_bindings_ecore_event_mouse_button_convert(ev, &ev2);
2684    e_client_mouse_down(ec, ev->buttons, (Evas_Point*)&ev->root, &ev2);
2685    return ECORE_CALLBACK_RENEW;
2686 }
2687 
2688 static Eina_Bool
_e_comp_x_mouse_move(void * d EINA_UNUSED,int t EINA_UNUSED,Ecore_Event_Mouse_Move * ev)2689 _e_comp_x_mouse_move(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Move *ev)
2690 {
2691    E_Client *ec;
2692 
2693    if (e_comp->comp_type != E_PIXMAP_TYPE_X) return ECORE_CALLBACK_RENEW;
2694    ec = e_client_action_get();
2695    if (!ec)
2696      {
2697         ec = _e_comp_x_client_find_by_window(ev->window);
2698         if ((!ec) && (ev->window != ev->event_window))
2699           ec = _e_comp_x_client_find_by_window(ev->event_window);
2700         if ((!ec) || e_client_util_ignored_get(ec)) return ECORE_CALLBACK_RENEW;
2701         if ((!ec->mouse.in) && evas_object_visible_get(ec->frame) && (!ec->desk->animate_count))
2702           {
2703              E_Client *tec;
2704              Ecore_Window top = e_comp_top_window_at_xy_get(ev->root.x, ev->root.y);
2705              int x, y;
2706              if (top == e_comp->ee_win) return ECORE_CALLBACK_RENEW;
2707 
2708              x = e_comp_canvas_x_root_adjust(ev->root.x);
2709              y = e_comp_canvas_y_root_adjust(ev->root.y);
2710              for (tec = e_client_above_get(ec); tec; tec = e_client_above_get(tec))
2711                {
2712                   if (!evas_object_visible_get(tec->frame)) continue;
2713                   if (E_INSIDE(x, y, tec->x, tec->y, tec->w, tec->h)) return ECORE_CALLBACK_RENEW;
2714                }
2715              if (!mouse_in_job)
2716                e_client_mouse_in(ec, x, y);
2717           }
2718         return ECORE_CALLBACK_RENEW;
2719      }
2720    E_COMP_X_PIXMAP_CHECK ECORE_CALLBACK_RENEW;
2721    if (_e_comp_x_client_data_get(ec)->deleted || e_client_util_ignored_get(ec)) return ECORE_CALLBACK_RENEW;
2722    if (e_client_util_resizing_get(ec) && (e_comp->comp_type == E_PIXMAP_TYPE_X) &&
2723        ec->netwm.sync.request &&
2724        _e_comp_x_client_data_get(ec)->alarm
2725       )
2726      {
2727         if ((ecore_loop_time_get() - ec->netwm.sync.send_time) > 0.5)
2728           {
2729              if (ec->pending_resize)
2730                {
2731                   ec->changes.pos = 1;
2732                   ec->changes.size = 1;
2733                   EC_CHANGED(ec);
2734                   _e_comp_x_client_move_resize_send(ec);
2735                }
2736              E_FREE_LIST(ec->pending_resize, free);
2737 
2738              ec->netwm.sync.wait = 0;
2739              /* sync.wait is incremented when resize_handle sends
2740               * sync-request and decremented by sync-alarm cb. so
2741               * we resize here either on initial resize, timeout or
2742               * when no new resize-request was added by sync-alarm cb.
2743               */
2744           }
2745      }
2746    e_client_mouse_move(ec, (Evas_Point*)&ev->root);
2747    return ECORE_CALLBACK_RENEW;
2748 }
2749 
2750 static Eina_Bool
_e_comp_x_focus_out(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Focus_Out * ev)2751 _e_comp_x_focus_out(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Focus_Out *ev)
2752 {
2753    E_Client *ec;
2754 
2755    ec = _e_comp_x_client_find_by_window(ev->win);
2756    if (!ec) return ECORE_CALLBACK_RENEW;
2757 
2758    _e_comp_x_client_pri_norm(ec);
2759    if (ev->mode == ECORE_X_EVENT_MODE_NORMAL)
2760      {
2761         if (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
2762           return ECORE_CALLBACK_PASS_ON;
2763         else if (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
2764           return ECORE_CALLBACK_PASS_ON;
2765         else if (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
2766           return ECORE_CALLBACK_PASS_ON;
2767      }
2768    else if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
2769      {
2770         if (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
2771           return ECORE_CALLBACK_PASS_ON;
2772         else if (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
2773           return ECORE_CALLBACK_PASS_ON;
2774         else if (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
2775           return ECORE_CALLBACK_PASS_ON;
2776         else if (ev->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
2777           return ECORE_CALLBACK_PASS_ON;
2778         else if (ev->detail == ECORE_X_EVENT_DETAIL_VIRTUAL)
2779           return ECORE_CALLBACK_PASS_ON;
2780      }
2781    else if (ev->mode == ECORE_X_EVENT_MODE_UNGRAB)
2782      {
2783         /* for firefox/thunderbird (xul) menu walking */
2784         /* NB: why did i disable this before? */
2785         if (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
2786           return ECORE_CALLBACK_PASS_ON;
2787         else if (ev->detail == ECORE_X_EVENT_DETAIL_POINTER)
2788           return ECORE_CALLBACK_PASS_ON;
2789      }
2790    else if (ev->mode == ECORE_X_EVENT_MODE_WHILE_GRABBED)
2791      {
2792         if (ev->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
2793           return ECORE_CALLBACK_PASS_ON;
2794         else if (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
2795           return ECORE_CALLBACK_PASS_ON;
2796      }
2797    evas_object_focus_set(ec->frame, 0);
2798    return ECORE_CALLBACK_PASS_ON;
2799 }
2800 
2801 static Eina_Bool
_e_comp_x_client_property(void * d EINA_UNUSED,int t EINA_UNUSED,E_Event_Client_Property * ev)2802 _e_comp_x_client_property(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Client_Property *ev)
2803 {
2804    if ((ev->property & E_CLIENT_PROPERTY_ICON) && ev->ec->desktop)
2805      ecore_x_window_prop_string_set(e_client_util_win_get(ev->ec), E_ATOM_DESKTOP_FILE,
2806                                     ev->ec->desktop->orig_path);
2807    return ECORE_CALLBACK_RENEW;
2808 }
2809 
2810 static void
_e_comp_x_client_zone_geometry_set(E_Client * ec)2811 _e_comp_x_client_zone_geometry_set(E_Client *ec)
2812 {
2813    unsigned int zgeom[4];
2814 
2815    E_COMP_X_PIXMAP_CHECK;
2816    zgeom[0] = ec->zone->x;
2817    zgeom[1] = ec->zone->y;
2818    zgeom[2] = ec->zone->w;
2819    zgeom[3] = ec->zone->h;
2820    ecore_x_window_prop_card32_set(e_client_util_win_get(ec), E_ATOM_ZONE_GEOMETRY, zgeom, 4);
2821 }
2822 
2823 static Eina_Bool
_e_comp_x_client_zone_set(void * data EINA_UNUSED,int type EINA_UNUSED,E_Event_Client * ev)2824 _e_comp_x_client_zone_set(void *data EINA_UNUSED, int type EINA_UNUSED, E_Event_Client *ev)
2825 {
2826    E_Client *ec = ev->ec;
2827 
2828    if (e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_RENEW;
2829    E_COMP_X_PIXMAP_CHECK ECORE_CALLBACK_RENEW;
2830    ecore_x_window_prop_card32_set(e_client_util_win_get(ev->ec), E_ATOM_ZONE, &ev->ec->zone->num, 1);
2831    _e_comp_x_client_zone_geometry_set(ev->ec);
2832    return ECORE_CALLBACK_RENEW;
2833 }
2834 
2835 static Eina_Bool
_e_comp_x_sync_alarm(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Sync_Alarm * ev)2836 _e_comp_x_sync_alarm(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Sync_Alarm *ev)
2837 {
2838    unsigned int serial;
2839    E_Client *ec;
2840 //   Eina_Bool resize = EINA_FALSE;
2841 
2842    ec = _e_comp_x_client_find_by_alarm(ev->alarm);
2843    if ((!ec) || e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_RENEW;
2844 
2845    if (ec->netwm.sync.wait)
2846      ec->netwm.sync.wait--;
2847 
2848    if (ecore_x_sync_counter_query(_e_comp_x_client_data_get(ec)->sync_counter, &serial))
2849      {
2850         E_Client_Pending_Resize *pnd = NULL;
2851 
2852         /* skip pending for which we didn't get a reply */
2853         while (ec->pending_resize)
2854           {
2855              pnd = ec->pending_resize->data;
2856              ec->pending_resize = eina_list_remove(ec->pending_resize, pnd);
2857 
2858              if (serial == pnd->serial)
2859                break;
2860 
2861              E_FREE(pnd);
2862           }
2863 
2864         if (pnd)
2865           {
2866 // disable this as it just seems to cause mis-sizing and issues...
2867 //             resize = ((ec->w != pnd->w) || (ec->h != pnd->h));
2868 //             e_comp_object_frame_wh_adjust(ec->frame, pnd->w, pnd->h, &ec->w, &ec->h);
2869              E_FREE(pnd);
2870           }
2871      }
2872 
2873 // this too... as above
2874 //   if (resize)
2875 //     {
2876 //        evas_object_resize(ec->frame, ec->w, ec->h);
2877 //        if (ec->internal_elm_win)
2878 //          evas_object_resize(ec->internal_elm_win, ec->client.w, ec->client.h);
2879 //     }
2880 
2881    ec->netwm.sync.send_time = ecore_loop_time_get();
2882 // this too - as above
2883 //   if (resize)
2884 //     {
2885 //        ecore_x_pointer_xy_get(e_comp->root,
2886 //                               &ec->mouse.current.mx,
2887 //                               &ec->mouse.current.my);
2888 //        e_client_mouse_move(ec, &(Evas_Point){ec->mouse.current.mx, ec->mouse.current.my});
2889 //     }
2890    return ECORE_CALLBACK_RENEW;
2891 }
2892 
2893 static Eina_Bool
_e_comp_x_desktop_change(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Desktop_Change * ev)2894 _e_comp_x_desktop_change(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Desktop_Change *ev)
2895 {
2896    E_Client *ec;
2897 
2898    ec = _e_comp_x_client_find_by_window(ev->win);
2899    if (ec)
2900      {
2901         if (ev->desk == 0xffffffff)
2902           e_client_stick(ec);
2903         else if ((int)ev->desk < (ec->zone->desk_x_count * ec->zone->desk_y_count))
2904           {
2905              E_Desk *desk;
2906 
2907              desk = e_desk_at_pos_get(ec->zone, ev->desk);
2908              if (desk)
2909                e_client_desk_set(ec, desk);
2910           }
2911      }
2912    else
2913      ecore_x_netwm_desktop_set(ev->win, ev->desk);
2914    return ECORE_CALLBACK_RENEW;
2915 }
2916 
2917 static Eina_Bool
_e_comp_x_move_resize_request(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Move_Resize_Request * ev)2918 _e_comp_x_move_resize_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Move_Resize_Request *ev)
2919 {
2920    E_Client *ec;
2921 
2922    ec = _e_comp_x_client_find_by_window(ev->win);
2923    if (!ec) return ECORE_CALLBACK_RENEW;
2924 
2925    if ((ec->shaded) || (ec->shading) ||
2926        (ec->fullscreen) || (ec->moving) ||
2927        (ec->resize_mode != E_POINTER_RESIZE_NONE))
2928      return ECORE_CALLBACK_PASS_ON;
2929 
2930    if ((ev->button >= 1) && (ev->button <= 3))
2931      {
2932         ec->mouse.last_down[ev->button - 1].mx = ev->x;
2933         ec->mouse.last_down[ev->button - 1].my = ev->y;
2934         ec->mouse.last_down[ev->button - 1].x = ec->x;
2935         ec->mouse.last_down[ev->button - 1].y = ec->y;
2936         ec->mouse.last_down[ev->button - 1].w = ec->w;
2937         ec->mouse.last_down[ev->button - 1].h = ec->h;
2938      }
2939    else
2940      {
2941         ec->moveinfo.down.x = ec->x;
2942         ec->moveinfo.down.y = ec->y;
2943         ec->moveinfo.down.w = ec->w;
2944         ec->moveinfo.down.h = ec->h;
2945      }
2946    ec->mouse.current.mx = ev->x;
2947    ec->mouse.current.my = ev->y;
2948    ec->moveinfo.down.button = ev->button;
2949    ec->moveinfo.down.mx = ev->x;
2950    ec->moveinfo.down.my = ev->y;
2951 
2952    if (!ec->lock_user_stacking)
2953      evas_object_raise(ec->frame);
2954 
2955    if (ev->direction == E_POINTER_MOVE)
2956      {
2957         ec->cur_mouse_action = e_action_find("window_move");
2958         if (ec->cur_mouse_action)
2959           {
2960              if ((!ec->cur_mouse_action->func.end_mouse) &&
2961                  (!ec->cur_mouse_action->func.end))
2962                ec->cur_mouse_action = NULL;
2963              if (ec->cur_mouse_action)
2964                {
2965                   e_object_ref(E_OBJECT(ec->cur_mouse_action));
2966                   ec->cur_mouse_action->func.go(E_OBJECT(ec), NULL);
2967                }
2968           }
2969         return ECORE_CALLBACK_PASS_ON;
2970      }
2971 
2972    ec->cur_mouse_action = e_action_find("window_resize");
2973    if (ec->cur_mouse_action)
2974      {
2975         if ((!ec->cur_mouse_action->func.end_mouse) &&
2976             (!ec->cur_mouse_action->func.end))
2977           ec->cur_mouse_action = NULL;
2978      }
2979    if (!ec->cur_mouse_action) return ECORE_CALLBACK_RENEW;
2980    e_object_ref(E_OBJECT(ec->cur_mouse_action));
2981    ec->cur_mouse_action->func.go(E_OBJECT(ec), NULL);
2982 
2983    if (ev->direction != E_POINTER_RESIZE_NONE)
2984      {
2985         e_pointer_mode_pop(ec, ec->resize_mode);
2986         ec->resize_mode = ev->direction;
2987         e_pointer_mode_push(ec, ec->resize_mode);
2988      }
2989    switch (ev->direction)
2990      {
2991       case E_POINTER_RESIZE_TL:
2992         GRAV_SET(ec, ECORE_X_GRAVITY_SE);
2993         break;
2994 
2995       case E_POINTER_RESIZE_T:
2996         GRAV_SET(ec, ECORE_X_GRAVITY_S);
2997         break;
2998 
2999       case E_POINTER_RESIZE_TR:
3000         GRAV_SET(ec, ECORE_X_GRAVITY_SW);
3001         break;
3002 
3003       case E_POINTER_RESIZE_R:
3004         GRAV_SET(ec, ECORE_X_GRAVITY_W);
3005         break;
3006 
3007       case E_POINTER_RESIZE_BR:
3008         GRAV_SET(ec, ECORE_X_GRAVITY_NW);
3009         break;
3010 
3011       case E_POINTER_RESIZE_B:
3012         GRAV_SET(ec, ECORE_X_GRAVITY_N);
3013         break;
3014 
3015       case E_POINTER_RESIZE_BL:
3016         GRAV_SET(ec, ECORE_X_GRAVITY_NE);
3017         break;
3018 
3019       case E_POINTER_RESIZE_L:
3020         GRAV_SET(ec, ECORE_X_GRAVITY_E);
3021         break;
3022 
3023       default:
3024         return ECORE_CALLBACK_PASS_ON;
3025      }
3026 
3027    return ECORE_CALLBACK_RENEW;
3028 }
3029 
3030 static Eina_Bool
_e_comp_x_focus_timer_cb(void * d EINA_UNUSED)3031 _e_comp_x_focus_timer_cb(void *d EINA_UNUSED)
3032 {
3033    E_Client *focused;
3034 
3035    /* if mouse-based focus policy clients exist for [focused] and [mouse_client],
3036     * [mouse_client] should have focus here.
3037     * race conditions in x11 focus setting can result in a scenario such that:
3038     * -> set focus on A
3039     * -> set focus on B
3040     * -> receive focus event on A
3041     * -> re-set focus on A
3042     * -> receive focus event on B
3043     * -> receive focus event on A
3044     * ...
3045     * where the end state is that the cursor is over a client which does not have focus.
3046     * this timer is triggered only when such eventing occurs in order to adjust the focused
3047     * client as necessary
3048     */
3049    focused = e_client_focused_get();
3050    if (mouse_client && focused && (!e_client_focus_policy_click(focused)) && (mouse_client != focused))
3051      {
3052         int x, y;
3053 
3054         ecore_evas_pointer_xy_get(e_comp->ee, &x, &y);
3055         if (E_INSIDE(x, y, mouse_client->x, mouse_client->y, mouse_client->w, mouse_client->h))
3056           {
3057              if (!_e_comp_x_client_data_get(mouse_client)->deleted)
3058                e_client_mouse_in(mouse_client, x, y);
3059           }
3060      }
3061    focus_timer = NULL;
3062    return EINA_FALSE;
3063 }
3064 
3065 static void
_e_comp_x_focus_timer(void)3066 _e_comp_x_focus_timer(void)
3067 {
3068    if (focus_timer)
3069      ecore_timer_loop_reset(focus_timer);
3070    else /* focus has changed twice in .002 seconds; .01 seconds should be more than enough delay */
3071      focus_timer = ecore_timer_loop_add(0.01, _e_comp_x_focus_timer_cb, NULL);
3072 }
3073 
3074 static Eina_Bool
_e_comp_x_focus_in(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Focus_In * ev)3075 _e_comp_x_focus_in(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Focus_In *ev)
3076 {
3077    E_Client *ec, *focused;
3078 
3079    ec = _e_comp_x_client_find_by_window(ev->win);
3080 
3081    if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
3082      {
3083         focused = e_client_focused_get();
3084         if (ec && focused)
3085           {
3086              if ((!ec->override) && (ec != focused))
3087                {
3088                   ecore_x_window_focus(e_client_util_win_get(focused));
3089                   ecore_x_icccm_take_focus_send(e_client_util_win_get(focused), ecore_x_current_time_get());
3090                }
3091           }
3092         else
3093           ecore_x_window_focus(e_comp->root);
3094         return ECORE_CALLBACK_RENEW;
3095      }
3096    if (!ec)
3097      {
3098         if ((ev->win == e_comp->ee_win) && (ev->time >= focus_canvas_time) && (!focus_time))
3099           {
3100              focused = e_client_focused_get();
3101              if (focused)
3102                evas_object_focus_set(focused->frame, 0);
3103              focus_canvas_time = 0;
3104           }
3105         return ECORE_CALLBACK_RENEW;
3106      }
3107 
3108    /* block refocus attempts on iconic clients
3109     * these result from iconifying a client during a grab */
3110    if (ec->iconic) return ECORE_CALLBACK_RENEW;
3111 
3112    focused = e_client_focused_get();
3113 
3114    _e_comp_x_client_pri_raise(ec);
3115    if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
3116      {
3117         if (ev->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
3118      }
3119    else if (ev->mode == ECORE_X_EVENT_MODE_UNGRAB)
3120      {
3121         /* this seems to break winlist...
3122         if (ev->detail == ECORE_X_EVENT_DETAIL_POINTER)
3123         */
3124 
3125         /* we're getting a non-linear focus re-set on a visible
3126          * window on current desk when no other client is focused;
3127          * this is probably when we're trying to reapply focus after
3128          * unfocusing some comp canvas widget
3129          */
3130         if ((ev->detail != ECORE_X_EVENT_DETAIL_NON_LINEAR) ||
3131             focused ||
3132             (!e_client_util_desk_visible(ec, e_desk_current_get(ec->zone))))
3133         return ECORE_CALLBACK_PASS_ON;
3134      }
3135 
3136    /* ignore focus in from !take_focus windows, we just gave it em */
3137    /* if (!ec->icccm.take_focus)
3138     *   return ECORE_CALLBACK_PASS_ON; */
3139 
3140    /* should be equal, maybe some clients don't reply with the proper timestamp ? */
3141    if (ev->time >= focus_time)
3142      evas_object_focus_set(ec->frame, 1);
3143    /* handle case of someone trying to benchmark focus handling */
3144    if ((!e_client_focus_policy_click(ec)) && (focused && (!e_client_focus_policy_click(focused))) &&
3145        (ev->time - focus_time <= 2))
3146      _e_comp_x_focus_timer();
3147    return ECORE_CALLBACK_PASS_ON;
3148 }
3149 
3150 static Eina_Bool
_e_comp_x_shape(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Shape * ev)3151 _e_comp_x_shape(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Shape *ev)
3152 {
3153    E_Client *ec;
3154    Eina_Bool pshaped;
3155    //const char *txt[] =
3156    //{
3157       //[ECORE_X_SHAPE_BOUNDING] = "BOUNDING",
3158       //[ECORE_X_SHAPE_INPUT] = "INPUT",
3159       //[ECORE_X_SHAPE_CLIP] = "CLIP",
3160    //};
3161 
3162    ec = _e_comp_x_client_find_by_window(ev->win);
3163    if (!ec) return ECORE_CALLBACK_RENEW;
3164    pshaped = ec->shaped;
3165    //INF("%p(%s): %d,%d %dx%d || %d", ec, txt[ev->type], ev->x, ev->y, ev->w, ev->h, ev->shaped);
3166    if (ev->win == e_client_util_win_get(ec))
3167      {
3168         if (ev->type == ECORE_X_SHAPE_INPUT)
3169           {
3170              ec->changes.shape_input = 1;
3171              ec->need_shape_merge = 1;
3172           }
3173         else
3174           {
3175              if ((_e_comp_x_client_data_get(ec)->shape.x != ev->x) ||
3176                  (_e_comp_x_client_data_get(ec)->shape.y != ev->y) ||
3177                  (_e_comp_x_client_data_get(ec)->shape.w != ev->w) ||
3178                  (_e_comp_x_client_data_get(ec)->shape.h != ev->h))
3179                {
3180                   /* bounding box changed, need export for rendering */
3181                   EINA_RECTANGLE_SET(&_e_comp_x_client_data_get(ec)->shape, ev->x, ev->y, ev->w, ev->h);
3182                   ec->need_shape_export = !ec->override;
3183                }
3184              ec->changes.shape = 1;
3185           }
3186      }
3187    else if (ec->shaped) //shape change on parent window only valid if window is known to be shaped
3188      ec->need_shape_export = 1;
3189    if (ec->changes.shape)
3190      {
3191         if ((ev->type == ECORE_X_SHAPE_BOUNDING) && (ec->shaped || (pshaped != ec->shaped)))
3192           {
3193              if (ec->shape_rects || (!ec->shaped))
3194                e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
3195           }
3196      }
3197    EC_CHANGED(ec);
3198    return ECORE_CALLBACK_PASS_ON;
3199 }
3200 
3201 static Eina_Bool
_e_comp_x_damage(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Damage * ev)3202 _e_comp_x_damage(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Damage *ev)
3203 {
3204    E_Client *ec;
3205    Ecore_X_Rectangle *rects = NULL;
3206    int n = 0;
3207    Eina_Bool skip;
3208 
3209    ec = _e_comp_x_client_find_by_damage(ev->damage);
3210    if ((!ec) || e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_PASS_ON;
3211    skip = ec->shape_rects_num > 50;
3212    if (_e_comp_x_client_data_get(ec)->damage)
3213      {
3214         Ecore_X_Region parts;
3215         Ecore_X_Rectangle bounds;
3216 
3217         parts = ecore_x_region_new(NULL, 0);
3218         ecore_x_damage_subtract(_e_comp_x_client_data_get(ec)->damage, 0, parts);
3219         if (!skip)
3220           rects = ecore_x_region_fetch(parts, &n, &bounds);
3221         ecore_x_region_free(parts);
3222      }
3223    //WRN("DAMAGE %p: %dx%d", ec, ev->area.width, ev->area.height);
3224 
3225    if (e_comp->nocomp)
3226      e_pixmap_dirty(ec->pixmap);
3227    else if (skip)
3228      e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
3229    else
3230      {
3231         int i;
3232 
3233         for (i = 0; i < n; i++)
3234           e_comp_object_damage(ec->frame, rects[i].x, rects[i].y, rects[i].width, rects[i].height);
3235      }
3236    free(rects);
3237    if ((!ec->re_manage) && (!ec->override) && (!_e_comp_x_client_data_get(ec)->first_damage))
3238      e_comp_object_render_update_del(ec->frame);
3239    else
3240      E_FREE_FUNC(_e_comp_x_client_data_get(ec)->first_draw_delay, ecore_timer_del);
3241    _e_comp_x_client_data_get(ec)->first_damage = 1;
3242    return ECORE_CALLBACK_RENEW;
3243 }
3244 
3245 static Eina_Bool
_e_comp_x_damage_win(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Damage * ev)3246 _e_comp_x_damage_win(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Damage *ev)
3247 {
3248    if (e_comp_find_by_window(ev->win)) e_comp_render_queue();
3249    return ECORE_CALLBACK_PASS_ON;
3250 }
3251 
3252 static Eina_Bool
_e_comp_x_grab_replay(void * data EINA_UNUSED,int type,void * event)3253 _e_comp_x_grab_replay(void *data EINA_UNUSED, int type, void *event)
3254 {
3255    Ecore_Event_Mouse_Button *ev = event;
3256    E_Binding_Event_Mouse_Button ev2;
3257    E_Client *ec;
3258 
3259    if (type != ECORE_EVENT_MOUSE_BUTTON_DOWN) return ECORE_CALLBACK_DONE;
3260    if ((!e_config->pass_click_on) &&
3261        (!e_config->always_click_to_raise) && // this works even if not on click-to-focus
3262        (!e_config->always_click_to_focus) // this works even if not on click-to-focus
3263        )
3264      return ECORE_CALLBACK_DONE;
3265    ec = _e_comp_x_client_find_by_window(ev->event_window);
3266    if (!ec) return ECORE_CALLBACK_DONE;
3267    if (ec->cur_mouse_action) return ECORE_CALLBACK_DONE;
3268    if (ev->event_window != e_client_util_win_get(ec)) return ECORE_CALLBACK_DONE;
3269    e_bindings_ecore_event_mouse_button_convert(ev, &ev2);
3270    return !e_bindings_mouse_button_find(E_BINDING_CONTEXT_WINDOW,
3271                                         &ev2, NULL);
3272 }
3273 
3274 static void
_e_comp_x_hook_client_eval_end(void * d EINA_UNUSED,E_Client * ec)3275 _e_comp_x_hook_client_eval_end(void *d EINA_UNUSED, E_Client *ec)
3276 {
3277    E_COMP_X_PIXMAP_CHECK;
3278    if (e_comp_x->restack && (!e_comp->new_clients))
3279      {
3280         e_hints_client_stacking_set();
3281         e_comp_x->restack = 0;
3282      }
3283 }
3284 
3285 static Eina_Bool
_e_comp_x_client_shape_rects_check(E_Client * ec,Ecore_X_Rectangle * rects,int num)3286 _e_comp_x_client_shape_rects_check(E_Client *ec, Ecore_X_Rectangle *rects, int num)
3287 {
3288    Eina_Bool changed = 1;
3289    Ecore_X_Rectangle *orects;
3290 
3291    if (((unsigned int)num == ec->shape_rects_num) && (ec->shape_rects))
3292      {
3293         int i;
3294 
3295         orects = (Ecore_X_Rectangle*)ec->shape_rects;
3296         changed = 0;
3297         for (i = 0; i < num; i++)
3298           {
3299              E_RECTS_CLIP_TO_RECT(rects[i].x, rects[i].y,
3300                rects[i].width, rects[i].height, 0, 0, ec->client.w, ec->client.h);
3301 
3302              if ((orects[i].x != rects[i].x) ||
3303                  (orects[i].y != rects[i].y) ||
3304                  (orects[i].width != rects[i].width) ||
3305                  (orects[i].height != rects[i].height))
3306                {
3307                   changed = 1;
3308                   break;
3309                }
3310           }
3311      }
3312    if ((changed) && (rects))
3313      {
3314         E_FREE(ec->shape_rects);
3315         ec->shape_rects = (Eina_Rectangle*)rects;
3316         ec->shape_rects_num = num;
3317         ec->shape_changed = 1;
3318         e_comp_shape_queue();
3319      }
3320    else
3321      free(rects);
3322    return changed;
3323 }
3324 
3325 static void
_e_comp_x_hook_client_post_new_client(void * d EINA_UNUSED,E_Client * ec)3326 _e_comp_x_hook_client_post_new_client(void *d EINA_UNUSED, E_Client *ec)
3327 {
3328    E_COMP_X_PIXMAP_CHECK;
3329    if (ec->changes.reset_gravity)
3330      {
3331         GRAV_SET(ec, ECORE_X_GRAVITY_NW);
3332      }
3333 
3334    if (ec->need_shape_merge)
3335      {
3336         _e_comp_x_client_shape_input_rectangle_set(ec);
3337         if ((!ec->shaped) && _e_comp_x_client_data_get(ec)->reparented)
3338           ecore_x_window_shape_mask_set(e_client_util_pwin_get(ec), 0);
3339         ec->need_shape_merge = 0;
3340      }
3341 
3342    if (ec->changes.internal_state)
3343      {
3344         Ecore_X_Atom state[1];
3345         int num = 0;
3346 
3347         if (e_win_centered_get(ec->internal_elm_win))
3348           state[num++] = E_ATOM_WINDOW_STATE_CENTERED;
3349 
3350         if (num)
3351           ecore_x_window_prop_card32_set(elm_win_window_id_get(ec->internal_elm_win), E_ATOM_WINDOW_STATE, state, num);
3352         else
3353           ecore_x_window_prop_property_del(elm_win_window_id_get(ec->internal_elm_win), E_ATOM_WINDOW_STATE);
3354         ec->changes.internal_state = 0;
3355      }
3356 
3357    if (ec->need_shape_export)
3358      {
3359         Ecore_X_Rectangle *rects;
3360         int num;
3361 
3362         rects = ecore_x_window_shape_rectangles_get(e_client_util_win_get(ec), &num);
3363         if (rects)
3364           _e_comp_x_client_shape_rects_check(ec, rects, num);
3365         else
3366           {
3367              E_FREE(ec->shape_rects);
3368              ec->shape_rects_num = 0;
3369           }
3370         ec->need_shape_export = 0;
3371      }
3372 }
3373 
3374 static void
_e_comp_x_hook_client_pre_frame_assign(void * d EINA_UNUSED,E_Client * ec)3375 _e_comp_x_hook_client_pre_frame_assign(void *d EINA_UNUSED, E_Client *ec)
3376 {
3377    Ecore_X_Window win, pwin;
3378    int w, h;
3379    E_Pixmap *ep;
3380    E_Comp_X_Client_Data *cd;
3381 
3382    E_COMP_X_PIXMAP_CHECK;
3383    ep = e_comp_x_client_pixmap_get(ec);
3384    win = e_client_util_win_get(ec);
3385    cd = _e_comp_x_client_data_get(ec);
3386    if (!cd->need_reparent) return;
3387    w = MAX(ec->client.w, 1);
3388    h = MAX(ec->client.h, 1);
3389    /* match ec parent argbness */
3390    if (ec->argb)
3391      pwin = ecore_x_window_manager_argb_new(e_comp->root, ec->client.x, ec->client.y, w, h);
3392    else
3393      {
3394         pwin = ecore_x_window_override_new(e_comp->root, ec->client.x, ec->client.y, w, h);
3395         ecore_x_window_shape_events_select(pwin, !ec->internal); //let's just agree never to do this with our own windows...
3396      }
3397 
3398    if (ec->client.w && ec->client.h)
3399      /* force a resize here (no-op most of the time)
3400       * prevents mismatch between remembered window size and current size
3401       */
3402      ecore_x_window_resize(win, ec->client.w, ec->client.h);
3403    ecore_x_window_container_manage(pwin);
3404    if (!ec->internal) ecore_x_window_client_manage(win);
3405    ecore_x_window_configure(pwin,
3406                             ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
3407                             ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
3408                             0, 0, 0, 0, 0,
3409                             win, ECORE_X_WINDOW_STACK_ABOVE);
3410    ecore_x_event_mask_set(pwin, ECORE_X_EVENT_MASK_KEY_DOWN | ECORE_X_EVENT_MASK_KEY_UP |
3411                                 ECORE_X_EVENT_MASK_MOUSE_MOVE | ECORE_X_EVENT_MASK_MOUSE_DOWN |
3412                                 ECORE_X_EVENT_MASK_MOUSE_UP |
3413                                 ECORE_X_EVENT_MASK_MOUSE_IN | ECORE_X_EVENT_MASK_MOUSE_OUT);
3414    ecore_x_window_border_width_set(win, 0);
3415    ec->border_size = 0;
3416 
3417    if (ec->e.state.video)
3418      {
3419         ecore_x_window_lower(pwin);
3420         ecore_x_composite_window_events_disable(pwin);
3421         ecore_x_window_ignore_set(pwin, EINA_TRUE);
3422      }
3423    if (!ec->internal)
3424      ecore_x_window_save_set_add(win);
3425    ecore_x_window_reparent(win, pwin, 0, 0);
3426    e_pixmap_alias(ep, E_PIXMAP_TYPE_X, pwin);
3427 
3428    {
3429       unsigned int managed = 1;
3430       ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &managed, 1);
3431    }
3432    e_pixmap_parent_window_set(ep, pwin);
3433    ec->border.changed = 1;
3434    if (!ec->shaped)
3435      ecore_x_window_shape_mask_set(pwin, 0);
3436    if (ec->shaped_input)
3437      ecore_x_window_shape_input_rectangles_set(pwin, (Ecore_X_Rectangle*)ec->shape_input_rects, ec->shape_input_rects_num);
3438    ec->changes.shape = 1;
3439    ec->changes.shape_input = 1;
3440    if (ec->internal_elm_win)
3441      {
3442         ecore_x_window_gravity_set(win, ECORE_X_GRAVITY_NW);
3443         ec->changes.reset_gravity = 1;
3444      }
3445    EC_CHANGED(ec);
3446 
3447    eina_hash_add(clients_win_hash, &pwin, ec);
3448 
3449    if (ec->visible)
3450      {
3451         if (cd->set_win_type && ec->internal_elm_win)
3452           {
3453              if (ec->dialog)
3454                ecore_x_netwm_window_type_set(win, ECORE_X_WINDOW_TYPE_DIALOG);
3455              else
3456                ecore_x_netwm_window_type_set(win, ECORE_X_WINDOW_TYPE_NORMAL);
3457              cd->set_win_type = 0;
3458           }
3459      }
3460    ecore_x_window_show(win);
3461    if (ec->icccm.state != ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
3462      ecore_x_window_show(pwin);
3463 
3464    _e_comp_x_focus_init(ec);
3465    e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, pwin);
3466    e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, pwin);
3467    _e_comp_x_client_evas_init(ec);
3468    if (ec->netwm.ping && (!ec->ping_poller))
3469      e_client_ping(ec);
3470    if (ec->visible && (ec->icccm.state != ECORE_X_WINDOW_STATE_HINT_WITHDRAWN))
3471      evas_object_show(ec->frame);
3472    cd->need_reparent = 0;
3473    ec->redirected = 1;
3474    if (cd->change_icon)
3475      {
3476         ec->changes.icon = 1;
3477         EC_CHANGED(ec);
3478      }
3479    cd->change_icon = 0;
3480    cd->reparented = 1;
3481    _e_comp_x_evas_comp_hidden_cb(ec, NULL, NULL);
3482 }
3483 
3484 static void
_e_comp_x_hook_client_fetch(void * d EINA_UNUSED,E_Client * ec)3485 _e_comp_x_hook_client_fetch(void *d EINA_UNUSED, E_Client *ec)
3486 {
3487    Ecore_X_Window win, pwin;
3488    int rem_change = 0;
3489    Eina_Bool need_desk_set = EINA_FALSE;
3490    E_Comp_X_Client_Data *cd;
3491 
3492    E_COMP_X_PIXMAP_CHECK;
3493    win = e_client_util_win_get(ec);
3494    pwin = e_client_util_pwin_get(ec);
3495    cd = _e_comp_x_client_data_get(ec);
3496    if (ec->changes.visible)
3497      _e_comp_x_client_shape_input_rectangle_set(ec);
3498    /* fetch any info queued to be fetched */
3499    if (ec->changes.prop || ec->netwm.fetch.state)
3500      {
3501         e_hints_window_state_get(ec);
3502         ec->netwm.fetch.state = 0;
3503         rem_change = 1;
3504      }
3505    if (ec->icccm.fetch.client_leader)
3506      {
3507         /* TODO: What do to if the client leader isn't mapped yet? */
3508         E_Client *ec_leader = NULL;
3509 
3510         ec->icccm.client_leader = ecore_x_icccm_client_leader_get(win);
3511         if (ec->icccm.client_leader)
3512           ec_leader = _e_comp_x_client_find_by_window(ec->icccm.client_leader);
3513         if (ec->leader)
3514           {
3515              if (ec->leader != ec_leader)
3516                {
3517                   ec->leader->group = eina_list_remove(ec->leader->group, ec);
3518                   if (ec->leader->modal == ec) ec->leader->modal = NULL;
3519                   ec->leader = NULL;
3520                }
3521              else
3522                ec_leader = NULL;
3523           }
3524         /* If this client is the leader of the group, don't register itself */
3525         if ((ec_leader) && (ec_leader != ec))
3526           {
3527              ec_leader->group = eina_list_append(ec_leader->group, ec);
3528              ec->leader = ec_leader;
3529              /* Only set the window modal to the leader it there is no parent */
3530              if ((ec->netwm.state.modal) &&
3531                  ((!ec->parent) || (ec->parent->modal != ec)))
3532                {
3533                   ec->leader->modal = ec;
3534                   if (ec->leader->focused)
3535                     evas_object_focus_set(ec->frame, 1);
3536                   else
3537                     {
3538                        Eina_List *l;
3539                        E_Client *child;
3540 
3541                        EINA_LIST_FOREACH(ec->leader->group, l, child)
3542                          {
3543                             if ((child != ec) && (child->focused))
3544                               evas_object_focus_set(ec->frame, 1);
3545                          }
3546                     }
3547                }
3548           }
3549         ec->icccm.fetch.client_leader = 0;
3550         rem_change = 1;
3551      }
3552    if (ec->icccm.fetch.title)
3553      {
3554         char *title = ecore_x_icccm_title_get(win);
3555         eina_stringshare_replace(&ec->icccm.title, title);
3556         free(title);
3557 
3558         e_comp_object_frame_title_set(ec->frame, ec->icccm.title);
3559 
3560         ec->icccm.fetch.title = 0;
3561         rem_change = 1;
3562      }
3563    if (ec->netwm.fetch.name)
3564      {
3565         char *name;
3566         ecore_x_netwm_name_get(win, &name);
3567         eina_stringshare_replace(&ec->netwm.name, name);
3568         free(name);
3569 
3570         ec->hacks.iconic_shading =
3571           ((ec->netwm.icon_name == ec->netwm.name) &&
3572            (!e_util_strcmp(ec->netwm.name, "QEMU")));
3573 
3574         e_comp_object_frame_title_set(ec->frame, ec->netwm.name);
3575 
3576         ec->netwm.fetch.name = 0;
3577         rem_change = 1;
3578      }
3579 
3580    if (ec->icccm.fetch.name_class)
3581      {
3582         const char *pname, *pclass;
3583         char *nname, *nclass;
3584 
3585         ecore_x_icccm_name_class_get(win, &nname, &nclass);
3586         pname = ec->icccm.name;
3587         pclass = ec->icccm.class;
3588         ec->icccm.name = eina_stringshare_add(nname);
3589         ec->icccm.class = eina_stringshare_add(nclass);
3590         ec->hacks.mapping_change =
3591           ((!e_util_strcasecmp(ec->icccm.class, "vmplayer")) ||
3592            (!e_util_strcasecmp(ec->icccm.class, "vmware")));
3593         if (ec->hacks.mapping_change)
3594           _e_comp_x_mapping_change_disabled++;
3595         _e_comp_x_mapping_change_disabled = MIN(_e_comp_x_mapping_change_disabled, 0);
3596         free(nname);
3597         free(nclass);
3598 
3599         if (!((ec->icccm.name == pname) &&
3600               (ec->icccm.class == pclass)))
3601           {
3602              ec->changes.icon = 1;
3603              rem_change = 1;
3604           }
3605 
3606         eina_stringshare_del(pname);
3607         eina_stringshare_del(pclass);
3608         ec->icccm.fetch.name_class = 0;
3609      }
3610    if (ec->changes.prop || ec->e.fetch.state)
3611      {
3612         e_hints_window_e_state_get(ec);
3613         ec->e.fetch.state = 0;
3614         rem_change = 1;
3615      }
3616    if (ec->e.fetch.stack)
3617      {
3618         cd->stack = ecore_x_e_stack_type_get(win);
3619         ec->e.state.stack = !!cd->stack;
3620         ec->e.fetch.stack = 0;
3621      }
3622    if (ec->e.fetch.profile)
3623      {
3624         const char **list = NULL;
3625         int n, i, res;
3626         unsigned int use;
3627 
3628         ec->e.state.profile.use = 0;
3629 
3630         if (ec->e.state.profile.name)
3631           {
3632              eina_stringshare_del(ec->e.state.profile.name);
3633              ec->e.state.profile.name = NULL;
3634           }
3635 
3636         if (ec->e.state.profile.available_list)
3637           {
3638              for (i = 0; i < ec->e.state.profile.num; i++)
3639                {
3640                   if (ec->e.state.profile.available_list[i])
3641                     {
3642                        eina_stringshare_del(ec->e.state.profile.available_list[i]);
3643                        ec->e.state.profile.available_list[i] = NULL;
3644                     }
3645                }
3646              E_FREE(ec->e.state.profile.available_list);
3647              ec->e.state.profile.available_list = NULL;
3648           }
3649         ec->e.state.profile.num = 0;
3650 
3651         res = ecore_x_window_prop_card32_get(win,
3652                                              ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED,
3653                                              &use,
3654                                              1);
3655         if ((res == 1) && (use == 1))
3656           {
3657              Ecore_X_Atom val;
3658              res = ecore_x_window_prop_atom_get(win,
3659                                                 ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE,
3660                                                 &val, 1);
3661              if (res == 1)
3662                {
3663                   char *name = ecore_x_atom_name_get(val);
3664                   if (name)
3665                     {
3666                        ec->e.state.profile.set = eina_stringshare_add(name);
3667                        free(name);
3668                     }
3669                }
3670 
3671              if (ecore_x_e_window_available_profiles_get(win, &list, &n))
3672                {
3673                   ec->e.state.profile.available_list = E_NEW(const char *, n);
3674                   for (i = 0; i < n; i++)
3675                     ec->e.state.profile.available_list[i] = eina_stringshare_add(list[i]);
3676                   ec->e.state.profile.num = n;
3677                }
3678              need_desk_set = EINA_TRUE;
3679              ec->e.state.profile.use = 1;
3680              free(list);
3681           }
3682 
3683         ec->e.fetch.profile = 0;
3684      }
3685    if (ec->changes.prop || ec->netwm.fetch.type)
3686      {
3687         unsigned int type = ec->netwm.type;
3688         e_hints_window_type_get(ec);
3689         if (((!ec->lock_border) || (!ec->border.name) || (type != ec->netwm.type)) && (cd->reparented || ec->internal))
3690           {
3691              ec->border.changed = 1;
3692              EC_CHANGED(ec);
3693           }
3694 
3695         if ((ec->netwm.type == E_WINDOW_TYPE_DOCK) || ec->tooltip)
3696           {
3697              if (!ec->netwm.state.skip_pager)
3698                {
3699                   ec->netwm.state.skip_pager = 1;
3700                   ec->netwm.update.state = 1;
3701                }
3702              if (!ec->netwm.state.skip_taskbar)
3703                {
3704                   ec->netwm.state.skip_taskbar = 1;
3705                   ec->netwm.update.state = 1;
3706                }
3707           }
3708         else if (ec->netwm.type == E_WINDOW_TYPE_DESKTOP)
3709           {
3710              ec->focus_policy_override = E_FOCUS_CLICK;
3711              _e_comp_x_focus_setdown(ec);
3712              _e_comp_x_focus_setup(ec);
3713              e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, pwin);
3714              e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, pwin);
3715              if (!ec->netwm.state.skip_pager)
3716                {
3717                   ec->netwm.state.skip_pager = 1;
3718                   ec->netwm.update.state = 1;
3719                }
3720              if (!ec->netwm.state.skip_taskbar)
3721                {
3722                   ec->netwm.state.skip_taskbar = 1;
3723                   ec->netwm.update.state = 1;
3724                }
3725              if (!e_client_util_ignored_get(ec))
3726                ec->border.changed = ec->borderless = 1;
3727           }
3728         if (ec->tooltip)
3729           {
3730              ec->icccm.accepts_focus = 0;
3731              eina_stringshare_replace(&ec->bordername, "borderless");
3732           }
3733         {
3734            E_Event_Client_Property *ev;
3735 
3736            ev = E_NEW(E_Event_Client_Property, 1);
3737            ev->ec = ec;
3738            REFD(ec, 1);
3739            e_object_ref(E_OBJECT(ec));
3740            ev->property = E_CLIENT_PROPERTY_NETWM_STATE;
3741            ecore_event_add(E_EVENT_CLIENT_PROPERTY, ev, _e_comp_x_client_event_free, NULL);
3742         }
3743         ec->netwm.fetch.type = 0;
3744      }
3745    if (ec->icccm.fetch.machine)
3746      {
3747         char *machine = ecore_x_icccm_client_machine_get(win);
3748 
3749         if ((!machine) && (ec->icccm.client_leader))
3750           machine = ecore_x_icccm_client_machine_get(ec->icccm.client_leader);
3751 
3752         eina_stringshare_replace(&ec->icccm.machine, machine);
3753         free(machine);
3754 
3755         ec->icccm.fetch.machine = 0;
3756         rem_change = 1;
3757      }
3758    if (ec->icccm.fetch.command)
3759      {
3760         if ((ec->icccm.command.argc > 0) && (ec->icccm.command.argv))
3761           {
3762              int i;
3763 
3764              for (i = 0; i < ec->icccm.command.argc; i++)
3765                free(ec->icccm.command.argv[i]);
3766              free(ec->icccm.command.argv);
3767           }
3768         ec->icccm.command.argc = 0;
3769         ec->icccm.command.argv = NULL;
3770         ecore_x_icccm_command_get(win,
3771                                   &(ec->icccm.command.argc),
3772                                   &(ec->icccm.command.argv));
3773         if ((ec->icccm.client_leader) &&
3774             (!ec->icccm.command.argv))
3775           ecore_x_icccm_command_get(ec->icccm.client_leader,
3776                                     &(ec->icccm.command.argc),
3777                                     &(ec->icccm.command.argv));
3778         ec->icccm.fetch.command = 0;
3779         rem_change = 1;
3780      }
3781    if (ec->changes.prop || ec->icccm.fetch.hints)
3782      {
3783         Eina_Bool accepts_focus, is_urgent;
3784         Ecore_X_Window_State_Hint state = ec->icccm.state;
3785 
3786         accepts_focus = EINA_TRUE;
3787         is_urgent = EINA_FALSE;
3788         ec->icccm.state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
3789         if (ecore_x_icccm_hints_get(win,
3790                                     &accepts_focus,
3791                                     &ec->icccm.state,
3792                                     &ec->icccm.icon_pixmap,
3793                                     &ec->icccm.icon_mask,
3794                                     (Ecore_X_Window*)&ec->icccm.icon_window,
3795                                     (Ecore_X_Window*)&ec->icccm.window_group,
3796                                     &is_urgent))
3797           {
3798              if (ec->new_client)
3799                {
3800                   /* clients may unset iconic state when no wm is present */
3801                   if (ec->netwm.state.hidden && (ec->icccm.state == ECORE_X_WINDOW_STATE_HINT_NORMAL))
3802                     ec->icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_ICONIC;
3803                   else
3804                     ec->icccm.initial_state = ec->icccm.state;
3805                }
3806              if (state != ec->icccm.state)
3807                {
3808                   if (ec->icccm.state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
3809                     ec->ignored = 1, ec->visible = 0;
3810                   else
3811                     {
3812                        ec->visible = 1;
3813                        ec->changes.visible = ec->new_client;
3814                        if ((!ec->new_client) &&
3815                          (ec->icccm.state == ECORE_X_WINDOW_STATE_HINT_NORMAL))
3816                          evas_object_show(ec->frame);
3817                     }
3818                }
3819              ec->icccm.accepts_focus = accepts_focus;
3820              ec->icccm.urgent = is_urgent;
3821              e_client_urgent_set(ec, is_urgent);
3822 
3823              /* If this is a new window, set the state as requested. */
3824              if ((ec->new_client) &&
3825                  (ec->icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
3826                e_client_iconify(ec);
3827           }
3828         ec->icccm.fetch.hints = 0;
3829         rem_change = 1;
3830      }
3831    if (ec->override) ec->placed = EINA_TRUE;
3832    if (ec->changes.prop || ec->icccm.fetch.size_pos_hints)
3833      {
3834         Eina_Bool request_pos;
3835 
3836         request_pos = EINA_FALSE;
3837         if (ecore_x_icccm_size_pos_hints_get(win,
3838                                              &request_pos,
3839                                              &ec->icccm.gravity,
3840                                              &ec->icccm.min_w,
3841                                              &ec->icccm.min_h,
3842                                              &ec->icccm.max_w,
3843                                              &ec->icccm.max_h,
3844                                              &ec->icccm.base_w,
3845                                              &ec->icccm.base_h,
3846                                              &ec->icccm.step_w,
3847                                              &ec->icccm.step_h,
3848                                              &ec->icccm.min_aspect,
3849                                              &ec->icccm.max_aspect))
3850           {
3851              ec->icccm.request_pos = request_pos;
3852              if (request_pos && (!ec->placed) && (!ec->re_manage))
3853                {
3854                   Ecore_X_Window_Attributes *att;
3855                   int bw;
3856                   int l, r, t, b;
3857                   int zx = 0, zy = 0, zw = 0, zh = 0;
3858 
3859                   if (ec->zone)
3860                     e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
3861                   e_comp_object_frame_geometry_get(ec->frame, &l, &r, &t, &b);
3862                   att = &cd->initial_attributes;
3863                   bw = att->border * 2;
3864                   switch (ec->icccm.gravity)
3865                     {
3866                      case ECORE_X_GRAVITY_N:
3867                        ec->x = (att->x - (bw / 2)) - (l / 2);
3868                        ec->y = att->y;
3869                        break;
3870 
3871                      case ECORE_X_GRAVITY_NE:
3872                        ec->x = (att->x - (bw)) - (l);
3873                        ec->y = att->y;
3874                        break;
3875 
3876                      case ECORE_X_GRAVITY_E:
3877                        ec->x = (att->x - (bw)) - (l);
3878                        ec->y = (att->y - (bw / 2)) - (t / 2);
3879                        break;
3880 
3881                      case ECORE_X_GRAVITY_SE:
3882                        ec->x = (att->x - (bw)) - (l);
3883                        ec->y = (att->y - (bw)) - (t);
3884                        break;
3885 
3886                      case ECORE_X_GRAVITY_S:
3887                        ec->x = (att->x - (bw / 2)) - (l / 2);
3888                        ec->y = (att->y - (bw)) - (t);
3889                        break;
3890 
3891                      case ECORE_X_GRAVITY_SW:
3892                        ec->x = att->x;
3893                        ec->y = (att->y - (bw)) - (t);
3894                        break;
3895 
3896                      case ECORE_X_GRAVITY_W:
3897                        ec->x = att->x;
3898                        ec->y = (att->y - (bw)) - (t);
3899                        break;
3900 
3901                      case ECORE_X_GRAVITY_CENTER:
3902                        ec->x = (att->x - (bw / 2)) - (l / 2);
3903                        ec->y = (att->y - (bw / 2)) - (t / 2);
3904                        break;
3905 
3906                      case ECORE_X_GRAVITY_NW:
3907                      default:
3908                        ec->x = att->x;
3909                        ec->y = att->y;
3910                     }
3911 
3912                   /*
3913                    * This ensures that windows that like to open with a x/y
3914                    * position smaller than returned by e_zone_useful_geometry_get()
3915                    * are moved to useful positions.
3916                    */
3917                   // ->
3918                   if (e_config->geometry_auto_move)
3919                     {
3920                        if (ec->x < zx)
3921                          ec->x = zx;
3922 
3923                        if (ec->y < zy)
3924                          ec->y = zy;
3925 
3926                        /* ensure we account for windows which already have client_inset;
3927                         * fixes lots of wine placement issues
3928                         */
3929                        if (ec->x - l >= zx)
3930                          ec->x -= l;
3931                        if (ec->y - t >= zy)
3932                          ec->y -= t;
3933 
3934                        if (ec->x + ec->w > zx + zw)
3935                          ec->x = zx + zw - ec->w;
3936 
3937                        if (ec->y + ec->h > zy + zh)
3938                          ec->y = zy + zh - ec->h;
3939 
3940                        // <--
3941                        if (e_comp_zone_xy_get(ec->x, ec->y))
3942                          {
3943                             if (!E_INSIDE(ec->x, ec->y, ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h))
3944                               {
3945                                  ec->x = E_CLAMP(ec->x, ec->zone->x, ec->zone->x + ec->zone->w);
3946                                  ec->y = E_CLAMP(ec->y, ec->zone->y, ec->zone->y + ec->zone->h);
3947                               }
3948                             /* some application failing to correctly center a window */
3949                             if (eina_list_count(e_comp->zones) > 1)
3950                               {
3951                                  if (abs((e_comp->w / 2) - ec->x - (ec->w / 2)) < 3)
3952                                    ec->x = ((ec->zone->x + ec->zone->w) / 2) - (ec->w / 2);
3953                                  if (abs((e_comp->h / 2) - ec->y - (ec->h / 2)) < 3)
3954                                    ec->y = ((ec->zone->y + ec->zone->h) / 2) - (ec->h / 2);
3955                               }
3956                             ec->changes.pos = 1;
3957                             ec->placed = 1;
3958                          }
3959                     }
3960                   else
3961                     {
3962                        ec->changes.pos = 1;
3963                        ec->placed = 1;
3964                     }
3965                }
3966              if (ec->placed && (!e_client_util_resizing_get(ec)) && (!ec->override))
3967                {
3968                   if (ec->fullscreen || ec->maximized)
3969                     e_client_rescale(ec);
3970                   else
3971                     {
3972                        int rw = ec->w, rh = ec->h;
3973 
3974                        e_client_resize_limit(ec, &rw, &rh);
3975                        evas_object_resize(ec->frame, rw, rh);
3976                     }
3977                }
3978           }
3979         if (ec->icccm.min_w > 32767) ec->icccm.min_w = 32767;
3980         if (ec->icccm.min_h > 32767) ec->icccm.min_h = 32767;
3981         if (ec->icccm.max_w > 32767) ec->icccm.max_w = 32767;
3982         if (ec->icccm.max_h > 32767) ec->icccm.max_h = 32767;
3983         if (ec->icccm.base_w > 32767) ec->icccm.base_w = 32767;
3984         if (ec->icccm.base_h > 32767) ec->icccm.base_h = 32767;
3985         //	if (ec->icccm.step_w < 1) ec->icccm.step_w = 1;
3986         //	if (ec->icccm.step_h < 1) ec->icccm.step_h = 1;
3987         // if doing a resize, fix it up
3988         if (e_client_util_resizing_get(ec))
3989           {
3990              int x, y, w, h, new_w, new_h;
3991 
3992              x = ec->x;
3993              y = ec->y;
3994              w = ec->w;
3995              h = ec->h;
3996              new_w = w;
3997              new_h = h;
3998              e_client_resize_limit(ec, &new_w, &new_h);
3999              if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
4000                  (ec->resize_mode == E_POINTER_RESIZE_L) ||
4001                  (ec->resize_mode == E_POINTER_RESIZE_BL))
4002                x += (w - new_w);
4003              if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
4004                  (ec->resize_mode == E_POINTER_RESIZE_T) ||
4005                  (ec->resize_mode == E_POINTER_RESIZE_TR))
4006                y += (h - new_h);
4007              evas_object_geometry_set(ec->frame, x, y, new_w, new_h);
4008           }
4009         ec->icccm.fetch.size_pos_hints = 0;
4010         rem_change = 1;
4011      }
4012    if (ec->icccm.fetch.protocol)
4013      {
4014         int i, num;
4015         Ecore_X_WM_Protocol *proto;
4016 
4017         proto = ecore_x_window_prop_protocol_list_get(win, &num);
4018         if (proto)
4019           {
4020              for (i = 0; i < num; i++)
4021                {
4022                   if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
4023                     ec->icccm.delete_request = 1;
4024                   else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
4025                     ec->icccm.take_focus = 1;
4026                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
4027                     ec->netwm.ping = 1;
4028                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
4029                     {
4030                        ec->netwm.sync.request = 1;
4031                        if (!ecore_x_netwm_sync_counter_get(win,
4032                                                            &cd->sync_counter))
4033                          ec->netwm.sync.request = 0;
4034                     }
4035                }
4036              free(proto);
4037           }
4038         if (ec->netwm.ping && cd->evas_init)
4039           e_client_ping(ec);
4040         else
4041           E_FREE_FUNC(ec->ping_poller, ecore_poller_del);
4042         ec->icccm.fetch.protocol = 0;
4043      }
4044    if (ec->icccm.fetch.transient_for)
4045      {
4046         /* TODO: What do to if the transient for isn't mapped yet? */
4047         E_Client *ec_parent = NULL;
4048 
4049         ec->icccm.transient_for = ecore_x_icccm_transient_for_get(win);
4050         if (ec->icccm.transient_for)
4051           ec_parent = _e_comp_x_client_find_by_window(ec->icccm.transient_for);
4052 
4053         e_client_parent_set(ec, ec_parent);
4054         if (ec->parent && (!e_client_util_ignored_get(ec)) && ec->netwm.state.modal)
4055           _e_comp_x_client_modal_setup(ec);
4056         if ((ec_parent) && (cd->stack != ECORE_X_STACK_NONE))
4057           {
4058              E_Client *ec2;
4059 
4060              // find last one
4061              for (ec2 = ec_parent; ec2->stack.next; ec2 = ec2->stack.next);
4062              ec->stack.prev = ec2;
4063              ec->stack.next = NULL;
4064              ec->stack.prev->stack.next = ec;
4065           }
4066         ec->icccm.fetch.transient_for = 0;
4067         rem_change = 1;
4068      }
4069    if (ec->icccm.fetch.window_role)
4070      {
4071         char *role = ecore_x_icccm_window_role_get(win);
4072         eina_stringshare_replace(&ec->icccm.window_role, role);
4073         free(role);
4074 
4075         ec->icccm.fetch.window_role = 0;
4076         rem_change = 1;
4077      }
4078    if (ec->icccm.fetch.icon_name)
4079      {
4080         char *icon_name = ecore_x_icccm_icon_name_get(win);
4081         eina_stringshare_replace(&ec->icccm.icon_name, icon_name);
4082         free(icon_name);
4083 
4084         ec->hacks.iconic_shading =
4085           ((ec->netwm.icon_name == ec->netwm.name) &&
4086            (!e_util_strcmp(ec->netwm.icon_name, "QEMU")));
4087 
4088         ec->icccm.fetch.icon_name = 0;
4089         rem_change = 1;
4090      }
4091    if (ec->netwm.fetch.icon_name)
4092      {
4093         char *icon_name;
4094         ecore_x_netwm_icon_name_get(win, &icon_name);
4095         eina_stringshare_replace(&ec->netwm.icon_name, icon_name);
4096         free(icon_name);
4097 
4098         ec->netwm.fetch.icon_name = 0;
4099         rem_change = 1;
4100      }
4101    if (ec->netwm.fetch.opacity)
4102      {
4103         unsigned int val;
4104 
4105         if (ecore_x_netwm_opacity_get(win, &val))
4106           {
4107              val >>= 24;
4108              if (ec->netwm.opacity != val)
4109                {
4110                   ec->netwm.opacity = val;
4111                   evas_object_color_set(ec->frame, val, val, val, val);
4112                   rem_change = 1;
4113                }
4114              ec->netwm.fetch.opacity = !ec->netwm.opacity;
4115           }
4116         else
4117           ec->netwm.fetch.opacity = 0;
4118      }
4119    if (ec->netwm.fetch.icon)
4120      {
4121         _e_comp_x_client_icon_free(ec->netwm.icons, ec->netwm.num_icons);
4122         ec->netwm.icons = NULL;
4123         ec->netwm.num_icons = 0;
4124         if (ecore_x_netwm_icons_get(win,
4125                                     &ec->netwm.icons,
4126                                     &ec->netwm.num_icons))
4127           {
4128              if (ec->netwm.icons)
4129                ec->netwm.icons = _e_comp_x_client_icon_deduplicate
4130                  (ec->netwm.icons, ec->netwm.num_icons);
4131              ec->changes.icon = 1;
4132           }
4133         ec->netwm.fetch.icon = 0;
4134      }
4135    if (ec->netwm.fetch.user_time)
4136      {
4137         ecore_x_netwm_user_time_get(win, &ec->netwm.user_time);
4138         ec->netwm.fetch.user_time = 0;
4139      }
4140    if (ec->netwm.fetch.strut)
4141      {
4142         if (!ecore_x_netwm_strut_partial_get(win,
4143                                              &ec->netwm.strut.left,
4144                                              &ec->netwm.strut.right,
4145                                              &ec->netwm.strut.top,
4146                                              &ec->netwm.strut.bottom,
4147                                              &ec->netwm.strut.left_start_y,
4148                                              &ec->netwm.strut.left_end_y,
4149                                              &ec->netwm.strut.right_start_y,
4150                                              &ec->netwm.strut.right_end_y,
4151                                              &ec->netwm.strut.top_start_x,
4152                                              &ec->netwm.strut.top_end_x,
4153                                              &ec->netwm.strut.bottom_start_x,
4154                                              &ec->netwm.strut.bottom_end_x))
4155           {
4156              ecore_x_netwm_strut_get(win,
4157                                      &ec->netwm.strut.left, &ec->netwm.strut.right,
4158                                      &ec->netwm.strut.top, &ec->netwm.strut.bottom);
4159 
4160              ec->netwm.strut.left_start_y = 0;
4161              ec->netwm.strut.left_end_y = 0;
4162              ec->netwm.strut.right_start_y = 0;
4163              ec->netwm.strut.right_end_y = 0;
4164              ec->netwm.strut.top_start_x = 0;
4165              ec->netwm.strut.top_end_x = 0;
4166              ec->netwm.strut.bottom_start_x = 0;
4167              ec->netwm.strut.bottom_end_x = 0;
4168           }
4169         ec->netwm.fetch.strut = 0;
4170      }
4171    if (ec->qtopia.fetch.soft_menu)
4172      {
4173         e_hints_window_qtopia_soft_menu_get(ec);
4174         ec->qtopia.fetch.soft_menu = 0;
4175         rem_change = 1;
4176      }
4177    if (ec->qtopia.fetch.soft_menus)
4178      {
4179         e_hints_window_qtopia_soft_menus_get(ec);
4180         ec->qtopia.fetch.soft_menus = 0;
4181         rem_change = 1;
4182      }
4183    if (ec->vkbd.fetch.state)
4184      {
4185         e_hints_window_virtual_keyboard_state_get(ec);
4186         ec->vkbd.fetch.state = 0;
4187         rem_change = 1;
4188      }
4189    if (ec->vkbd.fetch.vkbd)
4190      {
4191         e_hints_window_virtual_keyboard_get(ec);
4192         ec->vkbd.fetch.vkbd = 0;
4193         rem_change = 1;
4194      }
4195    if (cd->illume.conformant.fetch.conformant)
4196      {
4197         cd->illume.conformant.conformant =
4198           ecore_x_e_illume_conformant_get(win);
4199         cd->illume.conformant.fetch.conformant = 0;
4200      }
4201    if (cd->illume.quickpanel.fetch.state)
4202      {
4203         cd->illume.quickpanel.state =
4204           ecore_x_e_illume_quickpanel_state_get(win);
4205         cd->illume.quickpanel.fetch.state = 0;
4206      }
4207    if (cd->illume.quickpanel.fetch.quickpanel)
4208      {
4209         cd->illume.quickpanel.quickpanel =
4210           ecore_x_e_illume_quickpanel_get(win);
4211         cd->illume.quickpanel.fetch.quickpanel = 0;
4212      }
4213    if (cd->illume.quickpanel.fetch.priority.major)
4214      {
4215         cd->illume.quickpanel.priority.major =
4216           ecore_x_e_illume_quickpanel_priority_major_get(win);
4217         cd->illume.quickpanel.fetch.priority.major = 0;
4218      }
4219    if (cd->illume.quickpanel.fetch.priority.minor)
4220      {
4221         cd->illume.quickpanel.priority.minor =
4222           ecore_x_e_illume_quickpanel_priority_minor_get(win);
4223         cd->illume.quickpanel.fetch.priority.minor = 0;
4224      }
4225    if (cd->illume.quickpanel.fetch.zone)
4226      {
4227         cd->illume.quickpanel.zone =
4228           ecore_x_e_illume_quickpanel_zone_get(win);
4229         cd->illume.quickpanel.fetch.zone = 0;
4230      }
4231    if (cd->illume.drag.fetch.drag)
4232      {
4233         cd->illume.drag.drag =
4234           ecore_x_e_illume_drag_get(win);
4235         cd->illume.drag.fetch.drag = 0;
4236      }
4237    if (cd->illume.drag.fetch.locked)
4238      {
4239         cd->illume.drag.locked =
4240           ecore_x_e_illume_drag_locked_get(win);
4241         cd->illume.drag.fetch.locked = 0;
4242      }
4243    if (cd->illume.win_state.fetch.state)
4244      {
4245         cd->illume.win_state.state =
4246           ecore_x_e_illume_window_state_get(win);
4247         cd->illume.win_state.fetch.state = 0;
4248      }
4249    if (ec->changes.shape)
4250      {
4251         Ecore_X_Rectangle *rects;
4252         int num;
4253         Eina_Bool pshaped = ec->shaped;
4254 
4255         ec->changes.shape = 0;
4256         rects = ecore_x_window_shape_rectangles_get(win, &num);
4257         if (rects && num)
4258           {
4259              int cw = 0, ch = 0;
4260 
4261              /* This doesn't fix the race, but makes it smaller. we detect
4262               * this and if cw and ch != client w/h then mark this as needing
4263               * a shape change again to fixup next event loop.
4264               */
4265              ecore_x_window_size_get(win, &cw, &ch);
4266              /* normalize for client window dead zone */
4267              if (ec->border_size && (num == 1))
4268                {
4269                   rects[0].x += ec->border_size;
4270                   rects[0].y += ec->border_size;
4271                   rects[0].width -= ec->border_size;
4272                   rects[0].height -= ec->border_size;
4273                }
4274              if ((cw != ec->client.w) || (ch != ec->client.h))
4275                {
4276                   ec->changes.shape = 1;
4277                   EC_CHANGED(ec);
4278                }
4279              if ((num == 1) &&
4280                  (rects[0].x == 0) &&
4281                  (rects[0].y == 0) &&
4282                  ((int)rects[0].width == cw) &&
4283                  ((int)rects[0].height == ch))
4284                {
4285                   if (ec->shaped)
4286                     {
4287                        ec->shaped = 0;
4288                        if (cd->reparented && (!ec->bordername))
4289                          {
4290                             ec->border.changed = 1;
4291                             EC_CHANGED(ec);
4292                          }
4293                     }
4294                }
4295              else
4296                {
4297                   if (cd->reparented)
4298                     {
4299                        ecore_x_window_shape_rectangles_set(pwin, rects, num);
4300                        if ((!ec->shaped) && (!ec->bordername))
4301                          {
4302                             ec->border.changed = 1;
4303                             EC_CHANGED(ec);
4304                          }
4305                     }
4306                   else
4307                     {
4308                        if (_e_comp_x_client_shape_rects_check(ec, rects, num))
4309                          e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
4310                     }
4311                   ec->shaped = 1;
4312                   ec->changes.shape_input = 0;
4313                   E_FREE(ec->shape_input_rects);
4314                   ec->shape_input_rects_num = 0;
4315                }
4316              if (cd->reparented || (!ec->shaped))
4317                free(rects);
4318              if (ec->shape_changed)
4319                e_comp_object_frame_theme_set(ec->frame, E_COMP_OBJECT_FRAME_RESHADOW);
4320              evas_object_pass_events_set(ec->frame, ec->netwm.type == E_WINDOW_TYPE_DND);
4321           }
4322         else
4323           {
4324              ec->shaped = 1;
4325              E_FREE(ec->shape_rects);
4326              ec->shape_rects_num = 0;
4327              E_FREE(ec->shape_input_rects);
4328              ec->shape_input_rects_num = 0;
4329              e_comp_object_frame_theme_set(ec->frame, E_COMP_OBJECT_FRAME_RESHADOW);
4330              if (ec->shaped && cd->reparented && (!ec->bordername))
4331                {
4332                   ec->border.changed = 1;
4333                   EC_CHANGED(ec);
4334                }
4335              evas_object_pass_events_set(ec->frame, 1);
4336           }
4337         if (ec->shaped != pshaped)
4338           {
4339              _e_comp_x_client_shape_input_rectangle_set(ec);
4340              if ((!ec->shaped) && cd->reparented)
4341                ecore_x_window_shape_mask_set(pwin, 0);
4342           }
4343         ec->need_shape_merge = 1;
4344      }
4345    if (ec->changes.shape_input)
4346      {
4347         Ecore_X_Rectangle *rects;
4348         Eina_Bool pshaped = ec->shaped_input, changed = EINA_FALSE;
4349         int num;
4350 
4351         ec->changes.shape_input = 0;
4352         rects = ecore_x_window_shape_input_rectangles_get(win, &num);
4353         if (rects && num)
4354           {
4355              int cw = 0, ch = 0;
4356 
4357              /* This doesn't fix the race, but makes it smaller. we detect
4358               * this and if cw and ch != client w/h then mark this as needing
4359               * a shape change again to fixup next event loop.
4360               */
4361              ecore_x_window_size_get(win, &cw, &ch);
4362              /* normalize for client window dead zone */
4363              if (ec->border_size && (num == 1))
4364                {
4365                   rects[0].x += ec->border_size;
4366                   rects[0].y += ec->border_size;
4367                   rects[0].width -= ec->border_size;
4368                   rects[0].height -= ec->border_size;
4369                }
4370              if ((cw != ec->client.w) || (ch != ec->client.h))
4371                ec->changes.shape_input = 1;
4372              if (num == 1)
4373                E_RECTS_CLIP_TO_RECT(rects[0].x, rects[0].y, rects[0].width, rects[0].height, 0, 0, cw, ch);
4374              if ((num == 1) &&
4375                  (rects[0].x == 0) &&
4376                  (rects[0].y == 0) &&
4377                  ((int)rects[0].width == cw) &&
4378                  ((int)rects[0].height == ch))
4379                {
4380                   ec->shaped_input = 0;
4381                   free(rects);
4382                }
4383              else
4384                {
4385                   ec->shaped_input = 1;
4386                   if (cd->reparented)
4387                     ecore_x_window_shape_input_rectangles_set(pwin, rects, num);
4388                   changed = EINA_TRUE;
4389                   free(ec->shape_input_rects);
4390                   ec->shape_input_rects = (Eina_Rectangle*)rects;
4391                   ec->shape_input_rects_num = num;
4392                }
4393              evas_object_pass_events_set(ec->frame, ec->netwm.type == E_WINDOW_TYPE_DND);
4394           }
4395         else
4396           {
4397              ec->shaped_input = 1;
4398              if (cd->reparented)
4399                ecore_x_window_shape_input_rectangles_set(pwin, rects, num);
4400              changed = EINA_TRUE;
4401              evas_object_pass_events_set(ec->frame, 1);
4402              free(ec->shape_input_rects);
4403              ec->shape_input_rects = NULL;
4404              ec->shape_input_rects_num = 0;
4405           }
4406         if (changed || (pshaped != ec->shaped_input))
4407           {
4408              ec->need_shape_merge = 1;
4409              e_comp_shape_queue();
4410           }
4411      }
4412    if (ec->changes.prop || ec->mwm.fetch.hints)
4413      {
4414         int pb;
4415 
4416         ec->mwm.exists =
4417           ecore_x_mwm_hints_get(win,
4418                                 &ec->mwm.func,
4419                                 &ec->mwm.decor,
4420                                 &ec->mwm.input);
4421         pb = ec->mwm.borderless;
4422         ec->mwm.borderless = 0;
4423         if (ec->mwm.exists)
4424           {
4425              if ((!(ec->mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
4426                  (!(ec->mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
4427                  (!(ec->mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
4428                ec->mwm.borderless = 1;
4429           }
4430         if (ec->mwm.borderless != pb)
4431           {
4432              if ((ec->internal || cd->reparented) && ((!ec->lock_border) || (!ec->border.name)))
4433                {
4434                   ec->border.changed = 1;
4435                   EC_CHANGED(ec);
4436                }
4437           }
4438         ec->mwm.fetch.hints = 0;
4439         rem_change = 1;
4440      }
4441    if (ec->e.fetch.video_parent)
4442      {
4443         /* unlinking child/parent */
4444         if (ec->e.state.video_parent_client != NULL)
4445           {
4446              ec->e.state.video_parent_client->e.state.video_child =
4447                eina_list_remove(ec->e.state.video_parent_client->e.state.video_child, ec);
4448           }
4449 
4450         ecore_x_window_prop_card32_get(win,
4451                                        ECORE_X_ATOM_E_VIDEO_PARENT,
4452                                        (Ecore_X_Window*)&ec->e.state.video_parent, 1);
4453 
4454         /* linking child/parent */
4455         if (ec->e.state.video_parent != 0)
4456           {
4457              E_Client *tmp;
4458 
4459              tmp = _e_comp_x_client_find_by_window(ec->e.state.video_parent);
4460              if (tmp)
4461                {
4462                   /* fprintf(stderr, "child added to parent \\o/\n"); */
4463                   ec->e.state.video_parent_client = tmp;
4464                   tmp->e.state.video_child = eina_list_append(tmp->e.state.video_child, ec);
4465                   if (ec->desk != tmp->desk)
4466                     e_client_desk_set(ec, tmp->desk);
4467                }
4468           }
4469 
4470         /* fprintf(stderr, "new parent %x => %p\n", ec->e.state.video_parent, ec->e.state.video_parent_client); */
4471 
4472         if (ec->e.state.video_parent_client) ec->e.fetch.video_parent = 0;
4473         rem_change = 1;
4474      }
4475    if (ec->e.fetch.video_position && ec->e.fetch.video_parent == 0)
4476      {
4477         unsigned int xy[2];
4478 
4479         ecore_x_window_prop_card32_get(win,
4480                                        ECORE_X_ATOM_E_VIDEO_POSITION,
4481                                        xy, 2);
4482         ec->e.state.video_position.x = xy[0];
4483         ec->e.state.video_position.y = xy[1];
4484         ec->e.state.video_position.updated = 1;
4485         ec->e.fetch.video_position = 0;
4486         ec->x = ec->e.state.video_position.x;
4487         ec->y = ec->e.state.video_position.y;
4488 
4489         fprintf(stderr, "internal position has been updated [%i, %i]\n", ec->e.state.video_position.x, ec->e.state.video_position.y);
4490      }
4491    if (ec->changes.prop || ec->netwm.update.state)
4492      {
4493         e_hints_window_state_set(ec);
4494         /* Some stats might change the border, like modal */
4495         if (((!ec->lock_border) || (!ec->border.name)) &&
4496             (!(((ec->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))) &&
4497             (ec->internal || cd->reparented))
4498           {
4499              ec->border.changed = 1;
4500              EC_CHANGED(ec);
4501           }
4502         if (ec->parent)
4503           {
4504              if (ec->netwm.state.modal)
4505                {
4506                   ec->parent->modal = ec;
4507                   if (ec->parent->focused)
4508                     evas_object_focus_set(ec->frame, 1);
4509                }
4510           }
4511         else if (ec->leader)
4512           {
4513              if (ec->netwm.state.modal)
4514                {
4515                   ec->leader->modal = ec;
4516                   if (ec->leader->focused)
4517                     evas_object_focus_set(ec->frame, 1);
4518                   else
4519                     {
4520                        Eina_List *l;
4521                        E_Client *child;
4522 
4523                        EINA_LIST_FOREACH(ec->leader->group, l, child)
4524                          {
4525                             if ((child != ec) && (child->focused))
4526                               evas_object_focus_set(ec->frame, 1);
4527                          }
4528                     }
4529                }
4530           }
4531         ec->netwm.update.state = 0;
4532      }
4533 
4534    if (cd->fetch_exe)
4535      {
4536         E_Exec_Instance *inst;
4537 
4538         if (((!ec->lock_border) || (!ec->border.name)) &&
4539             (ec->internal || cd->reparented))
4540           {
4541              ec->border.changed = 1;
4542              EC_CHANGED(ec);
4543           }
4544 
4545         {
4546            char *str = NULL;
4547 
4548            if ((!ec->internal) &&
4549                ((ecore_x_netwm_startup_id_get(win, &str) && (str)) ||
4550                ((ec->icccm.client_leader > 0) &&
4551                 ecore_x_netwm_startup_id_get(ec->icccm.client_leader, &str) && (str)))
4552                )
4553              {
4554                 if (!strncmp(str, "E_START|", 8))
4555                   {
4556                      int id;
4557 
4558                      id = atoi(str + 8);
4559                      if (id > 0) ec->netwm.startup_id = id;
4560                   }
4561                 free(str);
4562              }
4563         }
4564         /* It's ok not to have fetch flag, should only be set on startup
4565          * and not changed. */
4566         if (!ecore_x_netwm_pid_get(win, &ec->netwm.pid))
4567           {
4568              if (ec->icccm.client_leader)
4569                {
4570                   if (!ecore_x_netwm_pid_get(ec->icccm.client_leader, &ec->netwm.pid))
4571                     ec->netwm.pid = -1;
4572                }
4573              else
4574                ec->netwm.pid = -1;
4575           }
4576 
4577         if (!e_client_util_ignored_get(ec))
4578           {
4579              inst = e_exec_startup_id_pid_instance_find(ec->netwm.startup_id,
4580                                                         ec->netwm.pid);
4581              if (inst)
4582                {
4583                   Eina_Bool found;
4584 
4585                   if (inst->used == 0)
4586                     {
4587                        inst->used++;
4588                        if ((!ec->remember) || !(ec->remember->apply & E_REMEMBER_APPLY_DESKTOP))
4589                          {
4590                             E_Zone *zone;
4591                             E_Desk *desk;
4592 
4593                             zone = e_comp_zone_number_get(inst->screen);
4594                             if (zone) e_client_zone_set(ec, zone);
4595                             desk = e_desk_at_xy_get(ec->zone, inst->desk_x,
4596                                                     inst->desk_y);
4597                             if (desk) e_client_desk_set(ec, desk);
4598                          }
4599                        if (ec->netwm.pid != ecore_exe_pid_get(inst->exe))
4600                          {
4601                             /* most likely what has happened here is that the .desktop launcher
4602                              * has spawned a process which then created this border, meaning the
4603                              * E_Exec instance will be deleted in a moment, and we will be unable to track it.
4604                              * to prevent this, we convert our instance to a phony
4605                              */
4606                              inst->phony = 1;
4607                          }
4608                     }
4609                   found = !!inst->clients;
4610                   e_exec_instance_client_add(inst, ec);
4611                   if (!found)
4612                     e_exec_instance_found(inst);
4613                }
4614 
4615              if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
4616                {
4617                   E_Client *ecl = NULL;
4618 
4619                   ecl = ec->parent;
4620                   if (!ecl)
4621                     ecl = ec->leader;
4622                   if (!ecl)
4623                     {
4624                        E_Client *child;
4625 
4626                        E_CLIENT_FOREACH(child)
4627                          {
4628                             if (child == ec) continue;
4629                             if (e_object_is_del(E_OBJECT(child))) continue;
4630                             if ((ec->icccm.client_leader) &&
4631                                 (child->icccm.client_leader ==
4632                                  ec->icccm.client_leader))
4633                               {
4634                                  ecl = child;
4635                                  break;
4636                               }
4637                          }
4638                     }
4639                   if (ecl)
4640                     {
4641                        if (ecl->zone)
4642                          e_client_zone_set(ec, ecl->zone);
4643                        if (ecl->desk)
4644                          e_client_desk_set(ec, ecl->desk);
4645                        else
4646                          e_client_stick(ec);
4647                     }
4648                }
4649           }
4650         cd->fetch_exe = 0;
4651      }
4652 
4653    if (need_desk_set)
4654      {
4655         E_Desk *desk = NULL;
4656         const char *p, *p2;
4657         Eina_Bool set = EINA_FALSE;
4658         int i;
4659 
4660         /* set desktop using given initial profile */
4661         p = ec->e.state.profile.set;
4662         if (p)
4663           {
4664              if (!e_util_strcmp(p, ec->desk->window_profile))
4665                {
4666                   e_client_desk_window_profile_wait_desk_set(ec, ec->desk);
4667                   set = EINA_TRUE;
4668                }
4669              else
4670                {
4671                   desk = e_comp_desk_window_profile_get(p);
4672                   if (desk)
4673                     {
4674                        e_client_desk_set(ec, desk);
4675                        set = EINA_TRUE;
4676                     }
4677                }
4678           }
4679 
4680         if (!set)
4681           {
4682              /* try to find desktop using available profile list */
4683              for (i = 0; i < ec->e.state.profile.num; i++)
4684                {
4685                   p2 = ec->e.state.profile.available_list[i];
4686                   if (!e_util_strcmp(p2, ec->desk->window_profile))
4687                     {
4688                        eina_stringshare_replace(&ec->e.state.profile.set, p2);
4689                        e_client_desk_window_profile_wait_desk_set(ec, ec->desk);
4690                        set = EINA_TRUE;
4691                        break;
4692                     }
4693                }
4694              if (!set)
4695                {
4696                   for (i = 0; i < ec->e.state.profile.num; i++)
4697                     {
4698                        p2 = ec->e.state.profile.available_list[i];
4699                        desk = e_comp_desk_window_profile_get(p2);
4700                        if (desk)
4701                          {
4702                             e_client_desk_set(ec, desk);
4703                             set = EINA_TRUE;
4704                             break;
4705                          }
4706                     }
4707                }
4708           }
4709 
4710         if ((!set) && ec->desk)
4711           {
4712              eina_stringshare_replace(&ec->e.state.profile.set, ec->desk->window_profile);
4713              e_client_desk_window_profile_wait_desk_set(ec, ec->desk);
4714           }
4715      }
4716 
4717    if (ec->e.state.profile.set)
4718      {
4719         printf("E: sent profile set req to 0x%x [%s]\n", win, ec->e.state.profile.set);
4720         ecore_x_e_window_profile_change_request_send(win,
4721                                                      ec->e.state.profile.set);
4722         eina_stringshare_replace(&ec->e.state.profile.wait, ec->e.state.profile.set);
4723         ec->e.state.profile.wait_for_done = 1;
4724         eina_stringshare_replace(&ec->e.state.profile.set, NULL);
4725      }
4726    if (cd->fetch_gtk_frame_extents)
4727      {
4728         unsigned int *extents;
4729         int count;
4730 
4731         if (ecore_x_window_prop_property_get(win,
4732                                              ATM_GTK_FRAME_EXTENTS,
4733                                              ECORE_X_ATOM_CARDINAL, 32,
4734                                              (void *)(&extents), &count))
4735           {
4736              /* _GTK_FRAME_EXTENTS describes a region l/r/t/b pixels
4737               * from the "window" object in which shadows will be drawn.
4738               * this area should not be accounted for in sizing or
4739               * placement calculations.
4740               */
4741              e_comp_object_frame_geometry_set(ec->frame,
4742                -extents[0], -extents[1], -extents[2], -extents[3]);
4743              if (ec->override &&
4744                 (ec->x == ec->comp_data->initial_attributes.x) &&
4745                 (ec->y == ec->comp_data->initial_attributes.y))
4746                e_comp_object_frame_xy_adjust(ec->frame, ec->x, ec->y, &ec->x, &ec->y);
4747              free(extents);
4748           }
4749         cd->fetch_gtk_frame_extents = 0;
4750      }
4751    ec->changes.prop = 0;
4752    if (rem_change) e_remember_update(ec);
4753    if ((!cd->reparented) && (!ec->internal)) ec->changes.border = 0;
4754    if (ec->changes.icon)
4755      {
4756         /* don't create an icon until we need it */
4757         if (cd->reparented) return;
4758         cd->change_icon = 1;
4759         ec->changes.icon = 0;
4760      }
4761 }
4762 
4763 static Eina_Bool
_e_comp_x_first_draw_delay_cb(void * data)4764 _e_comp_x_first_draw_delay_cb(void *data)
4765 {
4766    E_Client *ec = data;
4767 
4768    _e_comp_x_client_data_get(ec)->first_draw_delay = NULL;
4769    if (ec->shape_rects || (!ec->shaped))
4770      e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
4771    return EINA_FALSE;
4772 }
4773 
4774 static void
_e_comp_x_hook_client_new(void * d EINA_UNUSED,E_Client * ec)4775 _e_comp_x_hook_client_new(void *d EINA_UNUSED, E_Client *ec)
4776 {
4777    Ecore_X_Window win;
4778    Eina_List *pending;
4779    Pending_Configure *pc;
4780 
4781    E_COMP_X_PIXMAP_CHECK;
4782    win = e_pixmap_window_get(ec->pixmap);
4783    ec->ignored = e_comp_ignore_win_find(win);
4784 
4785    ec->comp_data = E_NEW(E_Comp_Client_Data, 1);
4786    ec->comp_data->set_win_type = ec->comp_data->fetch_exe = 1;
4787 
4788    /* FIXME: ewww - round trip */
4789    ec->argb = ecore_x_window_argb_get(win);
4790    ec->changes.shape = 1;
4791    ec->changes.shape_input = 1;
4792 
4793    ec->netwm.type = E_WINDOW_TYPE_UNKNOWN;
4794    ec->icccm.state = ec->icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NONE;
4795 
4796    if (!_e_comp_x_client_new_helper(ec)) return;
4797    ec->ignored |= e_comp->comp_type == E_PIXMAP_TYPE_WL;
4798    pending = eina_hash_set(pending_configures, &win, NULL);
4799    if (pending)
4800      {
4801         Eina_Bool request_pos = EINA_FALSE;
4802 
4803         /* UGLY: round trip, but necessary to work around bad clients
4804          * positioning windows anyway AND libreoffice trying to hack
4805          * getting its windows across multiple screens this way
4806          * which isn't really right either... */
4807         ecore_x_icccm_size_pos_hints_get(win,
4808                                          &request_pos,
4809                                          &ec->icccm.gravity,
4810                                          &ec->icccm.min_w,
4811                                          &ec->icccm.min_h,
4812                                          &ec->icccm.max_w,
4813                                          &ec->icccm.max_h,
4814                                          &ec->icccm.base_w,
4815                                          &ec->icccm.base_h,
4816                                          &ec->icccm.step_w,
4817                                          &ec->icccm.step_h,
4818                                          &ec->icccm.min_aspect,
4819                                          &ec->icccm.max_aspect);
4820         if (request_pos)
4821           {
4822              Eina_List *l;
4823              E_Zone *zone;
4824              pc = eina_list_last_data_get(pending);
4825              EINA_LIST_FOREACH(e_comp->zones, l, zone)
4826                {
4827                   if (E_INTERSECTS(pc->point.x, pc->point.y, ec->w, ec->h,
4828                                    zone->x, zone->y, zone->w, zone->h))
4829                     {
4830                        e_client_zone_set(ec, zone);
4831                        break;
4832                     }
4833                }
4834           }
4835      }
4836    EINA_LIST_FREE(pending, pc)
4837      {
4838         ecore_timer_del(pc->timer);
4839         free(pc);
4840      }
4841 
4842    ec->comp_data->first_damage = ec->internal;
4843 
4844    eina_hash_add(clients_win_hash, &win, ec);
4845    if (!ec->input_only)
4846      ec->comp_data->first_draw_delay = ecore_timer_loop_add(e_comp_config_get()->first_draw_delay, _e_comp_x_first_draw_delay_cb, ec);
4847 }
4848 
4849 static void
_e_comp_x_hook_client_focus_unset_job(void * d EINA_UNUSED)4850 _e_comp_x_hook_client_focus_unset_job(void *d EINA_UNUSED)
4851 {
4852    E_Client *ec = unfocus_job_client;
4853    unfocus_job = NULL;
4854    if (!unfocus_job_client) return;
4855    unfocus_job_client = NULL;
4856    E_COMP_X_PIXMAP_CHECK;
4857    _e_comp_x_focus_setup(ec);
4858    _e_comp_x_focus_check();
4859 }
4860 
4861 static void
_e_comp_x_hook_client_focus_unset(void * d EINA_UNUSED,E_Client * ec)4862 _e_comp_x_hook_client_focus_unset(void *d EINA_UNUSED, E_Client *ec)
4863 {
4864    if (focus_job_client == ec)
4865      {
4866         focus_job_client = NULL;
4867         E_FREE_FUNC(focus_job, ecore_job_del);
4868      }
4869    if (ec->override) return;
4870    unfocus_job_client = ec;
4871    if (!unfocus_job)
4872      unfocus_job = ecore_job_add(_e_comp_x_hook_client_focus_unset_job, NULL);
4873 }
4874 
4875 static void
_e_comp_x_hook_client_focus_set_job(void * d EINA_UNUSED)4876 _e_comp_x_hook_client_focus_set_job(void *d EINA_UNUSED)
4877 {
4878    E_Client *ec = focus_job_client;
4879    focus_job = NULL;
4880    if (!focus_job_client) return;
4881    focus_job_client = NULL;
4882    focus_time = ecore_x_current_time_get();
4883    focus_canvas_time = 0;
4884    if (!e_client_has_xwindow(ec))
4885      {
4886         e_grabinput_focus(e_comp->root, E_FOCUS_METHOD_PASSIVE);
4887         return;
4888      }
4889    _e_comp_x_focus_setdown(ec);
4890 
4891    if ((ec->icccm.take_focus) && (ec->icccm.accepts_focus))
4892      {
4893         e_grabinput_focus(e_client_util_win_get(ec), E_FOCUS_METHOD_LOCALLY_ACTIVE);
4894         /* TODO what if the client didn't take focus ? */
4895      }
4896    else if (!ec->icccm.accepts_focus)
4897      {
4898         e_grabinput_focus(e_client_util_win_get(ec), E_FOCUS_METHOD_GLOBALLY_ACTIVE);
4899      }
4900    else if (!ec->icccm.take_focus)
4901      {
4902         e_grabinput_focus(e_client_util_win_get(ec), E_FOCUS_METHOD_PASSIVE);
4903      }
4904 }
4905 
4906 static void
_e_comp_x_hook_client_focus_set(void * d EINA_UNUSED,E_Client * ec)4907 _e_comp_x_hook_client_focus_set(void *d EINA_UNUSED, E_Client *ec)
4908 {
4909    if (unfocus_job_client == ec)
4910      {
4911         unfocus_job_client = NULL;
4912         E_FREE_FUNC(unfocus_job, ecore_job_del);
4913      }
4914    if (ec->override) return;
4915    focus_job_client = ec;
4916    if (!focus_job)
4917      focus_job = ecore_job_add(_e_comp_x_hook_client_focus_set_job, NULL);
4918 }
4919 
4920 static void
_e_comp_x_hook_client_redirect(void * d EINA_UNUSED,E_Client * ec)4921 _e_comp_x_hook_client_redirect(void *d EINA_UNUSED, E_Client *ec)
4922 {
4923    E_COMP_X_PIXMAP_CHECK;
4924    if (_e_comp_x_client_data_get(ec)->unredirected_single)
4925      {
4926         ecore_x_composite_redirect_window(_e_comp_x_client_window_get(ec), ECORE_X_COMPOSITE_UPDATE_MANUAL);
4927         _e_comp_x_client_data_get(ec)->unredirected_single = 0;
4928      }
4929    else if (e_comp->nocomp)
4930      {
4931         /* first window */
4932         e_comp_x_nocomp_end();
4933         ecore_x_window_reparent(_e_comp_x_client_window_get(ec), e_comp->root, ec->client.x, ec->client.y);
4934         _e_comp_x_client_stack(ec);
4935      }
4936    if (!_e_comp_x_client_data_get(ec)->damage)
4937      _e_comp_x_client_damage_add(ec);
4938 }
4939 
4940 static void
_e_comp_x_hook_client_unredirect(void * d EINA_UNUSED,E_Client * ec)4941 _e_comp_x_hook_client_unredirect(void *d EINA_UNUSED, E_Client *ec)
4942 {
4943    Ecore_X_Region parts;
4944 
4945    E_COMP_X_PIXMAP_CHECK;
4946    eina_hash_del(damages_hash, &_e_comp_x_client_data_get(ec)->damage, ec);
4947    parts = ecore_x_region_new(NULL, 0);
4948    ecore_x_damage_subtract(_e_comp_x_client_data_get(ec)->damage, 0, parts);
4949    ecore_x_region_free(parts);
4950    ecore_x_damage_free(_e_comp_x_client_data_get(ec)->damage);
4951    _e_comp_x_client_data_get(ec)->damage = 0;
4952 
4953    if (ec->unredirected_single && (!_e_comp_x_client_data_get(ec)->unredirected_single))
4954      {
4955         ecore_x_composite_unredirect_window(_e_comp_x_client_window_get(ec), ECORE_X_COMPOSITE_UPDATE_MANUAL);
4956         ecore_x_window_reparent(_e_comp_x_client_window_get(ec), e_comp->win, ec->client.x, ec->client.y);
4957         ecore_x_window_raise(_e_comp_x_client_window_get(ec));
4958         _e_comp_x_client_data_get(ec)->unredirected_single = 1;
4959      }
4960    if (!e_comp->nocomp) return; //wait for it...
4961    ecore_x_composite_unredirect_subwindows(e_comp->root, ECORE_X_COMPOSITE_UPDATE_MANUAL);
4962    ecore_x_window_hide(e_comp->win);
4963 }
4964 
4965 static Eina_Bool
_e_comp_x_dead_win_timer(void * d)4966 _e_comp_x_dead_win_timer(void *d)
4967 {
4968    uint32_t pwin = (uintptr_t)(uintptr_t*)d;
4969 
4970    eina_hash_del_by_key(dead_wins, &pwin);
4971    return EINA_FALSE;
4972 }
4973 
4974 static void
_e_comp_x_hook_client_del(void * d EINA_UNUSED,E_Client * ec)4975 _e_comp_x_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
4976 {
4977    Ecore_X_Window win, pwin;
4978    unsigned int visible = 0;
4979    E_Comp_X_Client_Data *cd;
4980 
4981    E_COMP_X_PIXMAP_CHECK;
4982    win = e_client_util_win_get(ec);
4983    pwin = e_client_util_pwin_get(ec);
4984    cd = _e_comp_x_client_data_get(ec);
4985 
4986    if (mouse_client == ec) mouse_client = NULL;
4987    if (focus_job_client == ec) focus_job_client = NULL;
4988    if (unfocus_job_client == ec) unfocus_job_client = NULL;
4989    if ((!stopping) && cd && (!cd->deleted))
4990      ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &visible, 1);
4991    if (stopping && ec->iconic)
4992      {
4993         e_hints_window_iconic_set(ec);
4994         e_hints_window_state_set(ec);
4995      }
4996    if ((!ec->already_unparented) && cd && cd->reparented)
4997      {
4998         _e_comp_x_focus_setdown(ec);
4999         e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, pwin);
5000         e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, pwin);
5001         if (!cd->deleted)
5002           {
5003              if (stopping)
5004                {
5005                   ecore_x_window_reparent(win, e_comp->root,
5006                                           ec->client.x, ec->client.y);
5007                   ecore_x_window_configure(win,
5008                                            ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
5009                                            ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
5010                                            0, 0, 0, 0, 0, pwin,
5011                                            ECORE_X_WINDOW_STACK_BELOW);
5012                }
5013 
5014              else
5015                /* put the window back where we found it to prevent annoying dancing windows */
5016                ecore_x_window_reparent(win, e_comp->root,
5017                                        cd->initial_attributes.x,
5018                                        cd->initial_attributes.y);
5019              if (!ec->internal)
5020                ecore_x_window_save_set_del(win);
5021           }
5022         e_pixmap_alias(NULL, E_PIXMAP_TYPE_X, pwin);
5023      }
5024    ec->already_unparented = 1;
5025    if (cd)
5026      eina_hash_del_by_key(clients_win_hash, &win);
5027    if (cd && cd->damage)
5028      {
5029         eina_hash_del(damages_hash, &cd->damage, ec);
5030         ecore_x_damage_free(cd->damage);
5031         cd->damage = 0;
5032      }
5033    if (cd && cd->reparented)
5034      {
5035         eina_hash_del_by_key(clients_win_hash, &pwin);
5036         e_pixmap_parent_window_set(e_comp_x_client_pixmap_get(ec), 0);
5037         ecore_x_window_free(pwin);
5038         eina_hash_add(dead_wins, &pwin, (void*)1);
5039         ecore_timer_add(0.5, _e_comp_x_dead_win_timer, (uintptr_t*)(uintptr_t)pwin);
5040      }
5041 
5042    if (ec->hacks.mapping_change)
5043      _e_comp_x_mapping_change_disabled--;
5044    if (ec->parent && (ec->parent->modal == ec))
5045      {
5046         E_Comp_X_Client_Data *pcd;
5047 
5048         pcd = _e_comp_x_client_data_get(ec->parent);
5049         if (pcd->lock_win)
5050           {
5051              eina_hash_del_by_key(clients_win_hash, &pcd->lock_win);
5052              ecore_x_window_hide(pcd->lock_win);
5053              ecore_x_window_free(pcd->lock_win);
5054              pcd->lock_win = 0;
5055           }
5056         ec->parent->lock_close = 0;
5057         ec->parent->modal = NULL;
5058      }
5059    if (cd)
5060      E_FREE_FUNC(cd->first_draw_delay, ecore_timer_del);
5061 #ifdef HAVE_WAYLAND
5062    if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
5063      {
5064         if (e_pixmap_is_x(ec->pixmap))
5065           e_comp_wl_client_xwayland_setup(ec, NULL, NULL);
5066         else
5067           {
5068              e_pixmap_alias(NULL, E_PIXMAP_TYPE_X, win);
5069              free(cd);
5070              e_pixmap_free(e_comp_x_client_pixmap_get(ec));
5071           }
5072      }
5073    else
5074 #endif
5075      {
5076         if (e_pixmap_free(ec->pixmap))
5077           e_pixmap_client_set(ec->pixmap, NULL);
5078         ec->pixmap = NULL;
5079      }
5080    if (ec->netwm.icons)
5081      {
5082         _e_comp_x_client_icon_free(ec->netwm.icons, ec->netwm.num_icons);
5083         ec->netwm.icons = NULL;
5084         ec->netwm.num_icons = 0;
5085      }
5086 
5087    if (post_clients)
5088      post_clients = eina_list_remove(post_clients, ec);
5089 
5090    _e_comp_x_focus_check();
5091 }
5092 
5093 static void
_e_comp_x_hook_client_move_end(void * d EINA_UNUSED,E_Client * ec)5094 _e_comp_x_hook_client_move_end(void *d EINA_UNUSED, E_Client *ec)
5095 {
5096    E_COMP_X_PIXMAP_CHECK;
5097    _e_comp_x_client_data_get(ec)->moving = 0;
5098    if (!_e_comp_x_client_data_get(ec)->move_counter) return;
5099    _e_comp_x_client_data_get(ec)->move_counter = 0;
5100    ec->post_move = 1;
5101    _e_comp_x_post_client_idler_add(ec);
5102 }
5103 
5104 static void
_e_comp_x_hook_client_move_begin(void * d EINA_UNUSED,E_Client * ec)5105 _e_comp_x_hook_client_move_begin(void *d EINA_UNUSED, E_Client *ec)
5106 {
5107    E_COMP_X_PIXMAP_CHECK;
5108    _e_comp_x_client_data_get(ec)->moving = 1;
5109 }
5110 
5111 static void
_e_comp_x_hook_client_resize_end(void * d EINA_UNUSED,E_Client * ec)5112 _e_comp_x_hook_client_resize_end(void *d EINA_UNUSED, E_Client *ec)
5113 {
5114    E_COMP_X_PIXMAP_CHECK;
5115    if (_e_comp_x_client_data_get(ec)->alarm)
5116      {
5117         eina_hash_del_by_key(alarm_hash, &_e_comp_x_client_data_get(ec)->alarm);
5118         ecore_x_sync_alarm_free(_e_comp_x_client_data_get(ec)->alarm);
5119         _e_comp_x_client_data_get(ec)->alarm = 0;
5120      }
5121    ec->netwm.sync.alarm = 0;
5122    /* resize to last geometry if sync alarm for it was not yet handled */
5123    if (ec->pending_resize)
5124      {
5125         EC_CHANGED(ec);
5126         ec->changes.pos = 1;
5127         ec->changes.size = 1;
5128      }
5129 
5130    E_FREE_LIST(ec->pending_resize, free);
5131 }
5132 
5133 static void
_e_comp_x_hook_client_resize_begin(void * d EINA_UNUSED,E_Client * ec)5134 _e_comp_x_hook_client_resize_begin(void *d EINA_UNUSED, E_Client *ec)
5135 {
5136    E_COMP_X_PIXMAP_CHECK;
5137    if (!ec->netwm.sync.request) return;
5138    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
5139      {
5140         _e_comp_x_client_data_get(ec)->alarm = ecore_x_sync_alarm_new(_e_comp_x_client_data_get(ec)->sync_counter);
5141         eina_hash_add(alarm_hash, &_e_comp_x_client_data_get(ec)->alarm, ec);
5142      }
5143    ec->netwm.sync.alarm = ec->netwm.sync.serial = 1;
5144    ec->netwm.sync.wait = 0;
5145    ec->netwm.sync.send_time = ecore_loop_time_get();
5146 }
5147 
5148 static void
_e_comp_x_hook_client_desk_set(void * d EINA_UNUSED,E_Client * ec)5149 _e_comp_x_hook_client_desk_set(void *d EINA_UNUSED, E_Client *ec)
5150 {
5151    unsigned int num[2];
5152    int x, y;
5153 
5154    E_COMP_X_PIXMAP_CHECK;
5155    e_desk_xy_get(ec->desk, &x, &y);
5156    num[0] = x, num[1] = y;
5157    ecore_x_window_prop_card32_set(e_client_util_win_get(ec), E_ATOM_DESK, num, 2);
5158 }
5159 
5160 static Eina_Bool
_e_comp_x_cb_ping(void * data EINA_UNUSED,int ev_type EINA_UNUSED,Ecore_X_Event_Ping * ev)5161 _e_comp_x_cb_ping(void *data EINA_UNUSED, int ev_type EINA_UNUSED, Ecore_X_Event_Ping *ev)
5162 {
5163    E_Client *ec;
5164 
5165    ec = _e_comp_x_client_find_by_window(ev->event_win);
5166    if (ec) ec->ping_ok = 1;
5167    return ECORE_CALLBACK_PASS_ON;
5168 }
5169 
5170 static void
_e_comp_pointer_grab(void)5171 _e_comp_pointer_grab(void)
5172 {
5173    if (_e_comp_x_suspend_grabbed) ecore_x_window_free(_e_comp_x_suspend_grabbed);
5174    _e_comp_x_suspend_grabbed = ecore_x_window_input_new(e_comp->root, 0, 0, 1, 1);
5175    ecore_x_window_show(_e_comp_x_suspend_grabbed);
5176    if (!e_grabinput_get(_e_comp_x_suspend_grabbed, 0, 0))
5177      {
5178         ecore_x_window_free(_e_comp_x_suspend_grabbed);
5179         _e_comp_x_suspend_grabbed = 0;
5180      }
5181 }
5182 
5183 static void
_e_comp_pointer_ungrab(void)5184 _e_comp_pointer_ungrab(void)
5185 {
5186    if (!_e_comp_x_suspend_grabbed) return;
5187    e_grabinput_release(_e_comp_x_suspend_grabbed, 0);
5188    ecore_x_window_free(_e_comp_x_suspend_grabbed);
5189    _e_comp_x_suspend_grabbed = 0;
5190 }
5191 
5192 static void
_e_comp_cb_pointer_suspend_resume_done(void * data,Evas_Object * obj,const char * emission,const char * source)5193 _e_comp_cb_pointer_suspend_resume_done(void *data, Evas_Object *obj, const char *emission, const char *source)
5194 {
5195    edje_object_signal_callback_del(obj, emission, source,
5196                                    _e_comp_cb_pointer_suspend_resume_done);
5197    if (!data)
5198      {
5199         _e_comp_pointer_ungrab();
5200         e_pointer_grab_set(e_comp->pointer, EINA_FALSE);
5201      }
5202 }
5203 
5204 EINTERN Eina_Bool
_e_comp_x_screensaver_on()5205 _e_comp_x_screensaver_on()
5206 {
5207    const char *s;
5208 
5209    if ((!e_comp->pointer) || (!e_comp->pointer->o_ptr)) return ECORE_CALLBACK_RENEW;
5210    s = edje_object_data_get(e_comp->pointer->o_ptr, "can_suspend");
5211 
5212    if ((s) && (atoi(s) == 1))
5213      {
5214         if (!e_desklock_state_get())
5215           {
5216              _e_comp_pointer_ungrab();
5217              e_pointer_grab_set(e_comp->pointer, EINA_FALSE);
5218              e_pointer_grab_set(e_comp->pointer, EINA_TRUE);
5219              _e_comp_pointer_grab();
5220              if (!_e_comp_x_suspend_grabbed) return ECORE_CALLBACK_RENEW;
5221           }
5222         edje_object_signal_callback_del(e_comp->pointer->o_ptr,
5223                                         "e,state,mouse,suspend,done", "e",
5224                                         _e_comp_cb_pointer_suspend_resume_done);
5225         edje_object_signal_callback_del(e_comp->pointer->o_ptr,
5226                                         "e,state,mouse,resume,done", "e",
5227                                         _e_comp_cb_pointer_suspend_resume_done);
5228         edje_object_signal_callback_add(e_comp->pointer->o_ptr,
5229                                         "e,state,mouse,suspend,done",
5230                                         "e",
5231                                         _e_comp_cb_pointer_suspend_resume_done,
5232                                         e_comp);
5233         edje_object_signal_emit(e_comp->pointer->o_ptr,
5234                                 "e,state,mouse,suspend", "e");
5235      }
5236    return ECORE_CALLBACK_RENEW;
5237 }
5238 
5239 EINTERN Eina_Bool
_e_comp_x_screensaver_off()5240 _e_comp_x_screensaver_off()
5241 {
5242    const char *s;
5243 
5244    _e_comp_pointer_ungrab();
5245    e_pointer_grab_set(e_comp->pointer, EINA_FALSE);
5246    if ((!e_comp->pointer) || (!e_comp->pointer->o_ptr)) return ECORE_CALLBACK_RENEW;
5247    s = edje_object_data_get(e_comp->pointer->o_ptr, "can_suspend");
5248 
5249    if ((s) && (atoi(s) == 1))
5250      {
5251         if (!e_desklock_state_get())
5252           {
5253              e_pointer_grab_set(e_comp->pointer, EINA_TRUE);
5254              _e_comp_pointer_grab();
5255              if (!_e_comp_x_suspend_grabbed) return ECORE_CALLBACK_RENEW;
5256           }
5257         edje_object_signal_callback_del(e_comp->pointer->o_ptr,
5258                                         "e,state,mouse,suspend,done", "e",
5259                                         _e_comp_cb_pointer_suspend_resume_done);
5260         edje_object_signal_callback_del(e_comp->pointer->o_ptr,
5261                                         "e,state,mouse,resume,done", "e",
5262                                         _e_comp_cb_pointer_suspend_resume_done);
5263         edje_object_signal_callback_add(e_comp->pointer->o_ptr,
5264                                         "e,state,mouse,resume,done",
5265                                         "e",
5266                                         _e_comp_cb_pointer_suspend_resume_done,
5267                                         NULL);
5268         edje_object_signal_emit(e_comp->pointer->o_ptr,
5269                                 "e,state,mouse,resume", "e");
5270      }
5271    return ECORE_CALLBACK_RENEW;
5272 }
5273 
5274 static Ecore_Timer *screensaver_eval_timer = NULL;
5275 static Ecore_Animator *screensaver_eval_animator = NULL;
5276 static Eina_Bool saver_on = EINA_FALSE;
5277 
5278 static Eina_Bool
_e_comp_x_screensaver_eval_cb(void * d EINA_UNUSED)5279 _e_comp_x_screensaver_eval_cb(void *d EINA_UNUSED)
5280 {
5281    E_FREE_FUNC(screensaver_eval_animator, ecore_animator_del);
5282    screensaver_eval_timer = NULL;
5283    e_screensaver_eval(saver_on);
5284    return EINA_FALSE;
5285 }
5286 
5287 static Eina_Bool
_e_comp_x_screensaver_pre_eval_cb(void * d EINA_UNUSED)5288 _e_comp_x_screensaver_pre_eval_cb(void *d EINA_UNUSED)
5289 {
5290    E_FREE_FUNC(screensaver_eval_timer, ecore_timer_del);
5291    screensaver_eval_animator = NULL;
5292    screensaver_eval_timer = ecore_timer_loop_add(0.3, _e_comp_x_screensaver_eval_cb, NULL);
5293    e_screensaver_eval(saver_on);
5294    return EINA_FALSE;
5295 }
5296 
5297 static Eina_Bool
_e_comp_x_screensaver_notify_cb(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Screensaver_Notify * ev)5298 _e_comp_x_screensaver_notify_cb(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Screensaver_Notify *ev)
5299 {
5300    if (e_screensaver_ignore_get()) return ECORE_CALLBACK_PASS_ON;
5301    if ((ev->on) && (!saver_on))
5302      {
5303         saver_on = EINA_TRUE;
5304         E_FREE_FUNC(screensaver_eval_timer, ecore_timer_del);
5305         E_FREE_FUNC(screensaver_eval_animator, ecore_animator_del);
5306         screensaver_eval_timer = ecore_timer_loop_add(0.3, _e_comp_x_screensaver_eval_cb, NULL);
5307      }
5308    else if ((!ev->on) && (saver_on))
5309      {
5310         saver_on = EINA_FALSE;
5311         E_FREE_FUNC(screensaver_eval_timer, ecore_timer_del);
5312         E_FREE_FUNC(screensaver_eval_animator, ecore_animator_del);
5313         screensaver_eval_animator = ecore_animator_add(_e_comp_x_screensaver_pre_eval_cb, NULL);
5314      }
5315    return ECORE_CALLBACK_PASS_ON;
5316 }
5317 
5318 static Eina_Bool
_e_comp_x_backlight_notify_cb(void * data EINA_UNUSED,int t EINA_UNUSED,Ecore_X_Event_Randr_Output_Property_Notify * ev)5319 _e_comp_x_backlight_notify_cb(void *data EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Randr_Output_Property_Notify *ev)
5320 {
5321    if (ev->property != backlight_atom) return ECORE_CALLBACK_RENEW;
5322    e_backlight_update();
5323    return ECORE_CALLBACK_RENEW;
5324 }
5325 
5326 static Eina_Bool
_e_comp_x_cb_frame_extents_request(void * data EINA_UNUSED,int ev_type EINA_UNUSED,Ecore_X_Event_Frame_Extents_Request * ev)5327 _e_comp_x_cb_frame_extents_request(void *data EINA_UNUSED, int ev_type EINA_UNUSED, Ecore_X_Event_Frame_Extents_Request *ev)
5328 {
5329    Ecore_X_Window_Type type;
5330    Ecore_X_MWM_Hint_Decor decor;
5331    Ecore_X_Window_State *state;
5332    Ecore_X_Window win;
5333    Frame_Extents *extents;
5334    const char *border, *sig, *key;
5335    int ok;
5336    unsigned int i, num;
5337 
5338    win = ecore_x_window_parent_get(ev->win);
5339    if (win != e_comp->root) return ECORE_CALLBACK_PASS_ON;
5340 
5341    /* TODO:
5342     * * We need to check if we remember this window, and border locking is set
5343     */
5344    border = "default";
5345    key = border;
5346    ok = ecore_x_mwm_hints_get(ev->win, NULL, &decor, NULL);
5347    if ((ok) &&
5348        (!(decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
5349        (!(decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
5350        (!(decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
5351      {
5352         border = "borderless";
5353         key = border;
5354      }
5355 
5356    ok = ecore_x_netwm_window_type_get(ev->win, &type);
5357    if ((ok) &&
5358        ((type == ECORE_X_WINDOW_TYPE_DESKTOP) ||
5359         (type == ECORE_X_WINDOW_TYPE_DOCK)))
5360      {
5361         border = "borderless";
5362         key = border;
5363      }
5364 
5365    sig = NULL;
5366    ecore_x_netwm_window_state_get(ev->win, &state, &num);
5367    if (state)
5368      {
5369         int maximized = 0;
5370 
5371         for (i = 0; i < num; i++)
5372           {
5373              switch (state[i])
5374                {
5375                 case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
5376                   maximized++;
5377                   break;
5378 
5379                 case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
5380                   maximized++;
5381                   break;
5382 
5383                 case ECORE_X_WINDOW_STATE_FULLSCREEN:
5384                   border = "borderless";
5385                   key = border;
5386                   break;
5387 
5388                 case ECORE_X_WINDOW_STATE_SHADED:
5389                 case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
5390                 case ECORE_X_WINDOW_STATE_SKIP_PAGER:
5391                 case ECORE_X_WINDOW_STATE_HIDDEN:
5392                 case ECORE_X_WINDOW_STATE_ICONIFIED:
5393                 case ECORE_X_WINDOW_STATE_MODAL:
5394                 case ECORE_X_WINDOW_STATE_STICKY:
5395                 case ECORE_X_WINDOW_STATE_ABOVE:
5396                 case ECORE_X_WINDOW_STATE_BELOW:
5397                 case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION:
5398                 case ECORE_X_WINDOW_STATE_UNKNOWN:
5399                   break;
5400                }
5401           }
5402         if ((maximized == 2) &&
5403             (e_config->maximize_policy == E_MAXIMIZE_FULLSCREEN))
5404           {
5405              sig = "ev,action,maximize,fullscreen";
5406              key = "maximize,fullscreen";
5407           }
5408         free(state);
5409      }
5410 
5411    extents = eina_hash_find(frame_extents, key);
5412    if (!extents)
5413      {
5414         Evas_Object *o;
5415         char buf[1024];
5416 
5417         extents = E_NEW(Frame_Extents, 1);
5418         if (!extents) return ECORE_CALLBACK_RENEW;
5419 
5420         o = edje_object_add(e_comp->evas);
5421         snprintf(buf, sizeof(buf), "ev/widgets/border/%s/border", border);
5422         ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
5423         if (ok)
5424           {
5425              Evas_Coord x, y, w, h;
5426 
5427              if (sig)
5428                {
5429                   edje_object_signal_emit(o, sig, "ev");
5430                   edje_object_message_signal_process(o);
5431                }
5432 
5433              evas_object_resize(o, 1000, 1000);
5434              edje_object_calc_force(o);
5435              edje_object_part_geometry_get(o, "ev.swallow.client",
5436                                            &x, &y, &w, &h);
5437              extents->l = x;
5438              extents->r = 1000 - (x + w);
5439              extents->t = y;
5440              extents->b = 1000 - (y + h);
5441           }
5442         else
5443           {
5444              extents->l = 0;
5445              extents->r = 0;
5446              extents->t = 0;
5447              extents->b = 0;
5448           }
5449         evas_object_del(o);
5450         eina_hash_add(frame_extents, key, extents);
5451      }
5452 
5453    if (extents)
5454      ecore_x_netwm_frame_size_set(ev->win, extents->l, extents->r, extents->t, extents->b);
5455 
5456    return ECORE_CALLBACK_RENEW;
5457 }
5458 
5459 static Eina_Bool
_e_comp_x_randr_change(void * data EINA_UNUSED,int ev_type EINA_UNUSED,void * event_info EINA_UNUSED)5460 _e_comp_x_randr_change(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event_info EINA_UNUSED)
5461 {
5462    E_Client *ec;
5463 
5464    ecore_x_netwm_desk_size_set(e_comp->root, e_comp->w, e_comp->h);
5465    E_CLIENT_FOREACH(ec)
5466      {
5467         if (!e_client_util_ignored_get(ec))
5468           _e_comp_x_client_zone_geometry_set(ec);
5469      }
5470    return ECORE_CALLBACK_RENEW;
5471 }
5472 
5473 static void
_e_comp_x_del(E_Comp * c)5474 _e_comp_x_del(E_Comp *c)
5475 {
5476    unsigned int i;
5477 
5478    if (!e_comp_wl)
5479      ecore_x_window_key_ungrab(c->root, "F", ECORE_EVENT_MODIFIER_SHIFT |
5480                                ECORE_EVENT_MODIFIER_CTRL |
5481                                ECORE_EVENT_MODIFIER_ALT, 0);
5482    if (ecore_x_display_get())
5483      {
5484         if (c->grabbed)
5485           {
5486              c->grabbed = 0;
5487              ecore_x_ungrab();
5488              ecore_x_sync();
5489           }
5490 
5491         if (restart)
5492           {
5493              Ecore_X_Atom a;
5494              Ecore_X_Window blackwin;
5495 
5496              a = ecore_x_atom_get("E_COMP_BLACK_WIN");
5497              blackwin = ecore_x_window_permanent_new(c->root, a);
5498              ecore_x_window_ignore_set(blackwin, 1);
5499              ecore_x_window_override_set(blackwin, EINA_TRUE);
5500              ecore_x_window_move_resize(blackwin, 0, 0, e_comp->w, e_comp->h);
5501              ecore_x_window_background_color_set(blackwin, 0, 0, 0);
5502              ecore_x_window_show(blackwin);
5503              ecore_x_window_prop_window_set(c->root, a, &blackwin, 1);
5504              ecore_x_sync();
5505           }
5506 
5507         for (i = e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); i <= e_comp_canvas_layer_map(E_LAYER_CLIENT_PRIO); i++)
5508           ecore_x_window_free(c->layers[i].win);
5509 
5510         ecore_x_composite_unredirect_subwindows
5511           (c->root, ECORE_X_COMPOSITE_UPDATE_MANUAL);
5512         if (c->block_win) ecore_x_window_free(c->block_win);
5513         ecore_x_composite_render_window_disable(c->win);
5514         e_alert_composite_win(c->root, 0);
5515 
5516         ecore_x_window_free(c->cm_selection);
5517         ecore_x_screen_is_composited_set(0, 0);
5518      }
5519 
5520    eina_list_free(c->x_comp_data->retry_clients);
5521    ecore_timer_del(c->x_comp_data->retry_timer);
5522    E_FREE_FUNC(mouse_in_job, ecore_job_del);
5523    E_FREE_FUNC(focus_job, ecore_job_del);
5524    E_FREE_FUNC(unfocus_job, ecore_job_del);
5525    free(c->x_comp_data);
5526    c->x_comp_data = e_comp_x = NULL;
5527    c->root = 0;
5528 }
5529 
5530 static void
_e_comp_x_manage_windows(void)5531 _e_comp_x_manage_windows(void)
5532 {
5533    Ecore_X_Window *windows;
5534    int wnum;
5535    int i;
5536    const char *atom_names[] =
5537    {
5538       "_XEMBED_INFO",
5539       "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
5540       "KWM_DOCKWINDOW"
5541    };
5542    Ecore_X_Atom atoms[3];
5543    Ecore_X_Atom atom_xmbed, atom_kde_netwm_systray, atom_kwm_dockwindow;
5544    int count;
5545 
5546    /* a manager is designated for each root. lets get all the windows in
5547       the managers root */
5548    windows = ecore_x_window_children_get(e_comp->root, &wnum);
5549    if (!windows) return;
5550 
5551    ecore_x_atoms_get(atom_names, 3, atoms);
5552    atom_xmbed = atoms[0];
5553    atom_kde_netwm_systray = atoms[1];
5554    atom_kwm_dockwindow = atoms[2];
5555    for (i = 0; i < wnum; i++)
5556      {
5557         unsigned int ret_val;
5558         unsigned char *data = NULL;
5559         int ret;
5560         E_Client *ec = NULL;
5561 
5562         if ((e_comp->win == windows[i]) || (e_comp->ee_win == windows[i]) ||
5563             (e_comp->root == windows[i]) || (e_comp->cm_selection == windows[i]))
5564           continue;
5565         if (_e_comp_x_client_find_by_window(windows[i]))
5566           continue;
5567         if (!ecore_x_window_prop_property_get(windows[i],
5568                                               atom_kde_netwm_systray,
5569                                               atom_xmbed, 32,
5570                                               &data, &count))
5571           data = NULL;
5572 
5573         if (!data)
5574           {
5575              if (!ecore_x_window_prop_property_get(windows[i],
5576                                                    atom_kwm_dockwindow,
5577                                                    atom_kwm_dockwindow, 32,
5578                                                    &data, &count))
5579                data = NULL;
5580           }
5581         if (data)
5582           {
5583              E_FREE(data);
5584              continue;
5585           }
5586         ret = ecore_x_window_prop_card32_get(windows[i],
5587                                              E_ATOM_MANAGED,
5588                                              &ret_val, 1);
5589 
5590         ec = _e_comp_x_client_new(windows[i], (ret > -1) && (ret_val == 1));
5591         if (ec && (!_e_comp_x_client_data_get(ec)->initial_attributes.visible))
5592           {
5593              DELD(ec, 3);
5594              E_FREE_FUNC(ec, e_object_del);
5595           }
5596         if (ec)
5597           {
5598              if (ec->override || (!ec->icccm.fetch.hints))
5599                {
5600                   _e_comp_x_client_evas_init(ec);
5601                   if (!ec->input_only)
5602                     _e_comp_x_client_damage_add(ec);
5603                   e_pixmap_usable_set(ec->pixmap, 1);
5604                   _e_comp_x_client_data_get(ec)->first_map = 1;
5605                   evas_object_geometry_set(ec->frame, ec->client.x, ec->client.y, ec->client.w, ec->client.h);
5606                }
5607              ec->ignore_first_unmap = 1;
5608              if (ec->override || (!ec->icccm.fetch.hints))
5609                evas_object_show(ec->frame);
5610              _e_comp_x_client_stack(ec);
5611           }
5612      }
5613    free(windows);
5614 }
5615 
5616 static void
_e_comp_x_bindings_grab_cb(void)5617 _e_comp_x_bindings_grab_cb(void)
5618 {
5619    Eina_List *l;
5620    E_Client *ec;
5621 
5622    EINA_LIST_FOREACH(e_comp->clients, l, ec)
5623      {
5624         if (e_client_util_ignored_get(ec)) continue;
5625         _e_comp_x_focus_init(ec);
5626         if (ec->focused)
5627           _e_comp_x_focus_setdown(ec);
5628         else
5629           {
5630              _e_comp_x_focus_setup(ec);
5631              e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, e_client_util_pwin_get(ec));
5632              e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, e_client_util_pwin_get(ec));
5633           }
5634      }
5635 }
5636 
5637 static void
_e_comp_x_bindings_ungrab_cb(void)5638 _e_comp_x_bindings_ungrab_cb(void)
5639 {
5640    Eina_List *l;
5641    E_Client *ec;
5642 
5643    EINA_LIST_FOREACH(e_comp->clients, l, ec)
5644      {
5645         Ecore_X_Window win;
5646 
5647         if (e_client_util_ignored_get(ec)) continue;
5648         win = e_client_util_win_get(ec);
5649         ecore_x_window_button_ungrab(win, 1, 0, 1);
5650         ecore_x_window_button_ungrab(win, 2, 0, 1);
5651         ecore_x_window_button_ungrab(win, 3, 0, 1);
5652         e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, e_client_util_pwin_get(ec));
5653         e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, e_client_util_pwin_get(ec));
5654         _e_comp_x_client_data_get(ec)->button_grabbed = 0;
5655      }
5656 }
5657 
5658 static void
_e_comp_x_desklock_hide(void)5659 _e_comp_x_desklock_hide(void)
5660 {
5661    e_comp_ungrab_input(1, 1);
5662 
5663    if (e_comp_x->lock_grab_break_wnd)
5664      ecore_x_window_show(e_comp_x->lock_grab_break_wnd);
5665    e_comp_x->lock_grab_break_wnd = 0;
5666    e_comp_override_del();
5667 }
5668 
5669 static Eina_Bool
_e_comp_x_desklock_show(void)5670 _e_comp_x_desklock_show(void)
5671 {
5672    if (!e_comp_grab_input(1, 1))
5673      {
5674         Ecore_X_Window *windows;
5675         int wnum, i;
5676 
5677         windows = ecore_x_window_children_get(e_comp->root, &wnum);
5678         if (!windows) goto fail;
5679         for (i = 0; i < wnum; i++)
5680           {
5681              Ecore_X_Window_Attributes att;
5682 
5683              memset(&att, 0, sizeof(Ecore_X_Window_Attributes));
5684              ecore_x_window_attributes_get(windows[i], &att);
5685              if (att.visible)
5686                {
5687                   ecore_x_window_hide(windows[i]);
5688                   if (e_comp_grab_input(1, 1))
5689                     {
5690                        e_comp_x->lock_grab_break_wnd = windows[i];
5691                        free(windows);
5692                        goto works;
5693                     }
5694                   ecore_x_window_show(windows[i]);
5695                }
5696           }
5697         free(windows);
5698      }
5699 works:
5700    e_comp_override_add();
5701 
5702    return EINA_TRUE;
5703 fail:
5704    /* everything failed - can't lock */
5705    e_util_dialog_show(_("Lock Failed"),
5706                       _("Locking the desktop failed because some application<ps/>"
5707                         "has grabbed either the keyboard or the mouse or both<ps/>"
5708                         "and their grab is unable to be broken."));
5709    return EINA_FALSE;
5710 }
5711 
5712 static Eina_Bool
_e_comp_x_setup(Ecore_X_Window root,int w,int h)5713 _e_comp_x_setup(Ecore_X_Window root, int w, int h)
5714 {
5715    Ecore_X_Window_Attributes att;
5716    Ecore_X_Atom a;
5717    Ecore_X_Window blackwin = 0;
5718    Eina_Bool res;
5719    unsigned int i;
5720 
5721    res = ecore_x_screen_is_composited(0);
5722    if (res)
5723      {
5724         ERR(_("Another compositor is already running on your display server."));
5725         return EINA_FALSE;
5726      }
5727    if (!ecore_x_window_manage(root)) return EINA_FALSE;
5728 
5729    a = ecore_x_atom_get("E_COMP_BLACK_WIN");
5730    if (ecore_x_window_prop_window_get(root, a, &blackwin, 1) == 1)
5731      {
5732         ecore_x_window_ignore_set(blackwin, 1);
5733      }
5734 
5735    e_comp_x = e_comp->x_comp_data = E_NEW(E_Comp_X_Data, 1);
5736    ecore_x_e_window_profile_supported_set(root, EINA_TRUE);
5737    e_comp->cm_selection = ecore_x_window_input_new(root, 0, 0, 1, 1);
5738    if (!e_comp->cm_selection) return EINA_FALSE;
5739    ecore_x_icccm_name_class_set(e_comp->cm_selection, "comp", "cm_selection");
5740    e_comp_ignore_win_add(E_PIXMAP_TYPE_X, e_comp->cm_selection);
5741    e_hints_init(root, e_comp->cm_selection);
5742    ecore_x_window_background_color_set(root, 0, 0, 0);
5743    ecore_x_screen_is_composited_set(0, e_comp->cm_selection);
5744    ecore_x_selection_owner_set(e_comp->cm_selection, ecore_x_atom_get("WM_S0"), ecore_x_current_time_get());
5745 
5746    e_comp->win = ecore_x_composite_render_window_enable(root);
5747    if (!e_comp->win)
5748      {
5749         ERR(_("Your display server does not support the compositor overlay window.\n"
5750               "This is needed for Enlightenment to function."));
5751         return EINA_FALSE;
5752      }
5753    e_comp->root = root;
5754 
5755    memset((&att), 0, sizeof(Ecore_X_Window_Attributes));
5756    ecore_x_window_attributes_get(e_comp->win, &att);
5757 
5758    if ((att.depth != 24) && (att.depth != 32))
5759      {
5760         /*
5761                   e_util_dialog_internal
5762                   (_("Compositor Error"), _("Your screen is not in 24/32bit display mode.<ps/>"
5763                   "This is required to be your default depth<ps/>"
5764                   "setting for the compositor to work properly."));
5765                   ecore_x_composite_render_window_disable(e_comp->win);
5766                   free(e_comp);
5767                   return NULL;
5768          */
5769      }
5770    e_alert_composite_win(root, e_comp->win);
5771 
5772    if (!e_comp->ee)
5773      {
5774         if (!e_comp_x_randr_canvas_new(e_comp->win, w, h))
5775           ecore_job_add(_e_comp_x_add_fail_job, NULL);
5776      }
5777 
5778    ecore_x_composite_redirect_subwindows(root, ECORE_X_COMPOSITE_UPDATE_MANUAL);
5779 
5780    ecore_evas_data_set(e_comp->ee, "comp", e_comp);
5781    e_comp->bindings_grab_cb = _e_comp_x_bindings_grab_cb;
5782    e_comp->bindings_ungrab_cb = _e_comp_x_bindings_ungrab_cb;
5783 
5784    if (e_comp->comp_type == E_PIXMAP_TYPE_NONE)
5785      {
5786         if (!e_comp_canvas_init(w, h)) return EINA_FALSE;
5787         ecore_x_window_key_grab(root, "F", ECORE_EVENT_MODIFIER_SHIFT |
5788                         ECORE_EVENT_MODIFIER_CTRL |
5789                         ECORE_EVENT_MODIFIER_ALT, 0);
5790      }
5791 
5792    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
5793      e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
5794    else
5795      e_grabinput_focus(e_comp->root, E_FOCUS_METHOD_PASSIVE);
5796 
5797    /* init layers */
5798    for (i = e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); i <= e_comp_canvas_layer_map(E_LAYER_CLIENT_PRIO); i++)
5799      {
5800         char buf[64];
5801         E_Client *ec;
5802 
5803         e_comp->layers[i].win = ecore_x_window_input_new(root, 0, 0, 1, 1);
5804         ecore_x_window_show(e_comp->layers[i].win);
5805         snprintf(buf, sizeof(buf), "%d", e_comp_canvas_layer_map_to(i));
5806         ecore_x_icccm_name_class_set(e_comp->layers[i].win, buf, "e_layer_win");
5807 
5808         if (i >= e_comp_canvas_layer_map(E_LAYER_CLIENT_ABOVE))
5809           ecore_x_window_raise(e_comp->layers[i].win);
5810         ec = _e_comp_x_client_new(e_comp->layers[i].win, 0);
5811         if (!ec) continue;
5812         evas_object_name_set(ec->frame, "layer_obj");
5813         ec->lock_client_stacking = 1;
5814         ec->internal = 1;
5815         ec->visible = 1;
5816         evas_object_del(e_comp->layers[i].obj);
5817         e_comp->layers[i].obj = ec->frame;
5818         evas_object_layer_set(ec->frame, e_comp_canvas_layer_map_to(i));
5819         evas_object_pass_events_set(ec->frame, 1);
5820         evas_object_show(ec->frame);
5821      }
5822    for (i = e_comp_canvas_layer_map(E_LAYER_CLIENT_NORMAL); i >= e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); i--)
5823      ecore_x_window_lower(e_comp->layers[i].win);
5824 
5825    ecore_evas_lower(e_comp->ee);
5826    if (e_comp->comp_type == E_PIXMAP_TYPE_NONE)
5827      {
5828         e_comp->pointer = e_pointer_window_new(e_comp->root, 0);
5829         e_comp->pointer->color = ecore_x_cursor_color_supported_get();
5830         e_pointer_type_push(e_comp->pointer, e_comp->pointer, "default");
5831         ecore_x_icccm_state_set(ecore_evas_window_get(e_comp->ee), ECORE_X_WINDOW_STATE_HINT_NORMAL);
5832         e_startup();
5833      }
5834    else
5835      e_pointer_window_add(e_comp->pointer, e_comp->root);
5836    _e_comp_x_manage_windows();
5837 
5838    if (blackwin)
5839      {
5840         ecore_x_window_free(blackwin);
5841         ecore_x_window_prop_property_del(root, a);
5842         ecore_x_window_ignore_set(blackwin, 0);
5843      }
5844 
5845    return !!e_comp->canvas->resize_object;
5846 }
5847 
5848 static Eina_Bool
_e_comp_x_screens_setup(void)5849 _e_comp_x_screens_setup(void)
5850 {
5851    Ecore_X_Window root;
5852    int rw, rh;
5853    Eina_Bool ret;
5854 
5855    if (e_comp->comp_type == E_PIXMAP_TYPE_NONE)
5856      {
5857         e_comp_x_randr_screen_iface_set();
5858         if (!e_randr2_init()) return 0;
5859      }
5860    root = ecore_x_window_root_first_get();
5861    if (!root)
5862      {
5863         e_error_message_show("X reports there are no root windows!\n");
5864         return 0;
5865      }
5866    ecore_x_window_size_get(root, &rw, &rh);
5867    if (e_comp->comp_type == E_PIXMAP_TYPE_NONE)
5868      e_randr2_screens_setup(rw, rh);
5869    ret = _e_comp_x_setup(root, rw, rh);
5870    if (ret) return EINA_TRUE;
5871    e_randr2_shutdown();
5872    e_xinerama_screens_set(NULL);
5873    e_comp->screen = NULL;
5874    return EINA_FALSE;
5875 }
5876 
5877 E_API Eina_Bool
e_comp_x_init(void)5878 e_comp_x_init(void)
5879 {
5880    Eina_List *h = NULL;
5881    if (!ecore_x_init(NULL))
5882      {
5883         fprintf(stderr, _("Enlightenment cannot initialize X Connection...\n"));
5884         return EINA_FALSE;
5885      }
5886 
5887    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
5888      ecore_x_io_error_handler_set(_e_main_cb_x_fatal, NULL);
5889 
5890    if (!ecore_x_composite_query())
5891      {
5892         _e_comp_x_print_win(0);
5893         ecore_x_shutdown();
5894         e_error_message_show
5895           (_("Your display server does not support XComposite, "
5896              "or Ecore-X was built without XComposite support. "
5897              "Note that for composite support you will also need "
5898              "XRender and XFixes support in X11 and Ecore."));
5899         return EINA_FALSE;
5900      }
5901    if (!ecore_x_damage_query())
5902      {
5903         e_error_message_show
5904           (_("Your display server does not support XDamage "
5905              "or Ecore was built without XDamage support."));
5906         return EINA_FALSE;
5907      }
5908    if (!e_atoms_init()) return 0;
5909 
5910    clients_win_hash = eina_hash_int32_new(NULL);
5911    damages_hash = eina_hash_int32_new(NULL);
5912    alarm_hash = eina_hash_int32_new(NULL);
5913    dead_wins = eina_hash_int32_new(NULL);
5914    pending_configures = eina_hash_int32_new(NULL);
5915    frame_extents = eina_hash_string_superfast_new(free);
5916 
5917    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_DESK_SET, _e_comp_x_hook_client_desk_set, NULL));
5918    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_RESIZE_BEGIN, _e_comp_x_hook_client_resize_begin, NULL));
5919    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_RESIZE_END, _e_comp_x_hook_client_resize_end, NULL));
5920    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_MOVE_BEGIN, _e_comp_x_hook_client_move_begin, NULL));
5921    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_MOVE_END, _e_comp_x_hook_client_move_end, NULL));
5922    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_DEL, _e_comp_x_hook_client_del, NULL));
5923    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_NEW_CLIENT, _e_comp_x_hook_client_new, NULL));
5924    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_EVAL_FETCH, _e_comp_x_hook_client_fetch, NULL));
5925    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_EVAL_PRE_FRAME_ASSIGN, _e_comp_x_hook_client_pre_frame_assign, NULL));
5926    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_UNREDIRECT, _e_comp_x_hook_client_unredirect, NULL));
5927    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_REDIRECT, _e_comp_x_hook_client_redirect, NULL));
5928    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_EVAL_POST_NEW_CLIENT, _e_comp_x_hook_client_post_new_client, NULL));
5929    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_FOCUS_SET, _e_comp_x_hook_client_focus_set, NULL));
5930    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_FOCUS_UNSET, _e_comp_x_hook_client_focus_unset, NULL));
5931    h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_EVAL_END, _e_comp_x_hook_client_eval_end, NULL));
5932 
5933    if (!_e_comp_x_screens_setup())
5934      {
5935         e_atoms_shutdown();
5936         E_FREE_LIST(h, e_client_hook_del);
5937         E_FREE_FUNC(clients_win_hash, eina_hash_free);
5938         E_FREE_FUNC(damages_hash, eina_hash_free);
5939         E_FREE_FUNC(alarm_hash, eina_hash_free);
5940         E_FREE_FUNC(frame_extents, eina_hash_free);
5941         return 0;
5942      }
5943 
5944    E_LIST_HANDLER_APPEND(handlers, E_EVENT_COMP_OBJECT_ADD, _e_comp_x_object_add, NULL);
5945 
5946    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_DESTROY, _e_comp_x_destroy, NULL);
5947    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_SHOW, _e_comp_x_show, NULL);
5948    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_SHOW_REQUEST, _e_comp_x_show_request, NULL);
5949    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_RESIZE_REQUEST, _e_comp_x_resize_request, NULL);
5950    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_HIDE, _e_comp_x_hide, NULL);
5951    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_REPARENT, _e_comp_x_reparent, NULL);
5952    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_CONFIGURE, _e_comp_x_configure, NULL);
5953    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST, _e_comp_x_configure_request, NULL);
5954    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_STATE_REQUEST, _e_comp_x_state_request, NULL);
5955    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_STACK, _e_comp_x_stack, NULL);
5956    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_STACK_REQUEST, _e_comp_x_stack_request, NULL);
5957    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_CLIENT_MESSAGE, _e_comp_x_message, NULL);
5958    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_PROPERTY, _e_comp_x_property, NULL);
5959    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_SHAPE, _e_comp_x_shape, NULL);
5960    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_DAMAGE_NOTIFY, _e_comp_x_damage, NULL);
5961    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_DAMAGE, _e_comp_x_damage_win, NULL);
5962 
5963    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_MAPPING_CHANGE, _e_comp_x_mapping_change, NULL);
5964 
5965    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_FOCUS_IN, _e_comp_x_focus_in, NULL);
5966    if (e_comp->comp_type != E_PIXMAP_TYPE_WL)
5967      E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_FOCUS_OUT, _e_comp_x_focus_out, NULL);
5968 
5969    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST,
5970                          _e_comp_x_move_resize_request, NULL);
5971    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_DESKTOP_CHANGE,
5972                          _e_comp_x_desktop_change, NULL);
5973    if (e_comp->comp_type != E_PIXMAP_TYPE_WL)
5974      E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_SYNC_ALARM,
5975                            _e_comp_x_sync_alarm, NULL);
5976 
5977    E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN,
5978                          _e_comp_x_mouse_down, NULL);
5979    E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_UP,
5980                          _e_comp_x_mouse_up, NULL);
5981    E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_WHEEL,
5982                          _e_comp_x_mouse_wheel, NULL);
5983    E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_MOVE,
5984                          _e_comp_x_mouse_move, NULL);
5985    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_MOUSE_IN,
5986                          _e_comp_x_mouse_in, NULL);
5987    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_MOUSE_OUT,
5988                          _e_comp_x_mouse_out, NULL);
5989 
5990    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ZONE_SET,
5991                          _e_comp_x_client_zone_set, NULL);
5992    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_PROPERTY,
5993                          _e_comp_x_client_property, NULL);
5994 
5995    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_FRAME_EXTENTS_REQUEST,
5996                          _e_comp_x_cb_frame_extents_request, NULL);
5997    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_PING,
5998                          _e_comp_x_cb_ping, NULL);
5999    E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY, _e_comp_x_backlight_notify_cb, NULL);
6000    if (ecore_x_randr_version_get() >= RANDR_VERSION_1_3)
6001      backlight_atom = ecore_x_atom_get("Backlight");
6002 
6003    if (!backlight_atom)
6004      backlight_atom = ecore_x_atom_get("BACKLIGHT");
6005 
6006    ecore_x_passive_grab_replay_func_set(_e_comp_x_grab_replay, NULL);
6007 
6008    if (!e_xsettings_init())
6009      e_error_message_show(_("Enlightenment cannot initialize the XSettings system.\n"));
6010    E_LIST_HANDLER_APPEND(handlers, E_EVENT_RANDR_CHANGE, _e_comp_x_randr_change, NULL);
6011 
6012    ecore_x_sync();
6013    _x_idle_flush = ecore_idle_enterer_add(_e_comp_x_flusher, NULL);
6014 
6015    if (e_comp->comp_type != E_PIXMAP_TYPE_WL)
6016      {
6017         ecore_x_screensaver_event_listen_set(1);
6018         E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREENSAVER_ON, _e_comp_x_screensaver_on, NULL);
6019         E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREENSAVER_OFF, _e_comp_x_screensaver_off, NULL);
6020         E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_SCREENSAVER_NOTIFY, _e_comp_x_screensaver_notify_cb, NULL);
6021         ecore_x_screensaver_custom_blanking_enable();
6022 
6023         e_screensaver_attrs_set(ecore_x_screensaver_timeout_get(),
6024                                 ecore_x_screensaver_blank_get(),
6025                                 ecore_x_screensaver_expose_get());
6026         e_desklock_show_hook_add(_e_comp_x_desklock_show);
6027         e_desklock_hide_hook_add(_e_comp_x_desklock_hide);
6028         int timeout = e_screensaver_timeout_get(EINA_TRUE);
6029         ecore_x_screensaver_set(timeout + 10,
6030                                 0,
6031                                 !e_config->screensaver_blanking,
6032                                 !e_config->screensaver_expose);
6033         ecore_x_screensaver_set(timeout,
6034                                 0,
6035                                 e_config->screensaver_blanking,
6036                                 e_config->screensaver_expose);
6037      }
6038    else
6039      e_dnd_init();
6040    eina_list_free(h);
6041    return EINA_TRUE;
6042 }
6043 
6044 E_API void
e_comp_x_shutdown(void)6045 e_comp_x_shutdown(void)
6046 {
6047    _e_comp_x_del(e_comp);
6048    E_FREE_LIST(handlers, ecore_event_handler_del);
6049    E_FREE_FUNC(clients_win_hash, eina_hash_free);
6050    E_FREE_FUNC(damages_hash, eina_hash_free);
6051    E_FREE_FUNC(alarm_hash, eina_hash_free);
6052    E_FREE_FUNC(pending_configures, eina_hash_free);
6053    E_FREE_FUNC(frame_extents, eina_hash_free);
6054    E_FREE_FUNC(mouse_in_fix_check_timer, ecore_timer_del);
6055    e_xsettings_shutdown();
6056    if (x_fatal) return;
6057    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
6058      ecore_x_screensaver_custom_blanking_disable();
6059    e_atoms_shutdown();
6060    /* ecore_x_ungrab(); */
6061    ecore_x_focus_reset();
6062    ecore_x_events_allow_all();
6063    ecore_x_shutdown();
6064 }
6065 
6066 EINTERN void
e_comp_x_nocomp_end(void)6067 e_comp_x_nocomp_end(void)
6068 {
6069    e_comp->nocomp = 0;
6070    ecore_x_window_show(e_comp->win);
6071    ecore_x_composite_redirect_subwindows(e_comp->root, ECORE_X_COMPOSITE_UPDATE_MANUAL);
6072    _e_comp_x_focus_check();
6073 }
6074 
6075 #ifdef HAVE_WAYLAND
6076 EINTERN void
e_comp_x_xwayland_client_setup(E_Client * ec,E_Client * wc)6077 e_comp_x_xwayland_client_setup(E_Client *ec, E_Client *wc)
6078 {
6079    Ecore_X_Window win, pwin;
6080    E_Comp_X_Client_Data *cd;
6081    Eina_Bool placed;
6082 
6083    win = e_client_util_win_get(ec);
6084    pwin = e_client_util_pwin_get(ec);
6085    cd = ec->comp_data;
6086    e_comp_wl_client_xwayland_setup(wc, cd, e_pixmap_ref(ec->pixmap));
6087    eina_hash_del(damages_hash, &cd->damage, ec);
6088    ecore_x_damage_free(cd->damage);
6089    E_FREE_FUNC(cd->first_draw_delay, ecore_timer_del);
6090    cd->damage = 0;
6091    ec->comp_data = NULL;
6092    cd->evas_init = 0;
6093    _e_comp_x_client_evas_init(wc);
6094    if (!e_comp_object_frame_exists(ec->frame))
6095      {
6096         int l, r, t, b;
6097 
6098         e_comp_object_frame_geometry_get(ec->frame, &l, &r, &t, &b);
6099         e_comp_object_frame_geometry_set(wc->frame, l, r, t, b);
6100      }
6101    wc->borderless = ec->borderless;
6102    wc->border.changed = 1;
6103    EC_CHANGED(wc);
6104    wc->depth = ec->depth;
6105    wc->override = ec->override;
6106    placed = ec->placed;
6107    wc->input_only = ec->input_only;
6108    wc->border_size = ec->border_size;
6109    wc->no_shape_cut = 0;
6110    memcpy(&wc->icccm, &ec->icccm, sizeof(ec->icccm));
6111    memcpy(&wc->netwm, &ec->netwm, sizeof(ec->netwm));
6112    memcpy(&wc->e, &ec->e, sizeof(ec->e));
6113    wc->new_client = !wc->override;
6114    if (wc->new_client)
6115      e_comp->new_clients++;
6116 
6117    eina_hash_set(clients_win_hash, &win, wc);
6118    if (pwin)
6119      eina_hash_set(clients_win_hash, &pwin, wc);
6120    wc->visible = 1;
6121    if (wc->ignored)
6122      e_client_unignore(wc);
6123    if (ec->override)
6124      e_client_focus_stack_set(eina_list_remove(e_client_focus_stack_get(), wc));
6125    evas_object_name_set(wc->frame, evas_object_name_get(ec->frame));
6126    wc->x = ec->x, wc->y = ec->y;
6127    wc->client.x = ec->client.x, wc->client.y = ec->client.y;
6128    wc->w = ec->w, wc->h = ec->h;
6129    wc->client.w = ec->client.w, wc->client.h = ec->client.h;
6130    wc->layer = ec->layer;
6131    wc->netwm.sync.request = 1;
6132    evas_object_layer_set(wc->frame, evas_object_layer_get(ec->frame));
6133    evas_object_geometry_set(wc->frame, ec->x, ec->y, ec->w, ec->h);
6134    evas_object_show(wc->frame);
6135    e_pixmap_alias(wc->pixmap, E_PIXMAP_TYPE_X, e_pixmap_window_get(ec->pixmap));
6136    e_object_del(E_OBJECT(ec));
6137    e_hints_window_visible_set(wc);
6138    _e_comp_x_client_stack(wc);
6139    wc->placed = placed;
6140    if (!placed) wc->changes.pos = 0;
6141 }
6142 #endif
6143 
6144 E_API inline E_Pixmap *
e_comp_x_client_pixmap_get(const E_Client * ec)6145 e_comp_x_client_pixmap_get(const E_Client *ec)
6146 {
6147 #ifdef HAVE_WAYLAND
6148    if ((!e_pixmap_is_x(ec->pixmap)) && e_client_has_xwindow(ec))
6149      return e_comp_wl_client_xwayland_pixmap(ec);
6150 #endif
6151    return ec->pixmap;
6152 }
6153