2e98272b08f2aa6e38ab62cbc4e125e35da82c8b
[framework/uifw/e17.git] / src / bin / e_border.c
1 #include "e.h"
2
3 //#define INOUTDEBUG_MOUSE 1
4 //#define INOUTDEBUG_FOCUS 1
5
6 /* These are compatible with netwm */
7 #define RESIZE_TL   0
8 #define RESIZE_T    1
9 #define RESIZE_TR   2
10 #define RESIZE_R    3
11 #define RESIZE_BR   4
12 #define RESIZE_B    5
13 #define RESIZE_BL   6
14 #define RESIZE_L    7
15 #define MOVE        8
16 #define RESIZE_NONE 11
17
18 /* local subsystem functions */
19 static void _e_border_free(E_Border *bd);
20 static void _e_border_del(E_Border *bd);
21
22 #ifdef PRINT_LOTS_OF_DEBUG
23 #define E_PRINT_BORDER_INFO(X) \
24   _e_border_print(X, __PRETTY_FUNC__)
25
26 static void _e_border_print(E_Border   *bd,
27                             const char *func);
28 #endif
29
30 /* FIXME: these likely belong in a separate icccm/client handler */
31 /* and the border needs to become a dumb object that just does what its */
32 /* told to do */
33 static Eina_Bool _e_border_cb_window_show_request(void *data,
34                                                   int   ev_type,
35                                                   void *ev);
36 static Eina_Bool _e_border_cb_window_destroy(void *data,
37                                              int   ev_type,
38                                              void *ev);
39 static Eina_Bool _e_border_cb_window_hide(void *data,
40                                           int   ev_type,
41                                           void *ev);
42 static Eina_Bool _e_border_cb_window_reparent(void *data,
43                                               int   ev_type,
44                                               void *ev);
45 static Eina_Bool _e_border_cb_window_configure_request(void *data,
46                                                        int   ev_type,
47                                                        void *ev);
48 static Eina_Bool _e_border_cb_window_resize_request(void *data,
49                                                     int   ev_type,
50                                                     void *ev);
51 static Eina_Bool _e_border_cb_window_gravity(void *data,
52                                              int   ev_type,
53                                              void *ev);
54 static Eina_Bool _e_border_cb_window_stack_request(void *data,
55                                                    int   ev_type,
56                                                    void *ev);
57 static Eina_Bool _e_border_cb_window_property(void *data,
58                                               int   ev_type,
59                                               void *ev);
60 static Eina_Bool _e_border_cb_window_colormap(void *data,
61                                               int   ev_type,
62                                               void *ev);
63 static Eina_Bool _e_border_cb_window_shape(void *data,
64                                            int   ev_type,
65                                            void *ev);
66 static Eina_Bool _e_border_cb_window_focus_in(void *data,
67                                               int   ev_type,
68                                               void *ev);
69 static Eina_Bool _e_border_cb_window_focus_out(void *data,
70                                                int   ev_type,
71                                                void *ev);
72 static Eina_Bool _e_border_cb_client_message(void *data,
73                                              int   ev_type,
74                                              void *ev);
75
76 static Eina_Bool _e_border_cb_window_state_request(void *data,
77                                                    int   ev_type,
78                                                    void *ev);
79 static Eina_Bool _e_border_cb_window_move_resize_request(void *data,
80                                                          int   ev_type,
81                                                          void *ev);
82 static Eina_Bool _e_border_cb_desktop_change(void *data,
83                                              int   ev_type,
84                                              void *ev);
85 static Eina_Bool _e_border_cb_sync_alarm(void *data,
86                                          int   ev_type,
87                                          void *ev);
88 static Eina_Bool _e_border_cb_efreet_cache_update(void *data,
89                                                   int   ev_type,
90                                                   void *ev);
91 static Eina_Bool _e_border_cb_config_icon_theme(void *data,
92                                                 int   ev_type,
93                                                 void *ev);
94
95 static Eina_Bool _e_border_cb_pointer_warp(void *data,
96                                            int   ev_type,
97                                            void *ev);
98 static void _e_border_cb_signal_bind(void        *data,
99                                      Evas_Object *obj,
100                                      const char  *emission,
101                                      const char  *source);
102 static Eina_Bool _e_border_cb_mouse_in(void *data,
103                                        int   type,
104                                        void *event);
105 static Eina_Bool _e_border_cb_mouse_out(void *data,
106                                         int   type,
107                                         void *event);
108 static Eina_Bool _e_border_cb_mouse_wheel(void *data,
109                                           int   type,
110                                           void *event);
111 static Eina_Bool _e_border_cb_mouse_down(void *data,
112                                          int   type,
113                                          void *event);
114 static Eina_Bool _e_border_cb_mouse_up(void *data,
115                                        int   type,
116                                        void *event);
117 static Eina_Bool _e_border_cb_mouse_move(void *data,
118                                          int   type,
119                                          void *event);
120 static Eina_Bool _e_border_cb_grab_replay(void *data,
121                                           int   type,
122                                           void *event);
123 static void _e_border_cb_drag_finished(E_Drag *drag,
124                                        int     dropped);
125
126 static void      _e_border_eval(E_Border *bd);
127 static void      _e_border_eval0(E_Border *bd);
128 static void      _e_border_container_layout_hook(E_Container *con);
129
130 static void      _e_border_moveinfo_gather(E_Border   *bd,
131                                            const char *source);
132 static void      _e_border_resize_handle(E_Border *bd);
133
134 static Eina_Bool _e_border_shade_animator(void *data);
135
136 static void      _e_border_event_border_add_free(void *data,
137                                                  void *ev);
138 static void      _e_border_event_border_remove_free(void *data,
139                                                     void *ev);
140 static void      _e_border_event_border_zone_set_free(void *data,
141                                                       void *ev);
142 static void      _e_border_event_border_desk_set_free(void *data,
143                                                       void *ev);
144 static void      _e_border_event_border_stack_free(void *data,
145                                                    void *ev);
146 static void      _e_border_event_border_icon_change_free(void *data,
147                                                          void *ev);
148 static void      _e_border_event_border_urgent_change_free(void *data,
149                                                            void *ev);
150 static void      _e_border_event_border_focus_in_free(void *data,
151                                                       void *ev);
152 static void      _e_border_event_border_focus_out_free(void *data,
153                                                        void *ev);
154 static void      _e_border_event_border_resize_free(void *data,
155                                                     void *ev);
156 static void      _e_border_event_border_move_free(void *data,
157                                                   void *ev);
158 static void      _e_border_event_border_show_free(void *data,
159                                                   void *ev);
160 static void      _e_border_event_border_hide_free(void *data,
161                                                   void *ev);
162 static void      _e_border_event_border_iconify_free(void *data,
163                                                      void *ev);
164 static void      _e_border_event_border_uniconify_free(void *data,
165                                                        void *ev);
166 static void      _e_border_event_border_stick_free(void *data,
167                                                    void *ev);
168 static void      _e_border_event_border_unstick_free(void *data,
169                                                      void *ev);
170 static void      _e_border_event_border_property_free(void *data,
171                                                       void *ev);
172 static void      _e_border_event_border_fullscreen_free(void *data,
173                                                         void *ev);
174 static void      _e_border_event_border_unfullscreen_free(void *data,
175                                                           void *ev);
176
177 static void      _e_border_zone_update(E_Border *bd);
178
179 static int       _e_border_resize_begin(E_Border *bd);
180 static int       _e_border_resize_end(E_Border *bd);
181 static void      _e_border_resize_update(E_Border *bd);
182
183 static int       _e_border_move_begin(E_Border *bd);
184 static int       _e_border_move_end(E_Border *bd);
185 static void      _e_border_move_update(E_Border *bd);
186
187 static Eina_Bool _e_border_cb_ping_poller(void *data);
188 static Eina_Bool _e_border_cb_kill_timer(void *data);
189
190 static void      _e_border_pointer_resize_begin(E_Border *bd);
191 static void      _e_border_pointer_resize_end(E_Border *bd);
192 static void      _e_border_pointer_move_begin(E_Border *bd);
193 static void      _e_border_pointer_move_end(E_Border *bd);
194
195 static void      _e_border_hook_call(E_Border_Hook_Point hookpoint,
196                                      void               *bd);
197
198 static void _e_border_client_move_resize_send(E_Border *bd);
199
200 static void _e_border_frame_replace(E_Border *bd,
201                                     Eina_Bool argb);
202
203 static void _e_border_shape_input_rectangle_set(E_Border* bd);
204 static void _e_border_show(E_Border *bd);
205 static void _e_border_hide(E_Border *bd);
206
207
208 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
209 static void _e_border_latest_stacked_focus (E_Border* bd);
210 static void _e_border_check_stack (E_Border *bd);
211 static void _e_border_focus_top_stack_set (E_Border* bd);
212 #endif
213
214 /* local subsystem globals */
215 static Eina_List *handlers = NULL;
216 static Eina_List *borders = NULL;
217 static Eina_Hash *borders_hash = NULL;
218 static E_Border *focused = NULL;
219 static Eina_List *focus_next = NULL;
220 static Ecore_X_Time focus_time = 0;
221
222 static E_Border *resize = NULL;
223 static E_Border *move = NULL;
224 static E_Drag *drag_border = NULL;
225
226 static int grabbed = 0;
227
228 static Eina_List *focus_stack = NULL;
229 static Eina_List *raise_stack = NULL;
230
231 static Ecore_X_Randr_Screen_Size screen_size = { -1, -1 };
232 static int screen_size_index = -1;
233
234 static int focus_track_frozen = 0;
235
236 static int warp_to = 0;
237 static int warp_to_x = 0;
238 static int warp_to_y = 0;
239 static int warp_x = 0;
240 static int warp_y = 0;
241 static Ecore_X_Window warp_to_win;
242 static Ecore_Timer *warp_timer = NULL;
243
244 EAPI int E_EVENT_BORDER_ADD = 0;
245 EAPI int E_EVENT_BORDER_REMOVE = 0;
246 EAPI int E_EVENT_BORDER_ZONE_SET = 0;
247 EAPI int E_EVENT_BORDER_DESK_SET = 0;
248 EAPI int E_EVENT_BORDER_RESIZE = 0;
249 EAPI int E_EVENT_BORDER_MOVE = 0;
250 EAPI int E_EVENT_BORDER_SHOW = 0;
251 EAPI int E_EVENT_BORDER_HIDE = 0;
252 EAPI int E_EVENT_BORDER_ICONIFY = 0;
253 EAPI int E_EVENT_BORDER_UNICONIFY = 0;
254 EAPI int E_EVENT_BORDER_STICK = 0;
255 EAPI int E_EVENT_BORDER_UNSTICK = 0;
256 EAPI int E_EVENT_BORDER_STACK = 0;
257 EAPI int E_EVENT_BORDER_ICON_CHANGE = 0;
258 EAPI int E_EVENT_BORDER_URGENT_CHANGE = 0;
259 EAPI int E_EVENT_BORDER_FOCUS_IN = 0;
260 EAPI int E_EVENT_BORDER_FOCUS_OUT = 0;
261 EAPI int E_EVENT_BORDER_PROPERTY = 0;
262 EAPI int E_EVENT_BORDER_FULLSCREEN = 0;
263 EAPI int E_EVENT_BORDER_UNFULLSCREEN = 0;
264
265 #define GRAV_SET(bd, grav)                                \
266   ecore_x_window_gravity_set(bd->bg_win, grav);           \
267   ecore_x_window_gravity_set(bd->client.shell_win, grav); \
268   ecore_x_window_gravity_set(bd->client.win, grav);
269
270 /* externally accessible functions */
271 EINTERN int
272 e_border_init(void)
273 {
274    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW_REQUEST, _e_border_cb_window_show_request, NULL));
275    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _e_border_cb_window_destroy, NULL));
276    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, _e_border_cb_window_hide, NULL));
277    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_REPARENT, _e_border_cb_window_reparent, NULL));
278    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST, _e_border_cb_window_configure_request, NULL));
279    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_RESIZE_REQUEST, _e_border_cb_window_resize_request, NULL));
280    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_GRAVITY, _e_border_cb_window_gravity, NULL));
281    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_STACK_REQUEST, _e_border_cb_window_stack_request, NULL));
282    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, _e_border_cb_window_property, NULL));
283    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_COLORMAP, _e_border_cb_window_colormap, NULL));
284    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHAPE, _e_border_cb_window_shape, NULL));
285    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, _e_border_cb_window_focus_in, NULL));
286    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, _e_border_cb_window_focus_out, NULL));
287    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _e_border_cb_client_message, NULL));
288    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, _e_border_cb_window_state_request, NULL));
289    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST, _e_border_cb_window_move_resize_request, NULL));
290    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_DESKTOP_CHANGE, _e_border_cb_desktop_change, NULL));
291    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_SYNC_ALARM, _e_border_cb_sync_alarm, NULL));
292
293    ecore_x_passive_grab_replay_func_set(_e_border_cb_grab_replay, NULL);
294
295    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_POINTER_WARP, _e_border_cb_pointer_warp, NULL));
296    handlers = eina_list_append(handlers, ecore_event_handler_add(EFREET_EVENT_DESKTOP_CACHE_UPDATE, _e_border_cb_efreet_cache_update, NULL));
297    handlers = eina_list_append(handlers, ecore_event_handler_add(EFREET_EVENT_ICON_CACHE_UPDATE, _e_border_cb_efreet_cache_update, NULL));
298    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_CONFIG_ICON_THEME, _e_border_cb_config_icon_theme, NULL));
299
300    if (!borders_hash) borders_hash = eina_hash_string_superfast_new(NULL);
301
302    E_EVENT_BORDER_ADD = ecore_event_type_new();
303    E_EVENT_BORDER_REMOVE = ecore_event_type_new();
304    E_EVENT_BORDER_DESK_SET = ecore_event_type_new();
305    E_EVENT_BORDER_ZONE_SET = ecore_event_type_new();
306    E_EVENT_BORDER_RESIZE = ecore_event_type_new();
307    E_EVENT_BORDER_MOVE = ecore_event_type_new();
308    E_EVENT_BORDER_SHOW = ecore_event_type_new();
309    E_EVENT_BORDER_HIDE = ecore_event_type_new();
310    E_EVENT_BORDER_ICONIFY = ecore_event_type_new();
311    E_EVENT_BORDER_UNICONIFY = ecore_event_type_new();
312    E_EVENT_BORDER_STICK = ecore_event_type_new();
313    E_EVENT_BORDER_UNSTICK = ecore_event_type_new();
314    E_EVENT_BORDER_STACK = ecore_event_type_new();
315    E_EVENT_BORDER_ICON_CHANGE = ecore_event_type_new();
316    E_EVENT_BORDER_URGENT_CHANGE = ecore_event_type_new();
317    E_EVENT_BORDER_FOCUS_IN = ecore_event_type_new();
318    E_EVENT_BORDER_FOCUS_OUT = ecore_event_type_new();
319    E_EVENT_BORDER_PROPERTY = ecore_event_type_new();
320    E_EVENT_BORDER_FULLSCREEN = ecore_event_type_new();
321    E_EVENT_BORDER_UNFULLSCREEN = ecore_event_type_new();
322
323 //   e_init_undone();
324
325    return 1;
326 }
327
328 EINTERN int
329 e_border_shutdown(void)
330 {
331    E_FREE_LIST(handlers, ecore_event_handler_del);
332
333    if (borders_hash) eina_hash_free(borders_hash);
334    borders_hash = NULL;
335
336    return 1;
337 }
338
339 EAPI E_Border *
340 e_border_new(E_Container   *con,
341              Ecore_X_Window win,
342              int            first_map,
343              int            internal)
344 {
345    E_Border *bd, *bd2;
346    Ecore_X_Window_Attributes *att;
347    unsigned int managed, desk[2];
348    int deskx, desky;
349
350    bd = E_OBJECT_ALLOC(E_Border, E_BORDER_TYPE, _e_border_free);
351    if (!bd) return NULL;
352    ecore_x_window_shadow_tree_flush();
353    e_object_del_func_set(E_OBJECT(bd), E_OBJECT_CLEANUP_FUNC(_e_border_del));
354
355    bd->w = 1;
356    bd->h = 1;
357    /* FIXME: ewww - round trip */
358    bd->client.argb = ecore_x_window_argb_get(win);
359    if (bd->client.argb)
360      bd->win = ecore_x_window_manager_argb_new(con->win, 0, 0, bd->w, bd->h);
361    else
362      {
363         bd->win = ecore_x_window_override_new(con->win, 0, 0, bd->w, bd->h);
364         ecore_x_window_shape_events_select(bd->win, 1);
365      }
366    e_bindings_mouse_grab(E_BINDING_CONTEXT_BORDER, bd->win);
367    e_bindings_wheel_grab(E_BINDING_CONTEXT_BORDER, bd->win);
368    e_focus_setup(bd);
369    bd->bg_ecore_evas = e_canvas_new(e_config->evas_engine_borders, bd->win,
370                                     0, 0, bd->w, bd->h, 1, 0,
371                                     &(bd->bg_win));
372    e_canvas_add(bd->bg_ecore_evas);
373    bd->event_win = ecore_x_window_input_new(bd->win, 0, 0, bd->w, bd->h);
374    bd->bg_evas = ecore_evas_get(bd->bg_ecore_evas);
375    ecore_x_window_shape_events_select(bd->bg_win, 1);
376    ecore_evas_name_class_set(bd->bg_ecore_evas, "E", "Frame_Window");
377    ecore_evas_title_set(bd->bg_ecore_evas, "Enlightenment Frame");
378    if (bd->client.argb)
379      bd->client.shell_win = ecore_x_window_manager_argb_new(bd->win, 0, 0, 1, 1);
380    else
381      bd->client.shell_win = ecore_x_window_override_new(bd->win, 0, 0, 1, 1);
382    ecore_x_window_container_manage(bd->client.shell_win);
383    if (!internal) ecore_x_window_client_manage(win);
384    /* FIXME: Round trip. XCB */
385    /* fetch needed to avoid grabbing the server as window may vanish */
386    att = &bd->client.initial_attributes;
387    if ((!ecore_x_window_attributes_get(win, att)) || (att->input_only))
388      {
389         //      printf("##- ATTR FETCH FAILED/INPUT ONLY FOR 0x%x - ABORT MANAGE\n", win);
390           e_canvas_del(bd->bg_ecore_evas);
391           ecore_evas_free(bd->bg_ecore_evas);
392           ecore_x_window_free(bd->client.shell_win);
393           e_bindings_mouse_ungrab(E_BINDING_CONTEXT_BORDER, bd->win);
394           e_bindings_wheel_ungrab(E_BINDING_CONTEXT_BORDER, bd->win);
395           ecore_x_window_free(bd->win);
396           free(bd);
397           return NULL;
398      }
399
400    /* printf("##- ON MAP CLIENT 0x%x SIZE %ix%i %i:%i\n",
401     *     bd->client.win, bd->client.w, bd->client.h, att->x, att->y); */
402
403    /* FIXME: if first_map is 1 then we should ignore the first hide event
404     * or ensure the window is already hidden and events flushed before we
405     * create a border for it */
406    if (first_map)
407      {
408         // printf("##- FIRST MAP\n");
409           bd->x = att->x;
410           bd->y = att->y;
411           bd->changes.pos = 1;
412           bd->re_manage = 1;
413           // needed to be 1 for internal windw and on restart.
414           // bd->ignore_first_unmap = 2;
415      }
416
417    bd->client.win = win;
418    bd->zone = e_zone_current_get(con);
419
420    _e_border_hook_call(E_BORDER_HOOK_NEW_BORDER, bd);
421
422    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_X_EVENT_MOUSE_IN, _e_border_cb_mouse_in, bd));
423    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_X_EVENT_MOUSE_OUT, _e_border_cb_mouse_out, bd));
424    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_cb_mouse_down, bd));
425    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, _e_border_cb_mouse_up, bd));
426    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, _e_border_cb_mouse_move, bd));
427    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL, _e_border_cb_mouse_wheel, bd));
428
429    bd->client.icccm.title = NULL;
430    bd->client.icccm.name = NULL;
431    bd->client.icccm.class = NULL;
432    bd->client.icccm.icon_name = NULL;
433    bd->client.icccm.machine = NULL;
434    bd->client.icccm.min_w = 1;
435    bd->client.icccm.min_h = 1;
436    bd->client.icccm.max_w = 32767;
437    bd->client.icccm.max_h = 32767;
438    bd->client.icccm.base_w = 0;
439    bd->client.icccm.base_h = 0;
440    bd->client.icccm.step_w = -1;
441    bd->client.icccm.step_h = -1;
442    bd->client.icccm.min_aspect = 0.0;
443    bd->client.icccm.max_aspect = 0.0;
444    bd->client.icccm.accepts_focus = 1;
445
446    bd->client.netwm.pid = 0;
447    bd->client.netwm.name = NULL;
448    bd->client.netwm.icon_name = NULL;
449    bd->client.netwm.desktop = 0;
450    bd->client.netwm.state.modal = 0;
451    bd->client.netwm.state.sticky = 0;
452    bd->client.netwm.state.shaded = 0;
453    bd->client.netwm.state.hidden = 0;
454    bd->client.netwm.state.maximized_v = 0;
455    bd->client.netwm.state.maximized_h = 0;
456    bd->client.netwm.state.skip_taskbar = 0;
457    bd->client.netwm.state.skip_pager = 0;
458    bd->client.netwm.state.fullscreen = 0;
459    bd->client.netwm.state.stacking = E_STACKING_NONE;
460    bd->client.netwm.action.move = 0;
461    bd->client.netwm.action.resize = 0;
462    bd->client.netwm.action.minimize = 0;
463    bd->client.netwm.action.shade = 0;
464    bd->client.netwm.action.stick = 0;
465    bd->client.netwm.action.maximized_h = 0;
466    bd->client.netwm.action.maximized_v = 0;
467    bd->client.netwm.action.fullscreen = 0;
468    bd->client.netwm.action.change_desktop = 0;
469    bd->client.netwm.action.close = 0;
470    bd->client.netwm.type = ECORE_X_WINDOW_TYPE_UNKNOWN;
471
472    {
473       int at_num = 0, i;
474       Ecore_X_Atom *atoms;
475
476       atoms = ecore_x_window_prop_list(bd->client.win, &at_num);
477       bd->client.icccm.fetch.command = 1;
478       if (atoms)
479         {
480            /* icccm */
481             for (i = 0; i < at_num; i++)
482               {
483                  if (atoms[i] == ECORE_X_ATOM_WM_NAME)
484                    bd->client.icccm.fetch.title = 1;
485                  else if (atoms[i] == ECORE_X_ATOM_WM_CLASS)
486                    bd->client.icccm.fetch.name_class = 1;
487                  else if (atoms[i] == ECORE_X_ATOM_WM_ICON_NAME)
488                    bd->client.icccm.fetch.icon_name = 1;
489                  else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_MACHINE)
490                    bd->client.icccm.fetch.machine = 1;
491                  else if (atoms[i] == ECORE_X_ATOM_WM_HINTS)
492                    bd->client.icccm.fetch.hints = 1;
493                  else if (atoms[i] == ECORE_X_ATOM_WM_NORMAL_HINTS)
494                    bd->client.icccm.fetch.size_pos_hints = 1;
495                  else if (atoms[i] == ECORE_X_ATOM_WM_PROTOCOLS)
496                    bd->client.icccm.fetch.protocol = 1;
497                  else if (atoms[i] == ECORE_X_ATOM_MOTIF_WM_HINTS)
498                    bd->client.mwm.fetch.hints = 1;
499                  else if (atoms[i] == ECORE_X_ATOM_WM_TRANSIENT_FOR)
500                    {
501                       bd->client.icccm.fetch.transient_for = 1;
502                       bd->client.netwm.fetch.type = 1;
503                    }
504                  else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_LEADER)
505                    bd->client.icccm.fetch.client_leader = 1;
506                  else if (atoms[i] == ECORE_X_ATOM_WM_WINDOW_ROLE)
507                    bd->client.icccm.fetch.window_role = 1;
508                  else if (atoms[i] == ECORE_X_ATOM_WM_STATE)
509                    bd->client.icccm.fetch.state = 1;
510               }
511             /* netwm, loop again, netwm will ignore some icccm, so we
512              * have to be sure that netwm is checked after */
513             for (i = 0; i < at_num; i++)
514               {
515                  if (atoms[i] == ECORE_X_ATOM_NET_WM_NAME)
516                    {
517      /* Ignore icccm */
518                        bd->client.icccm.fetch.title = 0;
519                        bd->client.netwm.fetch.name = 1;
520                    }
521                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON_NAME)
522                    {
523      /* Ignore icccm */
524                        bd->client.icccm.fetch.icon_name = 0;
525                        bd->client.netwm.fetch.icon_name = 1;
526                    }
527                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON)
528                    {
529                       bd->client.netwm.fetch.icon = 1;
530                    }
531                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_USER_TIME)
532                    {
533                       bd->client.netwm.fetch.user_time = 1;
534                    }
535                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT)
536                    {
537                       printf("ECORE_X_ATOM_NET_WM_STRUT\n");
538                       bd->client.netwm.fetch.strut = 1;
539                    }
540                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
541                    {
542                       printf("ECORE_X_ATOM_NET_WM_STRUT_PARTIAL\n");
543                       bd->client.netwm.fetch.strut = 1;
544                    }
545                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_WINDOW_TYPE)
546                    {
547      /* Ignore mwm
548         bd->client.mwm.fetch.hints = 0;
549       */
550                         bd->client.netwm.fetch.type = 1;
551                    }
552                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_STATE)
553                    {
554                       bd->client.netwm.fetch.state = 1;
555                    }
556               }
557             /* other misc atoms */
558             for (i = 0; i < at_num; i++)
559               {
560      /* loop to check for own atoms */
561                   if (atoms[i] == E_ATOM_WINDOW_STATE)
562                     {
563                        bd->client.e.fetch.state = 1;
564                     }
565      /* loop to check for qtopia atoms */
566                   if (atoms[i] == ATM__QTOPIA_SOFT_MENU)
567                     bd->client.qtopia.fetch.soft_menu = 1;
568                   else if (atoms[i] == ATM__QTOPIA_SOFT_MENUS)
569                     bd->client.qtopia.fetch.soft_menus = 1;
570      /* loop to check for vkbd atoms */
571                   else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
572                     bd->client.vkbd.fetch.state = 1;
573                   else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
574                     bd->client.vkbd.fetch.vkbd = 1;
575      /* loop to check for illume atoms */
576                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
577                     bd->client.illume.conformant.fetch.conformant = 1;
578                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
579                     bd->client.illume.quickpanel.fetch.state = 1;
580                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
581                     bd->client.illume.quickpanel.fetch.quickpanel = 1;
582                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
583                     bd->client.illume.quickpanel.fetch.priority.major = 1;
584                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
585                     bd->client.illume.quickpanel.fetch.priority.minor = 1;
586                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
587                     bd->client.illume.quickpanel.fetch.zone = 1;
588                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
589                     bd->client.illume.drag.fetch.locked = 1;
590                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG)
591                     bd->client.illume.drag.fetch.drag = 1;
592               }
593             free(atoms);
594         }
595    }
596    bd->client.border.changed = 1;
597
598    bd->client.w = att->w;
599    bd->client.h = att->h;
600
601    bd->w = bd->client.w;
602    bd->h = bd->client.h;
603
604    bd->resize_mode = RESIZE_NONE;
605    bd->layer = 100;
606    bd->saved.layer = bd->layer;
607    bd->changes.icon = 1;
608    bd->changes.size = 1;
609    bd->changes.shape = 1;
610    bd->changes.shape_input = 1;
611
612    bd->offer_resistance = 1;
613
614    /* just to friggin make java happy - we're DELAYING the reparent until
615     * eval time...
616     */
617 /*   ecore_x_window_reparent(win, bd->client.shell_win, 0, 0); */
618    bd->need_reparent = 1;
619
620    ecore_x_window_border_width_set(win, 0);
621    ecore_x_window_show(bd->event_win);
622    ecore_x_window_show(bd->client.shell_win);
623    bd->shape = e_container_shape_add(con);
624
625    bd->take_focus = 1;
626    bd->new_client = 1;
627    bd->changed = 1;
628
629 //   bd->zone = e_zone_current_get(con);
630    bd->desk = e_desk_current_get(bd->zone);
631    e_container_border_add(bd);
632    borders = eina_list_append(borders, bd);
633    bd2 = eina_hash_find(borders_hash, e_util_winid_str_get(bd->client.win));
634    if (bd2)
635      {
636         printf("EEEEK! 2 borders with same client window id in them! very bad!\n");
637         printf("optimisations failing due to bizarre client behavior. will\n");
638         printf("work around.\n");
639         printf("bd=%p, bd->references=%i, bd->deleted=%i, bd->client.win=%x\n",
640                bd2, bd2->e_obj_inherit.references, bd2->e_obj_inherit.deleted,
641                bd2->client.win);
642         eina_hash_del(borders_hash, e_util_winid_str_get(bd->client.win), bd2);
643         eina_hash_del(borders_hash, e_util_winid_str_get(bd2->bg_win), bd2);
644         eina_hash_del(borders_hash, e_util_winid_str_get(bd2->win), bd2);
645      }
646    eina_hash_add(borders_hash, e_util_winid_str_get(bd->client.win), bd);
647    eina_hash_add(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
648    eina_hash_add(borders_hash, e_util_winid_str_get(bd->win), bd);
649    managed = 1;
650    ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &managed, 1);
651    ecore_x_window_prop_card32_set(win, E_ATOM_CONTAINER, &bd->zone->container->num, 1);
652    ecore_x_window_prop_card32_set(win, E_ATOM_ZONE, &bd->zone->num, 1);
653    e_desk_xy_get(bd->desk, &deskx, &desky);
654    desk[0] = deskx;
655    desk[1] = desky;
656    ecore_x_window_prop_card32_set(win, E_ATOM_DESK, desk, 2);
657
658    focus_stack = eina_list_append(focus_stack, bd);
659
660    bd->pointer = e_pointer_window_new(bd->win, 0);
661    return bd;
662 }
663
664 EAPI void
665 e_border_res_change_geometry_save(E_Border *bd)
666 {
667    E_OBJECT_CHECK(bd);
668    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
669
670    if (bd->pre_res_change.valid) return;
671    bd->pre_res_change.valid = 1;
672    bd->pre_res_change.x = bd->x;
673    bd->pre_res_change.y = bd->y;
674    bd->pre_res_change.w = bd->w;
675    bd->pre_res_change.h = bd->h;
676    bd->pre_res_change.saved.x = bd->saved.x;
677    bd->pre_res_change.saved.y = bd->saved.y;
678    bd->pre_res_change.saved.w = bd->saved.w;
679    bd->pre_res_change.saved.h = bd->saved.h;
680 }
681
682 EAPI void
683 e_border_res_change_geometry_restore(E_Border *bd)
684 {
685    struct
686    {
687       unsigned char valid : 1;
688       int           x, y, w, h;
689       struct
690       {
691          int x, y, w, h;
692       } saved;
693    } pre_res_change;
694
695    E_OBJECT_CHECK(bd);
696    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
697    if (!bd->pre_res_change.valid) return;
698    if (bd->new_client) return;
699
700    ecore_x_window_shadow_tree_flush();
701    memcpy(&pre_res_change, &bd->pre_res_change, sizeof(pre_res_change));
702
703    if (bd->fullscreen)
704      {
705         e_border_unfullscreen(bd);
706         e_border_fullscreen(bd, e_config->fullscreen_policy);
707      }
708    else if (bd->maximized != E_MAXIMIZE_NONE)
709      {
710         E_Maximize max;
711
712         max = bd->maximized;
713         e_border_unmaximize(bd, E_MAXIMIZE_BOTH);
714         e_border_maximize(bd, max);
715      }
716    else
717      {
718         int x, y, w, h, zx, zy, zw, zh;
719
720         bd->saved.x = bd->pre_res_change.saved.x;
721         bd->saved.y = bd->pre_res_change.saved.y;
722         bd->saved.w = bd->pre_res_change.saved.w;
723         bd->saved.h = bd->pre_res_change.saved.h;
724
725         e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
726
727         if (bd->saved.w > zw)
728           bd->saved.w = zw;
729         if ((bd->saved.x + bd->saved.w) > (zx + zw))
730           bd->saved.x = zx + zw - bd->saved.w;
731
732         if (bd->saved.h > zh)
733           bd->saved.h = zh;
734         if ((bd->saved.y + bd->saved.h) > (zy + zh))
735           bd->saved.y = zy + zh - bd->saved.h;
736
737         x = bd->pre_res_change.x;
738         y = bd->pre_res_change.y;
739         w = bd->pre_res_change.w;
740         h = bd->pre_res_change.h;
741         if (w > zw)
742           w = zw;
743         if (h > zh)
744           h = zh;
745         if ((x + w) > (zx + zw))
746           x = zx + zw - w;
747         if ((y + h) > (zy + zh))
748           y = zy + zh - h;
749         e_border_move_resize(bd, x, y, w, h);
750      }
751    memcpy(&bd->pre_res_change, &pre_res_change, sizeof(pre_res_change));
752 }
753
754 EAPI void
755 e_border_zone_set(E_Border *bd,
756                   E_Zone   *zone)
757 {
758    E_Event_Border_Zone_Set *ev;
759
760    E_OBJECT_CHECK(bd);
761    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
762    E_OBJECT_CHECK(zone);
763    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
764    if (!zone) return;
765    if (bd->zone == zone) return;
766
767    /* if the window does not lie in the new zone, move it so that it does */
768    if (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))
769      {
770         int x, y;
771         /* first guess -- get offset from old zone, and apply to new zone */
772         x = zone->x + (bd->x - bd->zone->x);
773         y = zone->y + (bd->y - bd->zone->y);
774
775         /* keep window from hanging off bottom and left */
776         if (x + bd->w > zone->x + zone->w) x += (zone->x + zone->w) - (x + bd->w);
777         if (y + bd->h > zone->y + zone->h) y += (zone->y + zone->h) - (y + bd->h);
778
779         /* make sure to and left are on screen (if the window is larger than the zone, it will hang off the bottom / right) */
780         if (x < zone->x) x = zone->x;
781         if (y < zone->y) y = zone->y;
782
783         if (!E_INTERSECTS(x, y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))
784           {
785              /* still not in zone at all, so just move it to closest edge */
786               if (x < zone->x) x = zone->x;
787               if (x >= zone->x + zone->w) x = zone->x + zone->w - bd->w;
788               if (y < zone->y) y = zone->y;
789               if (y >= zone->y + zone->h) y = zone->y + zone->h - bd->h;
790           }
791         e_border_move(bd, x, y);
792      }
793
794    bd->zone = zone;
795
796    if (bd->desk->zone != bd->zone)
797      e_border_desk_set(bd, e_desk_current_get(bd->zone));
798
799    ev = E_NEW(E_Event_Border_Zone_Set, 1);
800    ev->border = bd;
801    e_object_ref(E_OBJECT(bd));
802 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_zone_set_event");
803    ev->zone = zone;
804    e_object_ref(E_OBJECT(zone));
805
806    ecore_event_add(E_EVENT_BORDER_ZONE_SET, ev, _e_border_event_border_zone_set_free, NULL);
807
808    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_ZONE, &bd->zone->num, 1);
809    e_remember_update(bd);
810 }
811
812 EAPI void
813 e_border_desk_set(E_Border *bd,
814                   E_Desk   *desk)
815 {
816    E_Event_Border_Desk_Set *ev;
817    E_Desk *old_desk;
818
819    E_OBJECT_CHECK(bd);
820    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
821    E_OBJECT_CHECK(desk);
822    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
823    if (bd->desk == desk) return;
824    ecore_x_window_shadow_tree_flush();
825    if (bd->fullscreen)
826      {
827         bd->desk->fullscreen_borders--;
828         desk->fullscreen_borders++;
829      }
830    old_desk = bd->desk;
831    bd->desk = desk;
832    e_border_zone_set(bd, desk->zone);
833
834    _e_border_hook_call(E_BORDER_HOOK_SET_DESK, bd);
835    e_hints_window_desktop_set(bd);
836
837    ev = E_NEW(E_Event_Border_Desk_Set, 1);
838    ev->border = bd;
839    e_object_ref(E_OBJECT(bd));
840 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_desk_set_event");
841    ev->desk = old_desk;
842    e_object_ref(E_OBJECT(old_desk));
843    ecore_event_add(E_EVENT_BORDER_DESK_SET, ev, _e_border_event_border_desk_set_free, NULL);
844
845    if (bd->ignore_first_unmap != 1)
846      {
847         if ((bd->desk->visible) || (bd->sticky))
848           e_border_show(bd);
849         else
850           e_border_hide(bd, 1);
851      }
852
853    if (e_config->transient.desktop)
854      {
855         Eina_List *l;
856         E_Border *child;
857         EINA_LIST_FOREACH(bd->transients, l, child)
858           {
859              e_border_desk_set(child, bd->desk);
860           }
861      }
862    e_remember_update(bd);
863 }
864
865 EAPI void
866 e_border_show(E_Border *bd)
867 {
868    E_Event_Border_Show *ev;
869    unsigned int visible;
870
871    E_OBJECT_CHECK(bd);
872    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
873    if (bd->visible) return;
874    ecore_x_window_shadow_tree_flush();
875    e_container_shape_show(bd->shape);
876    if (!bd->need_reparent)
877      ecore_x_window_show(bd->client.win);
878    e_hints_window_visible_set(bd);
879    bd->visible = 1;
880    bd->changes.visible = 1;
881
882    visible = 1;
883    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
884    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MANAGED, &visible, 1);
885
886    ev = E_NEW(E_Event_Border_Show, 1);
887    ev->border = bd;
888    e_object_ref(E_OBJECT(bd));
889 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_show_event");
890    ecore_event_add(E_EVENT_BORDER_SHOW, ev, _e_border_event_border_show_free, NULL);
891 }
892
893 EAPI void
894 e_border_hide(E_Border *bd,
895               int       manage)
896 {
897    unsigned int visible;
898
899    E_OBJECT_CHECK(bd);
900    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
901    if (!bd->visible) return;
902    ecore_x_window_shadow_tree_flush();
903    if (bd->moving)
904      _e_border_move_end(bd);
905    if (bd->resize_mode != RESIZE_NONE)
906      {
907         _e_border_pointer_resize_end(bd);
908         bd->resize_mode = RESIZE_NONE;
909         _e_border_resize_end(bd);
910      }
911
912    e_container_shape_hide(bd->shape);
913    if (!bd->iconic) e_hints_window_hidden_set(bd);
914
915    bd->visible = 0;
916    bd->changes.visible = 1;
917
918    if (!bd->need_reparent)
919      {
920         if (bd->focused)
921           {
922              e_border_focus_set(bd, 0, 1);
923              if (manage != 2)
924                {
925                   E_Border *pbd;
926                   E_Container *con;
927                   E_Zone *zone;
928                   E_Desk *desk;
929
930                   con = e_container_current_get(e_manager_current_get());
931                   zone = e_zone_current_get(con);
932                   desk = e_desk_current_get(zone);
933
934                   if ((bd->parent) &&
935                       (bd->parent->desk == desk) && (bd->parent->modal == bd))
936                     e_border_focus_set(bd->parent, 1, 1);
937                   else if (e_config->focus_revert_on_hide_or_close)
938                     {
939      /* When using pointer focus, the border under the
940       * pointer (if any) gets focused, in sloppy/click
941       * focus the last focused window on the current
942       * desk gets focus */
943                          if (e_config->focus_policy == E_FOCUS_MOUSE)
944                            {
945                               pbd = e_border_under_pointer_get(desk, bd);
946                               if (pbd)
947                                 e_border_focus_set(pbd, 1, 1);
948                            }
949 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
950                          else if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) &&
951                                   (e_config->focus_policy == E_FOCUS_CLICK))     
952                            _e_border_latest_stacked_focus(bd);
953 #endif
954                          else
955                            e_desk_last_focused_focus(desk);
956                     }
957                }
958           }
959         if (manage == 1)
960           {
961              /* Make sure that this border isn't deleted */
962               bd->await_hide_event++;
963           }
964         if (manage != 2)
965           {
966              if (!e_manager_comp_evas_get(bd->zone->container->manager))
967                ecore_x_window_hide(bd->client.win);
968           }
969      }
970
971    visible = 0;
972    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
973    if (!manage)
974      ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MANAGED, &visible, 1);
975
976    if (!stopping)
977      {
978         E_Event_Border_Hide *ev;
979
980         ev = E_NEW(E_Event_Border_Hide, 1);
981         ev->border = bd;
982         e_object_ref(E_OBJECT(bd));
983 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_hide_event");
984         ecore_event_add(E_EVENT_BORDER_HIDE, ev, _e_border_event_border_hide_free, NULL);
985      }
986    bd->post_show = 0;
987 }
988
989 static void
990 _e_border_frame_replace(E_Border *bd, Eina_Bool argb)
991 {
992    Ecore_X_Window win;
993    Ecore_Evas *bg_ecore_evas;
994    char buf[PATH_MAX];
995
996    bd->argb = argb;
997
998    win = bd->win;
999    bg_ecore_evas = bd->bg_ecore_evas;
1000
1001    /* unregister old frame window */
1002    eina_hash_del(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
1003    eina_hash_del(borders_hash, e_util_winid_str_get(bd->win), bd);
1004
1005    e_focus_setdown(bd);
1006    e_bindings_mouse_ungrab(E_BINDING_CONTEXT_BORDER, bd->win);
1007    e_bindings_wheel_ungrab(E_BINDING_CONTEXT_BORDER, bd->win);
1008
1009    if (bd->icon_object)
1010      evas_object_del(bd->icon_object);
1011
1012    evas_object_del(bd->bg_object);
1013    e_canvas_del(bg_ecore_evas);
1014    ecore_evas_free(bg_ecore_evas);
1015
1016    if (bd->pointer)
1017      e_object_del(E_OBJECT(bd->pointer));
1018
1019    /* create new frame */
1020    if (argb)
1021      bd->win = ecore_x_window_manager_argb_new(bd->zone->container->win,
1022                                                bd->x, bd->y, bd->w, bd->h);
1023    else
1024      {
1025         bd->win = ecore_x_window_override_new(bd->zone->container->win,
1026                                               bd->x, bd->y, bd->w, bd->h);
1027         ecore_x_window_shape_events_select(bd->win, 1);
1028      }
1029
1030    ecore_x_window_configure(bd->win,
1031                             ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
1032                             ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
1033                             0, 0, 0, 0, 0,
1034                             win, ECORE_X_WINDOW_STACK_BELOW);
1035
1036    e_bindings_mouse_grab(E_BINDING_CONTEXT_BORDER, bd->win);
1037    e_bindings_wheel_grab(E_BINDING_CONTEXT_BORDER, bd->win);
1038    e_focus_setup(bd);
1039
1040    bd->bg_ecore_evas = e_canvas_new(e_config->evas_engine_borders, bd->win,
1041                                     0, 0, bd->w, bd->h, 1, 0,
1042                                     &(bd->bg_win));
1043
1044    e_canvas_add(bd->bg_ecore_evas);
1045    ecore_x_window_reparent(bd->event_win, bd->win, 0, 0);
1046
1047    bd->bg_evas = ecore_evas_get(bd->bg_ecore_evas);
1048    ecore_evas_name_class_set(bd->bg_ecore_evas, "E", "Frame_Window");
1049    ecore_evas_title_set(bd->bg_ecore_evas, "Enlightenment Frame");
1050
1051    ecore_x_window_shape_events_select(bd->bg_win, 1);
1052
1053    /* move client with shell win over to new frame */
1054    ecore_x_window_reparent(bd->client.shell_win, bd->win,
1055                            bd->client_inset.l, bd->client_inset.t);
1056
1057    bd->pointer = e_pointer_window_new(bd->win, 0);
1058
1059    eina_hash_add(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
1060    eina_hash_add(borders_hash, e_util_winid_str_get(bd->win), bd);
1061
1062    if (bd->visible)
1063      {
1064         ecore_evas_show(bd->bg_ecore_evas);
1065         ecore_x_window_show(bd->win);
1066      }
1067
1068    bd->bg_object = edje_object_add(bd->bg_evas);
1069    snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
1070    e_theme_edje_object_set(bd->bg_object, "base/theme/borders", buf);
1071
1072    bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
1073
1074    /* cleanup old frame */
1075    ecore_x_window_free(win);
1076 }
1077
1078 static void
1079 _e_border_client_move_resize_send(E_Border *bd)
1080 {
1081    if (bd->internal_ecore_evas)
1082      ecore_evas_managed_move(bd->internal_ecore_evas,
1083                              bd->x + bd->fx.x + bd->client_inset.l,
1084                              bd->y + bd->fx.y + bd->client_inset.t);
1085
1086    ecore_x_icccm_move_resize_send(bd->client.win,
1087                                   bd->x + bd->fx.x + bd->client_inset.l,
1088                                   bd->y + bd->fx.y + bd->client_inset.t,
1089                                   bd->client.w,
1090                                   bd->client.h);
1091 }
1092
1093 static void
1094 _e_border_pending_move_resize_add(E_Border    *bd,
1095                                   int          move,
1096                                   int          resize,
1097                                   int          x,
1098                                   int          y,
1099                                   int          w,
1100                                   int          h,
1101                                   Eina_Bool    without_border,
1102                                   unsigned int serial)
1103 {
1104    E_Border_Pending_Move_Resize *pnd;
1105
1106    pnd = E_NEW(E_Border_Pending_Move_Resize, 1);
1107    if (!pnd) return;
1108    pnd->resize = resize;
1109    pnd->move = move;
1110    pnd->without_border = without_border;
1111    pnd->x = x;
1112    pnd->y = y;
1113    pnd->w = w;
1114    pnd->h = h;
1115    pnd->serial = serial;
1116    bd->pending_move_resize = eina_list_append(bd->pending_move_resize, pnd);
1117 }
1118
1119 static void
1120 _e_border_move_internal(E_Border *bd,
1121                         int       x,
1122                         int       y,
1123                         Eina_Bool without_border)
1124 {
1125    E_Event_Border_Move *ev;
1126
1127    E_OBJECT_CHECK(bd);
1128    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1129
1130    ecore_x_window_shadow_tree_flush();
1131    if (bd->new_client)
1132      {
1133         _e_border_pending_move_resize_add(bd, 1, 0, x, y, 0, 0, without_border, 0);
1134         return;
1135      }
1136
1137    if (bd->maximized)
1138      {
1139        if ((bd->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_BOTH)
1140          {
1141             if (e_config->allow_manip)
1142               bd->maximized = 0;
1143
1144             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
1145               {
1146                   x = bd->x;
1147               }
1148             else
1149             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
1150               {
1151                   y = bd->y;
1152               }
1153          }
1154        else
1155        if (e_config->allow_manip)
1156          bd->maximized = 0;
1157        else
1158          return;
1159      }
1160
1161    if (without_border)
1162      {
1163         x -= bd->client_inset.l;
1164         y -= bd->client_inset.t;
1165      }
1166
1167    if ((x == bd->x) && (y == bd->y)) return;
1168    bd->pre_res_change.valid = 0;
1169    bd->x = x;
1170    bd->y = y;
1171    bd->changed = 1;
1172    bd->changes.pos = 1;
1173 #if 0
1174    if (bd->client.netwm.sync.request)
1175      {
1176         bd->client.netwm.sync.wait++;
1177         ecore_x_netwm_sync_request_send(bd->client.win, bd->client.netwm.sync.serial++);
1178      }
1179 #endif
1180    _e_border_client_move_resize_send(bd);
1181    _e_border_move_update(bd);
1182    ev = E_NEW(E_Event_Border_Move, 1);
1183    ev->border = bd;
1184    e_object_ref(E_OBJECT(bd));
1185 //  e_object_breadcrumb_add(E_OBJECT(bd), "border_move_event");
1186    ecore_event_add(E_EVENT_BORDER_MOVE, ev, _e_border_event_border_move_free, NULL);
1187    _e_border_zone_update(bd);
1188 }
1189
1190 /**
1191  * Move window to coordinates that already account border decorations.
1192  *
1193  * This call will consider given position already accounts border
1194  * decorations, so it will not be considered later. This will just
1195  * work properly with borders that have being evaluated and border
1196  * decorations are known (border->client_inset).
1197  *
1198  * @parm x horizontal position to place window.
1199  * @parm y vertical position to place window.
1200  *
1201  * @see e_border_move_without_border()
1202  */
1203 EAPI void
1204 e_border_move(E_Border *bd,
1205               int       x,
1206               int       y)
1207 {
1208    if (bd->fullscreen)
1209      return;
1210
1211    _e_border_move_internal(bd, x, y, 0);
1212 }
1213
1214 /**
1215  * Move window to coordinates that do not account border decorations yet.
1216  *
1217  * This call will consider given position does not account border
1218  * decoration, so these values (border->client_inset) will be
1219  * accounted automatically. This is specially useful when it is a new
1220  * client and has not be evaluated yet, in this case
1221  * border->client_inset will be zeroed and no information is known. It
1222  * will mark pending requests so border will be accounted on
1223  * evalutation phase.
1224  *
1225  * @parm x horizontal position to place window.
1226  * @parm y vertical position to place window.
1227  *
1228  * @see e_border_move()
1229  */
1230 EAPI void
1231 e_border_move_without_border(E_Border *bd,
1232                              int       x,
1233                              int       y)
1234 {
1235    if (bd->fullscreen)
1236      return;
1237
1238    _e_border_move_internal(bd, x, y, 1);
1239 }
1240
1241 EAPI void
1242 e_border_center(E_Border *bd)
1243 {
1244    int x, y, w, h;
1245    E_OBJECT_CHECK(bd);
1246    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1247
1248    e_zone_useful_geometry_get(bd->zone, &x, &y, &w, &h);
1249    e_border_move(bd, x + (w - bd->w) / 2, y + (h - bd->h) / 2);
1250 }
1251
1252 EAPI void
1253 e_border_center_pos_get(E_Border *bd,
1254                         int      *x,
1255                         int      *y)
1256 {
1257    int zx, zy, zw, zh;
1258    E_OBJECT_CHECK(bd);
1259    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1260
1261    e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
1262    if (x) *x = zx + (zw - bd->w) / 2;
1263    if (y) *y = zy + (zh - bd->h) / 2;
1264 }
1265
1266 EAPI void
1267 e_border_fx_offset(E_Border *bd,
1268                    int       x,
1269                    int       y)
1270 {
1271    E_OBJECT_CHECK(bd);
1272    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1273
1274    if ((x == bd->fx.x) && (y == bd->fx.y)) return;
1275    bd->fx.x = x;
1276    bd->fx.y = y;
1277
1278    bd->changes.pos = 1;
1279    bd->changed = 1;
1280
1281    if (bd->moving) _e_border_move_update(bd);
1282 }
1283
1284 static void
1285 _e_border_move_resize_internal(E_Border *bd,
1286                                int       x,
1287                                int       y,
1288                                int       w,
1289                                int       h,
1290                                Eina_Bool without_border,
1291                                Eina_Bool move)
1292 {
1293    E_Event_Border_Move *mev;
1294    E_Event_Border_Resize *rev;
1295
1296    E_OBJECT_CHECK(bd);
1297    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1298
1299    ecore_x_window_shadow_tree_flush();
1300
1301    if (bd->new_client)
1302      {
1303         _e_border_pending_move_resize_add(bd, move, 1, x, y, w, h, without_border, 0);
1304         return;
1305      }
1306
1307    if (bd->maximized)
1308      {
1309        if ((bd->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_BOTH)
1310          {
1311             if (e_config->allow_manip)
1312               bd->maximized = 0;
1313
1314             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
1315               {
1316                   x = bd->x;
1317                   w = bd->w;
1318               }
1319             else
1320             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
1321               {
1322                   y = bd->y;
1323                   h = bd->h;
1324               }
1325          }
1326        else
1327        if (e_config->allow_manip)
1328          bd->maximized = 0;
1329        else
1330          return;
1331      }
1332
1333    if (without_border)
1334      {
1335         x -= bd->client_inset.l;
1336         y -= bd->client_inset.t;
1337         w += (bd->client_inset.l + bd->client_inset.r);
1338         h += (bd->client_inset.t + bd->client_inset.b);
1339      }
1340
1341    if ((!move || ((x == bd->x) && (y == bd->y))) &&
1342        (w == bd->w) && (h == bd->h))
1343      return;
1344
1345    bd->pre_res_change.valid = 0;
1346    if (move)
1347      {
1348         bd->changes.pos = 1;
1349         bd->x = x;
1350         bd->y = y;
1351      }
1352    bd->w = w;
1353    bd->h = h;
1354    bd->client.w = bd->w - (bd->client_inset.l + bd->client_inset.r);
1355    bd->client.h = bd->h - (bd->client_inset.t + bd->client_inset.b);
1356
1357    if ((bd->shaped) || (bd->client.shaped))
1358      {
1359         bd->need_shape_merge = 1;
1360         bd->need_shape_export = 1;
1361      }
1362    if (bd->shaped_input)
1363      {
1364         bd->need_shape_merge = 1;
1365      }
1366
1367    if (bd->internal_ecore_evas)
1368      {
1369         bd->changed = 1;
1370         bd->changes.size = 1;
1371      }
1372    else
1373      {
1374         if (resize && bd->client.netwm.sync.request)
1375           {
1376              bd->client.netwm.sync.wait++;
1377              /* Don't use x and y as supplied to this function, as it is called with 0, 0
1378               * when no move is intended.  The border geometry is set above anyways.
1379               */
1380              _e_border_pending_move_resize_add(bd, move, 1, bd->x, bd->y, bd->w, bd->h, without_border,
1381                                                bd->client.netwm.sync.serial);
1382              ecore_x_netwm_sync_request_send(bd->client.win,
1383                                              bd->client.netwm.sync.serial++);
1384           }
1385         else
1386           {
1387              bd->changed = 1;
1388              bd->changes.size = 1;
1389           }
1390      }
1391
1392    _e_border_client_move_resize_send(bd);
1393
1394    _e_border_resize_update(bd);
1395    if (move)
1396      {
1397         mev = E_NEW(E_Event_Border_Move, 1);
1398         mev->border = bd;
1399         e_object_ref(E_OBJECT(bd));
1400         //   e_object_breadcrumb_add(E_OBJECT(bd), "border_move_event");
1401         ecore_event_add(E_EVENT_BORDER_MOVE, mev, _e_border_event_border_move_free, NULL);
1402      }
1403
1404    rev = E_NEW(E_Event_Border_Resize, 1);
1405    rev->border = bd;
1406    e_object_ref(E_OBJECT(bd));
1407 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
1408    ecore_event_add(E_EVENT_BORDER_RESIZE, rev, _e_border_event_border_resize_free, NULL);
1409    _e_border_zone_update(bd);
1410 }
1411
1412 /**
1413  * Move and resize window to values that already account border decorations.
1414  *
1415  * This call will consider given values already accounts border
1416  * decorations, so it will not be considered later. This will just
1417  * work properly with borders that have being evaluated and border
1418  * decorations are known (border->client_inset).
1419  *
1420  * @parm x horizontal position to place window.
1421  * @parm y vertical position to place window.
1422  * @parm w horizontal window size.
1423  * @parm h vertical window size.
1424  *
1425  * @see e_border_move_resize_without_border()
1426  */
1427 EAPI void
1428 e_border_move_resize(E_Border *bd,
1429                      int       x,
1430                      int       y,
1431                      int       w,
1432                      int       h)
1433 {
1434    if (bd->fullscreen)
1435      return;
1436
1437    _e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
1438 }
1439
1440 /**
1441  * Move and resize window to values that do not account border decorations yet.
1442  *
1443  * This call will consider given values already accounts border
1444  * decorations, so it will not be considered later. This will just
1445  * work properly with borders that have being evaluated and border
1446  * decorations are known (border->client_inset).
1447  *
1448  * @parm x horizontal position to place window.
1449  * @parm y vertical position to place window.
1450  * @parm w horizontal window size.
1451  * @parm h vertical window size.
1452  *
1453  * @see e_border_move_resize()
1454  */
1455 EAPI void
1456 e_border_move_resize_without_border(E_Border *bd,
1457                                     int       x,
1458                                     int       y,
1459                                     int       w,
1460                                     int       h)
1461 {
1462    if (bd->fullscreen)
1463      return;
1464
1465    _e_border_move_resize_internal(bd, x, y, w, h, 1, 1);
1466 }
1467
1468 /**
1469  * Resize window to values that already account border decorations.
1470  *
1471  * This call will consider given size already accounts border
1472  * decorations, so it will not be considered later. This will just
1473  * work properly with borders that have being evaluated and border
1474  * decorations are known (border->client_inset).
1475  *
1476  * @parm w horizontal window size.
1477  * @parm h vertical window size.
1478  *
1479  * @see e_border_resize_without_border()
1480  */
1481 EAPI void
1482 e_border_resize(E_Border *bd,
1483                 int       w,
1484                 int       h)
1485 {
1486    if (bd->fullscreen)
1487      return;
1488
1489    _e_border_move_resize_internal(bd, 0, 0, w, h, 0, 0);
1490 }
1491
1492 /**
1493  * Resize window to values that do not account border decorations yet.
1494  *
1495  * This call will consider given size does not account border
1496  * decoration, so these values (border->client_inset) will be
1497  * accounted automatically. This is specially useful when it is a new
1498  * client and has not be evaluated yet, in this case
1499  * border->client_inset will be zeroed and no information is known. It
1500  * will mark pending requests so border will be accounted on
1501  * evalutation phase.
1502  *
1503  * @parm w horizontal window size.
1504  * @parm h vertical window size.
1505  *
1506  * @see e_border_resize()
1507  */
1508 EAPI void
1509 e_border_resize_without_border(E_Border *bd,
1510                                int       w,
1511                                int       h)
1512 {
1513    if (bd->fullscreen)
1514      return;
1515
1516    _e_border_move_resize_internal(bd, 0, 0, w, h, 1, 0);
1517 }
1518
1519 EAPI void
1520 e_border_layer_set(E_Border *bd,
1521                    int       layer)
1522 {
1523    int raise;
1524
1525    E_OBJECT_CHECK(bd);
1526    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1527
1528    ecore_x_window_shadow_tree_flush();
1529
1530    raise = e_config->transient.raise;
1531
1532    bd->saved.layer = bd->layer;
1533    bd->layer = layer;
1534    if (e_config->transient.layer)
1535      {
1536         Eina_List *l;
1537         E_Border *child;
1538
1539         /* We need to set raise to one, else the child wont
1540          * follow to the new layer. It should be like this,
1541          * even if the user usually doesn't want to raise
1542          * the transients.
1543          */
1544         e_config->transient.raise = 1;
1545         EINA_LIST_FOREACH(bd->transients, l, child)
1546           {
1547              child->layer = layer;
1548           }
1549      }
1550    e_border_raise(bd);
1551    e_config->transient.raise = raise;
1552 }
1553
1554 EAPI void
1555 e_border_raise(E_Border *bd)
1556 {
1557    E_Event_Border_Stack *ev;
1558    E_Border *last = NULL, *child;
1559    Eina_List *l;
1560
1561    E_OBJECT_CHECK(bd);
1562    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1563
1564    ecore_x_window_shadow_tree_flush();
1565
1566    if (e_config->transient.raise)
1567      {
1568 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
1569         if (e_config->focus_setting != E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
1570           {
1571 #endif
1572         EINA_LIST_REVERSE_FOREACH(bd->transients, l, child)
1573         {
1574            /* Don't stack iconic transients. If the user wants these shown,
1575             * thats another option.
1576             */
1577              if (!child->iconic)
1578                {
1579                   if (last)
1580                     e_border_stack_below(child, last);
1581                   else
1582                     {
1583                        E_Border *above;
1584
1585      /* First raise the border to find out which border we will end up above */
1586                        above = e_container_border_raise(child);
1587
1588                        if (above)
1589                          {
1590      /* We ended up above a border, now we must stack this border to
1591       * generate the stacking event, and to check if this transient
1592       * has other transients etc.
1593       */
1594                               e_border_stack_above(child, above);
1595                          }
1596                        else
1597                          {
1598      /* If we didn't end up above any border, we are on the bottom! */
1599                              e_border_lower(child);
1600                          }
1601                     }
1602                   last = child;
1603                }
1604         }
1605 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
1606           }
1607         else
1608           {
1609              EINA_LIST_FOREACH(bd->transients, l, child)
1610                {
1611                 /* Don't stack iconic transients. If the user wants these shown,
1612                  * thats another option.
1613                  */
1614                   if (!child->iconic)
1615                     {
1616                        if (!last) last = child;
1617                        e_border_raise (child);
1618                     }
1619                }
1620           }
1621 #endif
1622      }
1623
1624    ev = E_NEW(E_Event_Border_Stack, 1);
1625    ev->border = bd;
1626    e_object_ref(E_OBJECT(bd));
1627
1628    if (last)
1629      {
1630         e_container_border_stack_below(bd, last);
1631         ev->stack = last;
1632         e_object_ref(E_OBJECT(last));
1633         ev->type = E_STACKING_BELOW;
1634      }
1635    else
1636      {
1637         E_Border *above;
1638
1639         /* If we don't have any children, raise this border */
1640         above = e_container_border_raise(bd);
1641         e_border_raise_latest_set(bd);
1642         if (above)
1643           {
1644              /* We ended up above a border */
1645               ev->stack = above;
1646               e_object_ref(E_OBJECT(above));
1647               ev->type = E_STACKING_ABOVE;
1648           }
1649         else
1650           {
1651              /* No border to raise above, same as a lower! */
1652               ev->stack = NULL;
1653               ev->type = E_STACKING_ABOVE;
1654           }
1655      }
1656
1657    ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
1658    e_remember_update(bd);
1659 }
1660
1661 EAPI void
1662 e_border_lower(E_Border *bd)
1663 {
1664    E_Event_Border_Stack *ev;
1665    E_Border *last = NULL, *child;
1666    Eina_List *l;
1667
1668    E_OBJECT_CHECK(bd);
1669    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1670
1671    ecore_x_window_shadow_tree_flush();
1672
1673    if (e_config->transient.lower)
1674      {
1675 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
1676         if (e_config->focus_setting != E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
1677           {
1678 #endif
1679         EINA_LIST_REVERSE_FOREACH(bd->transients, l, child)
1680         {
1681            /* Don't stack iconic transients. If the user wants these shown,
1682             * thats another option.
1683             */
1684              if (!child->iconic)
1685                {
1686                   if (last)
1687                     e_border_stack_below(child, last);
1688                   else
1689                     {
1690                        E_Border *below;
1691
1692      /* First lower the border to find out which border we will end up below */
1693                        below = e_container_border_lower(child);
1694
1695                        if (below)
1696                          {
1697      /* We ended up below a border, now we must stack this border to
1698       * generate the stacking event, and to check if this transient
1699       * has other transients etc.
1700       */
1701                               e_border_stack_below(child, below);
1702                          }
1703                        else
1704                          {
1705      /* If we didn't end up below any border, we are on top! */
1706                              e_border_raise(child);
1707                          }
1708                     }
1709                   last = child;
1710                }
1711         }
1712 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
1713           }
1714         else
1715           {
1716              EINA_LIST_FOREACH(bd->transients, l, child)
1717                {
1718                 /* Don't stack iconic transients. If the user wants these shown,
1719                  * thats another option.
1720                  */
1721                   if (!child->iconic)
1722                     {
1723                        e_border_lower (child);
1724                        last = child;
1725                     }
1726                }
1727           }
1728 #endif
1729      }
1730
1731    ev = E_NEW(E_Event_Border_Stack, 1);
1732    ev->border = bd;
1733    e_object_ref(E_OBJECT(bd));
1734
1735    if (last)
1736      {
1737         e_container_border_stack_below(bd, last);
1738         ev->stack = last;
1739         e_object_ref(E_OBJECT(last));
1740         ev->type = E_STACKING_BELOW;
1741      }
1742    else
1743      {
1744         E_Border *below;
1745
1746         /* If we don't have any children, lower this border */
1747         below = e_container_border_lower(bd);
1748         if (below)
1749           {
1750              /* We ended up below a border */
1751               ev->stack = below;
1752               e_object_ref(E_OBJECT(below));
1753               ev->type = E_STACKING_BELOW;
1754           }
1755         else
1756           {
1757              /* No border to hide under, same as a raise! */
1758               ev->stack = NULL;
1759               ev->type = E_STACKING_BELOW;
1760           }
1761      }
1762
1763    ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
1764    e_remember_update(bd);
1765 }
1766
1767 EAPI void
1768 e_border_stack_above(E_Border *bd,
1769                      E_Border *above)
1770 {
1771    /* TODO: Should stack above allow the border to change level */
1772     E_Event_Border_Stack *ev;
1773     E_Border *last = NULL, *child;
1774     Eina_List *l;
1775
1776     E_OBJECT_CHECK(bd);
1777     E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1778
1779     ecore_x_window_shadow_tree_flush();
1780
1781     if (e_config->transient.raise)
1782       {
1783          EINA_LIST_REVERSE_FOREACH(bd->transients, l, child)
1784          {
1785             /* Don't stack iconic transients. If the user wants these shown,
1786              * thats another option.
1787              */
1788               if (!child->iconic)
1789                 {
1790                    if (last)
1791                      e_border_stack_below(child, last);
1792                    else
1793                      e_border_stack_above(child, above);
1794                    last = child;
1795                 }
1796          }
1797       }
1798
1799     ev = E_NEW(E_Event_Border_Stack, 1);
1800     ev->border = bd;
1801     e_object_ref(E_OBJECT(bd));
1802
1803     if (last)
1804       {
1805          e_container_border_stack_below(bd, last);
1806          ev->stack = last;
1807          e_object_ref(E_OBJECT(last));
1808          ev->type = E_STACKING_BELOW;
1809       }
1810     else
1811       {
1812          e_container_border_stack_above(bd, above);
1813          ev->stack = above;
1814          e_object_ref(E_OBJECT(above));
1815          ev->type = E_STACKING_ABOVE;
1816       }
1817
1818     ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
1819     e_remember_update(bd);
1820 }
1821
1822 EAPI void
1823 e_border_stack_below(E_Border *bd,
1824                      E_Border *below)
1825 {
1826    /* TODO: Should stack below allow the border to change level */
1827     E_Event_Border_Stack *ev;
1828     E_Border *last = NULL, *child;
1829     Eina_List *l;
1830
1831     E_OBJECT_CHECK(bd);
1832     E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1833
1834     ecore_x_window_shadow_tree_flush();
1835
1836     if (e_config->transient.lower)
1837       {
1838          EINA_LIST_REVERSE_FOREACH(bd->transients, l, child)
1839          {
1840             /* Don't stack iconic transients. If the user wants these shown,
1841              * thats another option.
1842              */
1843               if (!child->iconic)
1844                 {
1845                    if (last)
1846                      e_border_stack_below(child, last);
1847                    else
1848                      e_border_stack_below(child, below);
1849                    last = child;
1850                 }
1851          }
1852       }
1853
1854     ev = E_NEW(E_Event_Border_Stack, 1);
1855     ev->border = bd;
1856     e_object_ref(E_OBJECT(bd));
1857
1858     if (last)
1859       {
1860          e_container_border_stack_below(bd, last);
1861          ev->stack = last;
1862          e_object_ref(E_OBJECT(last));
1863          ev->type = E_STACKING_BELOW;
1864       }
1865     else
1866       {
1867          e_container_border_stack_below(bd, below);
1868          ev->stack = below;
1869          e_object_ref(E_OBJECT(below));
1870          ev->type = E_STACKING_BELOW;
1871       }
1872
1873     ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
1874     e_remember_update(bd);
1875 }
1876
1877 EAPI void
1878 e_border_focus_latest_set(E_Border *bd)
1879 {
1880    focus_stack = eina_list_remove(focus_stack, bd);
1881    focus_stack = eina_list_prepend(focus_stack, bd);
1882 }
1883
1884 EAPI void
1885 e_border_raise_latest_set(E_Border *bd)
1886 {
1887    raise_stack = eina_list_remove(raise_stack, bd);
1888    raise_stack = eina_list_prepend(raise_stack, bd);
1889 }
1890
1891 /*
1892  * Sets the focus to the given border if necessary
1893  * There are 3 cases of different focus_policy-configurations:
1894  *
1895  * - E_FOCUS_CLICK: just set the focus, the most simple one
1896  *
1897  * - E_FOCUS_MOUSE: focus is where the mouse is, so try to
1898  *   warp the pointer to the window. If this fails (because
1899  *   the pointer is already in the window), just set the focus.
1900  *
1901  * - E_FOCUS_SLOPPY: focus is where the mouse is or on the
1902  *   last window which was focused, if the mouse is on the
1903  *   desktop. So, we need to look if there is another window
1904  *   under the pointer and warp to pointer to the right
1905  *   one if so (also, we set the focus afterwards). In case
1906  *   there is no window under pointer, the pointer is on the
1907  *   desktop and so we just set the focus.
1908  *
1909  *
1910  * This function is to be called when setting the focus was not
1911  * explicitly triggered by the user (by moving the mouse or
1912  * clicking for example), but implicitly (by closing a window,
1913  * the last focused window should get focus).
1914  *
1915  */
1916 EAPI void
1917 e_border_focus_set_with_pointer(E_Border *bd)
1918 {
1919 #ifdef PRINT_LOTS_OF_DEBUG
1920    E_PRINT_BORDER_INFO(bd);
1921 #endif
1922    /* note: this is here as it seems there are enough apps that do not even
1923     * expect us to emulate a look of focus but not actually set x input
1924     * focus as we do - so simply abort any focuse set on such windows */
1925    /* be strict about accepting focus hint */
1926    if ((!bd->client.icccm.accepts_focus) &&
1927        (!bd->client.icccm.take_focus)) return;
1928    if (bd->lock_focus_out) return;
1929
1930    /* Try to grab the pointer to make sure it's not "in use" */
1931 /*
1932  * this causes problems as the grab can cause an in/out event (by grab) that
1933  * normally would be like a grab from a menu or something else and e gets into
1934  * a self-feeding loop. sorry - can't grab :(
1935    if (!ecore_x_pointer_grab(bd->zone->container->win))
1936      return;
1937  */
1938
1939    if (e_config->focus_policy == E_FOCUS_SLOPPY)
1940      {
1941         if (e_border_under_pointer_get(bd->desk, bd))
1942           {
1943              if (!e_border_pointer_warp_to_center(bd))
1944                {
1945                   e_border_focus_set(bd, 1, 1);
1946                }
1947           }
1948         else
1949           {
1950              e_border_focus_set(bd, 1, 1);
1951           }
1952      }
1953    else if (e_config->focus_policy == E_FOCUS_CLICK)
1954      {
1955         e_border_focus_set(bd, 1, 1);
1956      }
1957    else
1958    if (!e_border_pointer_warp_to_center(bd))
1959      {
1960         e_border_focus_set(bd, 1, 1);
1961      }
1962
1963    //ecore_x_pointer_ungrab();
1964 }
1965
1966 EAPI void
1967 e_border_focus_set(E_Border *bd,
1968                    int       focus,
1969                    int       set)
1970 {
1971    E_Border *unfocus = NULL;
1972
1973    E_OBJECT_CHECK(bd);
1974    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1975    /* note: this is here as it seems there are enough apps that do not even
1976     * expect us to emulate a look of focus but not actually set x input
1977     * focus as we do - so simply abort any focuse set on such windows */
1978    /* be strict about accepting focus hint */
1979    if ((!bd->client.icccm.accepts_focus) &&
1980        (!bd->client.icccm.take_focus))
1981      return;
1982    if ((set) && (focus) && (bd->lock_focus_out)) return;
1983    /* dont focus an iconified window. that's silly! */
1984    if (focus)
1985      {
1986         if (bd->iconic)
1987           return;
1988
1989         if (!bd->visible)
1990           return;
1991
1992         /* FIXME: hack for deskflip animation:
1993          * dont update focus when sliding previous desk */
1994         if ((!bd->sticky) && (bd->desk != e_desk_current_get(bd->desk->zone)))
1995           return;
1996
1997         /* TODO */
1998         /* if !set and no other window is focused 'revert focus when lost' */
1999      }
2000
2001    if ((bd->modal) && (bd->modal != bd) && (bd->modal->visible))
2002      {
2003         e_border_focus_set(bd->modal, focus, set);
2004         return;
2005      }
2006    else if ((bd->leader) && (bd->leader->modal) && (bd->leader->modal != bd))
2007      {
2008         e_border_focus_set(bd->leader->modal, focus, set);
2009         return;
2010      }
2011 #ifdef INOUTDEBUG_FOCUS
2012    printf("%s focus set %d %d\n", e_border_name_get(bd), focus, set);
2013 #endif
2014
2015    if ((set) && (focus))
2016      {
2017         if (bd->visible && bd->changes.visible)
2018           {
2019              bd->want_focus = 1;
2020              bd->changed = 1;
2021              return;
2022           }
2023         if ((!bd->focused) || (focus_next && (bd != eina_list_data_get(focus_next))))
2024           {
2025              Eina_List *l;
2026
2027              if ((l = eina_list_data_find_list(focus_next, bd)))
2028                focus_next = eina_list_promote_list(focus_next, l);
2029              else
2030                focus_next = eina_list_prepend(focus_next, bd);
2031              return;
2032           }
2033      }
2034    else if ((focus) && (!bd->focused))
2035      {
2036         E_Event_Border_Focus_In *ev;
2037
2038         if (focused)
2039           unfocus = focused;
2040
2041         bd->focused = 1;
2042         focused = bd;
2043
2044         e_focus_event_focus_in(bd);
2045         e_border_focus_latest_set(bd);
2046         e_hints_active_window_set(bd->zone->container->manager, bd);
2047
2048         edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
2049         if (bd->icon_object)
2050           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
2051
2052         ev = E_NEW(E_Event_Border_Focus_In, 1);
2053         ev->border = bd;
2054         e_object_ref(E_OBJECT(bd));
2055
2056         ecore_event_add(E_EVENT_BORDER_FOCUS_IN, ev,
2057                         _e_border_event_border_focus_in_free, NULL);
2058      }
2059    else if ((!focus) && (bd->want_focus))
2060      {
2061         if ((bd->visible) && (bd->changes.visible))
2062           {
2063              bd->want_focus = 0;
2064              bd->changed = 1;
2065              return;
2066           }
2067      }
2068    else if ((!focus) && (bd->focused))
2069      {
2070         unfocus = bd;
2071
2072         /* should always be the case. anyway */
2073         if (bd == focused)
2074           focused = NULL;
2075
2076         if (set)
2077           e_grabinput_focus(bd->zone->container->bg_win, E_FOCUS_METHOD_PASSIVE);
2078      }
2079
2080    if ((unfocus) &&
2081        (!e_object_is_del(E_OBJECT(unfocus)) &&
2082         (e_object_ref_get(E_OBJECT(unfocus)) > 0)))
2083      {
2084         E_Event_Border_Focus_Out *ev;
2085
2086         bd = unfocus;
2087         bd->focused = 0;
2088         e_focus_event_focus_out(bd);
2089
2090         if (bd->raise_timer)
2091           ecore_timer_del(bd->raise_timer);
2092         bd->raise_timer = NULL;
2093
2094         edje_object_signal_emit(bd->bg_object, "e,state,unfocused", "e");
2095         if (bd->icon_object)
2096           edje_object_signal_emit(bd->icon_object, "e,state,unfocused", "e");
2097
2098         ev = E_NEW(E_Event_Border_Focus_Out, 1);
2099         ev->border = bd;
2100         e_object_ref(E_OBJECT(bd));
2101
2102         ecore_event_add(E_EVENT_BORDER_FOCUS_OUT, ev,
2103                         _e_border_event_border_focus_out_free, NULL);
2104      }
2105 }
2106
2107 EAPI void
2108 e_border_shade(E_Border   *bd,
2109                E_Direction dir)
2110 {
2111    E_Event_Border_Resize *ev;
2112
2113    E_OBJECT_CHECK(bd);
2114    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2115    if ((bd->shaded) || (bd->shading) || (bd->fullscreen) ||
2116        ((bd->maximized) && (!e_config->allow_manip))) return;
2117    if ((bd->client.border.name) &&
2118        (!strcmp("borderless", bd->client.border.name))) return;
2119
2120    ecore_x_window_shadow_tree_flush();
2121
2122    bd->shade.x = bd->x;
2123    bd->shade.y = bd->y;
2124    bd->shade.dir = dir;
2125
2126    e_hints_window_shaded_set(bd, 1);
2127    e_hints_window_shade_direction_set(bd, dir);
2128
2129    if (e_config->border_shade_animate)
2130      {
2131         bd->shade.start = ecore_loop_time_get();
2132         bd->shading = 1;
2133         bd->changes.shading = 1;
2134         bd->changed = 1;
2135
2136         if (bd->shade.dir == E_DIRECTION_UP ||
2137             bd->shade.dir == E_DIRECTION_LEFT)
2138           ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_SW);
2139         else
2140           ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NE);
2141
2142         bd->shade.anim = ecore_animator_add(_e_border_shade_animator, bd);
2143         edje_object_signal_emit(bd->bg_object, "e,state,shading", "e");
2144      }
2145    else
2146      {
2147         if (bd->shade.dir == E_DIRECTION_UP)
2148           {
2149              bd->h = bd->client_inset.t + bd->client_inset.b;
2150           }
2151         else if (bd->shade.dir == E_DIRECTION_DOWN)
2152           {
2153              bd->h = bd->client_inset.t + bd->client_inset.b;
2154              bd->y = bd->y + bd->client.h;
2155              bd->changes.pos = 1;
2156           }
2157         else if (bd->shade.dir == E_DIRECTION_LEFT)
2158           {
2159              bd->w = bd->client_inset.l + bd->client_inset.r;
2160           }
2161         else if (bd->shade.dir == E_DIRECTION_RIGHT)
2162           {
2163              bd->w = bd->client_inset.l + bd->client_inset.r;
2164              bd->x = bd->x + bd->client.w;
2165              bd->changes.pos = 1;
2166           }
2167
2168         if ((bd->shaped) || (bd->client.shaped))
2169           {
2170              bd->need_shape_merge = 1;
2171              bd->need_shape_export = 1;
2172           }
2173         if (bd->shaped_input)
2174           {
2175              bd->need_shape_merge = 1;
2176           }
2177
2178         bd->changes.size = 1;
2179         bd->shaded = 1;
2180         bd->changes.shaded = 1;
2181         bd->changed = 1;
2182         edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
2183         e_border_frame_recalc(bd);
2184         ev = E_NEW(E_Event_Border_Resize, 1);
2185         ev->border = bd;
2186         /* The resize is added in the animator when animation complete */
2187         /* For non-animated, we add it immediately with the new size */
2188         e_object_ref(E_OBJECT(bd));
2189         //           e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
2190         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
2191      }
2192
2193    e_remember_update(bd);
2194 }
2195
2196 EAPI void
2197 e_border_unshade(E_Border   *bd,
2198                  E_Direction dir)
2199 {
2200    E_Event_Border_Resize *ev;
2201
2202    E_OBJECT_CHECK(bd);
2203    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2204    if ((!bd->shaded) || (bd->shading))
2205      return;
2206
2207    ecore_x_window_shadow_tree_flush();
2208
2209    bd->shade.dir = dir;
2210
2211    e_hints_window_shaded_set(bd, 0);
2212    e_hints_window_shade_direction_set(bd, dir);
2213
2214    if (bd->shade.dir == E_DIRECTION_UP ||
2215        bd->shade.dir == E_DIRECTION_LEFT)
2216      {
2217         bd->shade.x = bd->x;
2218         bd->shade.y = bd->y;
2219      }
2220    else
2221      {
2222         bd->shade.x = bd->x - bd->client.w;
2223         bd->shade.y = bd->y - bd->client.h;
2224      }
2225    if (e_config->border_shade_animate)
2226      {
2227         bd->shade.start = ecore_loop_time_get();
2228         bd->shading = 1;
2229         bd->changes.shading = 1;
2230         bd->changed = 1;
2231
2232         if (bd->shade.dir == E_DIRECTION_UP)
2233           {
2234              ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_SW);
2235              ecore_x_window_move_resize(bd->client.win, 0,
2236                                         bd->h - (bd->client_inset.t + bd->client_inset.b) -
2237                                         bd->client.h,
2238                                         bd->client.w, bd->client.h);
2239           }
2240         else if (bd->shade.dir == E_DIRECTION_LEFT)
2241           {
2242              ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_SW);
2243              ecore_x_window_move_resize(bd->client.win,
2244                                         bd->w - (bd->client_inset.l + bd->client_inset.r) -
2245                                         bd->client.h,
2246                                         0, bd->client.w, bd->client.h);
2247           }
2248         else
2249           ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NE);
2250
2251         bd->shade.anim = ecore_animator_add(_e_border_shade_animator, bd);
2252         edje_object_signal_emit(bd->bg_object, "e,state,unshading", "e");
2253      }
2254    else
2255      {
2256         if (bd->shade.dir == E_DIRECTION_UP)
2257           {
2258              bd->h = bd->client_inset.t + bd->client.h + bd->client_inset.b;
2259           }
2260         else if (bd->shade.dir == E_DIRECTION_DOWN)
2261           {
2262              bd->h = bd->client_inset.t + bd->client.h + bd->client_inset.b;
2263              bd->y = bd->y - bd->client.h;
2264              bd->changes.pos = 1;
2265           }
2266         else if (bd->shade.dir == E_DIRECTION_LEFT)
2267           {
2268              bd->w = bd->client_inset.l + bd->client.w + bd->client_inset.r;
2269           }
2270         else if (bd->shade.dir == E_DIRECTION_RIGHT)
2271           {
2272              bd->w = bd->client_inset.l + bd->client.w + bd->client_inset.r;
2273              bd->x = bd->x - bd->client.w;
2274              bd->changes.pos = 1;
2275           }
2276         if ((bd->shaped) || (bd->client.shaped))
2277           {
2278              bd->need_shape_merge = 1;
2279              bd->need_shape_export = 1;
2280           }
2281         if (bd->shaped_input)
2282           {
2283              bd->need_shape_merge = 1;
2284           }
2285
2286         bd->changes.size = 1;
2287         bd->shaded = 0;
2288         bd->changes.shaded = 1;
2289         bd->changed = 1;
2290         edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
2291         e_border_frame_recalc(bd);
2292         ev = E_NEW(E_Event_Border_Resize, 1);
2293         ev->border = bd;
2294         /* The resize is added in the animator when animation complete */
2295         /* For non-animated, we add it immediately with the new size */
2296         e_object_ref(E_OBJECT(bd));
2297         //           e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
2298         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
2299      }
2300
2301    e_remember_update(bd);
2302 }
2303
2304 EAPI void
2305 e_border_maximize(E_Border  *bd,
2306                   E_Maximize max)
2307 {
2308    E_OBJECT_CHECK(bd);
2309    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2310
2311    if (!(max & E_MAXIMIZE_DIRECTION)) max |= E_MAXIMIZE_BOTH;
2312
2313    if ((bd->shaded) || (bd->shading)) return;
2314    ecore_x_window_shadow_tree_flush();
2315    if (bd->fullscreen)
2316      e_border_unfullscreen(bd);
2317    /* Only allow changes in vertical/ horizontal maximization */
2318    if (((bd->maximized & E_MAXIMIZE_DIRECTION) == (max & E_MAXIMIZE_DIRECTION)) ||
2319        ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)) return;
2320    if (bd->new_client)
2321      {
2322         bd->need_maximize = 1;
2323         bd->maximized &= ~E_MAXIMIZE_TYPE;
2324         bd->maximized |= max;
2325         return;
2326      }
2327
2328    {
2329       int x1, y1, x2, y2;
2330       int w, h, pw, ph;
2331       int zx, zy, zw, zh;
2332
2333       zx = zy = zw = zh = 0;
2334
2335       bd->pre_res_change.valid = 0;
2336       if (!(bd->maximized & E_MAXIMIZE_HORIZONTAL))
2337         {
2338            /* Horizontal hasn't been set */
2339            bd->saved.x = bd->x - bd->zone->x;
2340            bd->saved.w = bd->w;
2341         }
2342       if (!(bd->maximized & E_MAXIMIZE_VERTICAL))
2343         {
2344            /* Vertical hasn't been set */
2345            bd->saved.y = bd->y - bd->zone->y;
2346            bd->saved.h = bd->h;
2347         }
2348       bd->saved.zone = bd->zone->num;
2349       e_hints_window_size_set(bd);
2350
2351       e_border_raise(bd);
2352       switch (max & E_MAXIMIZE_TYPE)
2353         {
2354          case E_MAXIMIZE_NONE:
2355            /* Ignore */
2356            max = E_MAXIMIZE_NONE;
2357            break;
2358
2359          case E_MAXIMIZE_FULLSCREEN:
2360            w = bd->zone->w;
2361            h = bd->zone->h;
2362
2363            if (bd->bg_object)
2364              {
2365                 Evas_Coord cx, cy, cw, ch;
2366
2367                 edje_object_signal_emit(bd->bg_object, "e,action,maximize,fullscreen", "e");
2368
2369                 evas_object_resize(bd->bg_object, w, h);
2370                 edje_object_calc_force(bd->bg_object);
2371                 edje_object_part_geometry_get(bd->bg_object, "e.swallow.client", &cx, &cy, &cw, &ch);
2372                 bd->client_inset.l = cx;
2373                 bd->client_inset.r = w - (cx + cw);
2374                 bd->client_inset.t = cy;
2375                 bd->client_inset.b = h - (cy + ch);
2376                 ecore_x_netwm_frame_size_set(bd->client.win,
2377                                              bd->client_inset.l, bd->client_inset.r,
2378                                              bd->client_inset.t, bd->client_inset.b);
2379                 ecore_x_e_frame_size_set(bd->client.win,
2380                                          bd->client_inset.l, bd->client_inset.r,
2381                                          bd->client_inset.t, bd->client_inset.b);
2382              }
2383            e_border_resize_limit(bd, &w, &h);
2384            /* center x-direction */
2385            x1 = bd->zone->x + (bd->zone->w - w) / 2;
2386            /* center y-direction */
2387            y1 = bd->zone->y + (bd->zone->h - h) / 2;
2388
2389            if ((max & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)
2390              e_border_move_resize(bd, x1, y1, w, h);
2391            else if ((max & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
2392              e_border_move_resize(bd, bd->x, y1, bd->w, h);
2393            else if ((max & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
2394              e_border_move_resize(bd, x1, bd->y, w, bd->h);
2395            break;
2396
2397          case E_MAXIMIZE_SMART:
2398          case E_MAXIMIZE_EXPAND:
2399            if (bd->zone)
2400              e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
2401
2402            if (bd->w < zw)
2403              w = bd->w;
2404            else
2405              w = zw;
2406
2407            if (bd->h < zh)
2408              h = bd->h;
2409            else
2410              h = zh;
2411
2412            if (bd->x < zx) // window left not useful coordinates
2413              x1 = zx;
2414            else if (bd->x + bd->w > zx + zw) // window right not useful coordinates
2415              x1 = zx + zw - bd->w;
2416            else // window normal position
2417              x1 = bd->x;
2418
2419            if (bd->y < zy) // window top not useful coordinates
2420              y1 = zy;
2421            else if (bd->y + bd->h > zy + zh) // window bottom not useful coordinates
2422              y1 = zy + zh - bd->h;
2423            else // window normal position
2424              y1 = bd->y;
2425
2426            if ((max & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)
2427              e_border_move_resize(bd, zx, zy, zw, zh);
2428            else if ((max & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
2429              e_border_move_resize(bd, x1, zy, w, zh);
2430            else if ((max & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
2431              e_border_move_resize(bd, zx, y1, zw, h);
2432            edje_object_signal_emit(bd->bg_object, "e,action,maximize", "e");
2433            break;
2434
2435          case E_MAXIMIZE_FILL:
2436            x1 = bd->zone->x;
2437            y1 = bd->zone->y;
2438            x2 = bd->zone->x + bd->zone->w;
2439            y2 = bd->zone->y + bd->zone->h;
2440
2441            /* walk through all shelves */
2442            e_maximize_border_shelf_fill(bd, &x1, &y1, &x2, &y2, max);
2443
2444            /* walk through all windows */
2445            e_maximize_border_border_fill(bd, &x1, &y1, &x2, &y2, max);
2446
2447            w = x2 - x1;
2448            h = y2 - y1;
2449            pw = w;
2450            ph = h;
2451            e_border_resize_limit(bd, &w, &h);
2452            /* center x-direction */
2453            x1 = x1 + (pw - w) / 2;
2454            /* center y-direction */
2455            y1 = y1 + (ph - h) / 2;
2456            if ((max & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)
2457              e_border_move_resize(bd, x1, y1, w, h);
2458            else if ((max & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
2459              e_border_move_resize(bd, bd->x, y1, bd->w, h);
2460            else if ((max & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
2461              e_border_move_resize(bd, x1, bd->y, w, bd->h);
2462            break;
2463         }
2464
2465       /* Remove previous type */
2466       bd->maximized &= ~E_MAXIMIZE_TYPE;
2467       /* Add new maximization. It must be added, so that VERTICAL + HORIZONTAL == BOTH */
2468       bd->maximized |= max;
2469
2470       e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
2471                                    bd->maximized & E_MAXIMIZE_VERTICAL);
2472    }
2473    e_remember_update(bd);
2474 }
2475
2476 EAPI void
2477 e_border_unmaximize(E_Border  *bd,
2478                     E_Maximize max)
2479 {
2480    E_OBJECT_CHECK(bd);
2481    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2482    if (!(max & E_MAXIMIZE_DIRECTION))
2483      {
2484         printf("BUG: Unmaximize call without direction!\n");
2485         return;
2486      }
2487
2488    if ((bd->shaded) || (bd->shading)) return;
2489    ecore_x_window_shadow_tree_flush();
2490    /* Remove directions not used */
2491    max &= (bd->maximized & E_MAXIMIZE_DIRECTION);
2492    /* Can only remove existing maximization directions */
2493    if (!max) return;
2494    if (bd->maximized & E_MAXIMIZE_TYPE)
2495      {
2496         bd->pre_res_change.valid = 0;
2497         bd->need_maximize = 0;
2498
2499         if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN)
2500           {
2501              if (bd->bg_object)
2502                {
2503                   Evas_Coord cx, cy, cw, ch;
2504
2505                   edje_object_signal_emit(bd->bg_object, "e,action,unmaximize,fullscreen", "e");
2506
2507                   evas_object_resize(bd->bg_object, 1000, 1000);
2508                   edje_object_calc_force(bd->bg_object);
2509                   edje_object_part_geometry_get(bd->bg_object, "e.swallow.client", &cx, &cy, &cw, &ch);
2510                   bd->client_inset.l = cx;
2511                   bd->client_inset.r = 1000 - (cx + cw);
2512                   bd->client_inset.t = cy;
2513                   bd->client_inset.b = 1000 - (cy + ch);
2514                   ecore_x_netwm_frame_size_set(bd->client.win,
2515                                                bd->client_inset.l, bd->client_inset.r,
2516                                                bd->client_inset.t, bd->client_inset.b);
2517                   ecore_x_e_frame_size_set(bd->client.win,
2518                                            bd->client_inset.l, bd->client_inset.r,
2519                                            bd->client_inset.t, bd->client_inset.b);
2520                }
2521
2522              bd->maximized = E_MAXIMIZE_NONE;
2523              _e_border_move_resize_internal(bd,
2524                                             bd->zone->x + bd->saved.x,
2525                                             bd->zone->y + bd->saved.y,
2526                                             bd->saved.w, bd->saved.h, 0, 1);
2527              bd->saved.x = bd->saved.y = bd->saved.w = bd->saved.h = 0;
2528              e_hints_window_size_unset(bd);
2529           }
2530         else
2531           {
2532              int w, h, x, y;
2533
2534              w = bd->w;
2535              h = bd->h;
2536              x = bd->x;
2537              y = bd->y;
2538
2539              if (max & E_MAXIMIZE_VERTICAL)
2540                {
2541                   /* Remove vertical */
2542                   h = bd->saved.h;
2543                   y = bd->saved.y + bd->zone->y;
2544                   bd->saved.h = bd->saved.y = 0;
2545                   bd->maximized &= ~E_MAXIMIZE_VERTICAL;
2546                }
2547              if (max & E_MAXIMIZE_HORIZONTAL)
2548                {
2549                   /* Remove horizontal */
2550                   w = bd->saved.w;
2551                   x = bd->saved.x + bd->zone->x;
2552                   bd->saved.w = bd->saved.x = 0;
2553                   bd->maximized &= ~E_MAXIMIZE_HORIZONTAL;
2554                }
2555
2556              e_border_resize_limit(bd, &w, &h);
2557
2558              if (!(bd->maximized & E_MAXIMIZE_DIRECTION))
2559                {
2560                   bd->maximized = E_MAXIMIZE_NONE;
2561                    _e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
2562                   e_hints_window_size_unset(bd);
2563                   edje_object_signal_emit(bd->bg_object, "e,action,unmaximize", "e");
2564                }
2565              else
2566                {
2567                  _e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
2568                  e_hints_window_size_set(bd);
2569                }
2570           }
2571         e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
2572                                      bd->maximized & E_MAXIMIZE_VERTICAL);
2573      }
2574    e_remember_update(bd);
2575 }
2576
2577 EAPI void
2578 e_border_fullscreen(E_Border    *bd,
2579                     E_Fullscreen policy)
2580 {
2581    E_Event_Border_Fullscreen *ev;
2582
2583    E_OBJECT_CHECK(bd);
2584    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2585
2586    if ((bd->shaded) || (bd->shading)) return;
2587    ecore_x_window_shadow_tree_flush();
2588    if (bd->new_client)
2589      {
2590         bd->need_fullscreen = 1;
2591         return;
2592      }
2593    if (!bd->fullscreen)
2594      {
2595         bd->pre_res_change.valid = 0;
2596
2597         bd->saved.x = bd->x - bd->zone->x;
2598         bd->saved.y = bd->y - bd->zone->y;
2599         bd->saved.w = bd->client.w;
2600         bd->saved.h = bd->client.h;
2601         bd->saved.maximized = bd->maximized;
2602         bd->saved.zone = bd->zone->num;
2603
2604         if (bd->maximized)
2605           e_border_unmaximize(bd, E_MAXIMIZE_BOTH);
2606         e_hints_window_size_set(bd);
2607
2608         bd->client_inset.l = 0;
2609         bd->client_inset.r = 0;
2610         bd->client_inset.t = 0;
2611         bd->client_inset.b = 0;
2612
2613         bd->desk->fullscreen_borders++;
2614
2615         /* e_zone_fullscreen_set(bd->zone, 1); */
2616         if (!e_config->allow_above_fullscreen)
2617           e_border_layer_set(bd, 200);
2618
2619         if ((eina_list_count(bd->zone->container->zones) > 1) || (policy == E_FULLSCREEN_RESIZE) || (!ecore_x_randr_query()))
2620           {
2621              e_border_move_resize(bd, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h);
2622           }
2623         else if (policy == E_FULLSCREEN_ZOOM)
2624           {
2625              Ecore_X_Randr_Screen_Size_MM *sizes;
2626              int num_sizes, i, best_size_index = 0;
2627
2628              ecore_x_randr_screen_primary_output_current_size_get(bd->zone->container->manager->root, &screen_size.width, &screen_size.height, NULL, NULL, NULL);
2629              sizes = ecore_x_randr_screen_primary_output_sizes_get(bd->zone->container->manager->root, &num_sizes);
2630              if (sizes)
2631                {
2632                   Ecore_X_Randr_Screen_Size best_size = { -1, -1 };
2633                   int best_dist = INT_MAX, dist;
2634
2635                   for (i = 0; i < num_sizes; i++)
2636                     {
2637                        if ((sizes[i].width > bd->w) && (sizes[i].height > bd->h))
2638                          {
2639                             dist = (sizes[i].width * sizes[i].height) - (bd->w * bd->h);
2640                             if (dist < best_dist)
2641                               {
2642                                  best_size.width = sizes[i].width;
2643                                  best_size.height = sizes[i].height;
2644                                  best_dist = dist;
2645                                  best_size_index = i;
2646                               }
2647                          }
2648                     }
2649                   if (((best_size.width != -1) && (best_size.height != -1)) &&
2650                       ((best_size.width != screen_size.width) ||
2651                        (best_size.height != screen_size.height)))
2652                     {
2653                        if (ecore_x_randr_screen_primary_output_size_set(bd->zone->container->manager->root,
2654                                                                         best_size_index))
2655                          screen_size_index = best_size_index;
2656                        e_border_move_resize(bd, 0, 0, best_size.width, best_size.height);
2657                     }
2658                   else
2659                     {
2660                        screen_size.width = -1;
2661                        screen_size.height = -1;
2662                        e_border_move_resize(bd, 0, 0, bd->zone->w, bd->zone->h);
2663                     }
2664                   free(sizes);
2665                }
2666              else
2667                e_border_move_resize(bd, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h);
2668           }
2669         bd->fullscreen = 1;
2670
2671         e_hints_window_fullscreen_set(bd, 1);
2672         e_hints_window_size_unset(bd);
2673         bd->client.border.changed = 1;
2674         bd->changed = 1;
2675      }
2676
2677    ev = E_NEW(E_Event_Border_Fullscreen, 1);
2678    ev->border = bd;
2679    e_object_ref(E_OBJECT(bd));
2680 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_fullscreen_event");
2681    ecore_event_add(E_EVENT_BORDER_FULLSCREEN, ev, _e_border_event_border_fullscreen_free, NULL);
2682
2683    e_remember_update(bd);
2684 }
2685
2686 EAPI void
2687 e_border_unfullscreen(E_Border *bd)
2688 {
2689    E_Event_Border_Unfullscreen *ev;
2690
2691    E_OBJECT_CHECK(bd);
2692    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2693    if ((bd->shaded) || (bd->shading)) return;
2694    ecore_x_window_shadow_tree_flush();
2695    if (bd->fullscreen)
2696      {
2697         bd->pre_res_change.valid = 0;
2698         bd->fullscreen = 0;
2699         bd->need_fullscreen = 0;
2700         bd->desk->fullscreen_borders--;
2701
2702         if ((screen_size.width != -1) && (screen_size.height != -1))
2703           {
2704              ecore_x_randr_screen_primary_output_size_set(bd->zone->container->manager->root, screen_size_index);
2705                                                           screen_size.width = -1;
2706                                                           screen_size.height = -1;
2707           }
2708         e_border_move_resize(bd,
2709                              bd->saved.x + bd->zone->x,
2710                              bd->saved.y + bd->zone->y,
2711                              bd->saved.w, bd->saved.h);
2712
2713         if (bd->saved.maximized)
2714           e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) |
2715                             bd->saved.maximized);
2716
2717         e_border_layer_set(bd, bd->saved.layer);
2718
2719         e_hints_window_fullscreen_set(bd, 0);
2720         bd->client.border.changed = 1;
2721         bd->changed = 1;
2722      }
2723
2724    ev = E_NEW(E_Event_Border_Unfullscreen, 1);
2725    ev->border = bd;
2726    e_object_ref(E_OBJECT(bd));
2727 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_unfullscreen_event");
2728    ecore_event_add(E_EVENT_BORDER_UNFULLSCREEN, ev, _e_border_event_border_unfullscreen_free, NULL);
2729
2730    e_remember_update(bd);
2731 }
2732
2733 EAPI void
2734 e_border_iconify(E_Border *bd)
2735 {
2736    E_Event_Border_Iconify *ev;
2737    unsigned int iconic;
2738
2739    E_OBJECT_CHECK(bd);
2740    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2741    if (bd->shading) return;
2742    ecore_x_window_shadow_tree_flush();
2743    if (!bd->iconic)
2744      {
2745         bd->iconic = 1;
2746         e_border_hide(bd, 1);
2747         if (bd->fullscreen) bd->desk->fullscreen_borders--;
2748         edje_object_signal_emit(bd->bg_object, "e,action,iconify", "e");
2749      }
2750    iconic = 1;
2751    e_hints_window_iconic_set(bd);
2752    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &iconic, 1);
2753
2754    ev = E_NEW(E_Event_Border_Iconify, 1);
2755    ev->border = bd;
2756    e_object_ref(E_OBJECT(bd));
2757 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_iconify_event");
2758    ecore_event_add(E_EVENT_BORDER_ICONIFY, ev, _e_border_event_border_iconify_free, NULL);
2759
2760    if (e_config->transient.iconify)
2761      {
2762         Eina_List *l;
2763         E_Border *child;
2764
2765         EINA_LIST_FOREACH(bd->transients, l, child)
2766           {
2767              e_border_iconify(child);
2768           }
2769      }
2770    e_remember_update(bd);
2771 }
2772
2773 EAPI void
2774 e_border_uniconify(E_Border *bd)
2775 {
2776    E_Desk *desk;
2777    E_Event_Border_Uniconify *ev;
2778    unsigned int iconic;
2779
2780    E_OBJECT_CHECK(bd);
2781    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2782    if (bd->shading) return;
2783    ecore_x_window_shadow_tree_flush();
2784    e_border_show(bd);
2785    if (bd->iconic)
2786      {
2787         bd->iconic = 0;
2788         if (bd->fullscreen) bd->desk->fullscreen_borders++;
2789         desk = e_desk_current_get(bd->desk->zone);
2790         e_border_desk_set(bd, desk);
2791         e_border_raise(bd);
2792         edje_object_signal_emit(bd->bg_object, "e,action,uniconify", "e");
2793      }
2794    iconic = 0;
2795    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &iconic, 1);
2796
2797    ev = E_NEW(E_Event_Border_Uniconify, 1);
2798    ev->border = bd;
2799    e_object_ref(E_OBJECT(bd));
2800 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_uniconify_event");
2801    ecore_event_add(E_EVENT_BORDER_UNICONIFY, ev, _e_border_event_border_uniconify_free, NULL);
2802
2803    if (e_config->transient.iconify)
2804      {
2805         Eina_List *l;
2806         E_Border *child;
2807
2808         EINA_LIST_FOREACH(bd->transients, l, child)
2809           {
2810              e_border_uniconify(child);
2811           }
2812      }
2813    e_remember_update(bd);
2814 }
2815
2816 EAPI void
2817 e_border_stick(E_Border *bd)
2818 {
2819    E_Event_Border_Stick *ev;
2820
2821    E_OBJECT_CHECK(bd);
2822    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2823    if (bd->sticky) return;
2824    bd->sticky = 1;
2825    e_hints_window_sticky_set(bd, 1);
2826    e_border_show(bd);
2827
2828    if (e_config->transient.desktop)
2829      {
2830         Eina_List *l;
2831         E_Border *child;
2832         EINA_LIST_FOREACH(bd->transients, l, child)
2833           {
2834              child->sticky = 1;
2835              e_hints_window_sticky_set(child, 1);
2836              e_border_show(child);
2837           }
2838      }
2839
2840    edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
2841    ev = E_NEW(E_Event_Border_Stick, 1);
2842    ev->border = bd;
2843    e_object_ref(E_OBJECT(bd));
2844 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_stick_event");
2845    ecore_event_add(E_EVENT_BORDER_STICK, ev, _e_border_event_border_stick_free, NULL);
2846    e_remember_update(bd);
2847 }
2848
2849 EAPI void
2850 e_border_unstick(E_Border *bd)
2851 {
2852    E_Event_Border_Unstick *ev;
2853
2854    E_OBJECT_CHECK(bd);
2855    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2856    /* Set the desk before we unstick the border */
2857    if (!bd->sticky) return;
2858    bd->sticky = 0;
2859    e_hints_window_sticky_set(bd, 0);
2860
2861    if (e_config->transient.desktop)
2862      {
2863         Eina_List *l;
2864         E_Border *child;
2865         EINA_LIST_FOREACH(bd->transients, l, child)
2866           {
2867              child->sticky = 0;
2868              e_hints_window_sticky_set(child, 0);
2869           }
2870      }
2871
2872    edje_object_signal_emit(bd->bg_object, "e,state,unsticky", "e");
2873    ev = E_NEW(E_Event_Border_Unstick, 1);
2874    ev->border = bd;
2875    e_object_ref(E_OBJECT(bd));
2876 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_unstick_event");
2877    ecore_event_add(E_EVENT_BORDER_UNSTICK, ev, _e_border_event_border_unstick_free, NULL);
2878
2879    e_border_desk_set(bd, e_desk_current_get(bd->zone));
2880    e_remember_update(bd);
2881 }
2882
2883 EAPI void
2884 e_border_pinned_set(E_Border *bd,
2885                     int       set)
2886 {
2887    int layer;
2888    int stacking;
2889
2890    if (bd)
2891      {
2892         bd->borderless = set;
2893         bd->user_skip_winlist = set;
2894         if (set)
2895           {
2896              layer = 50;
2897              stacking = E_STACKING_BELOW;
2898           }
2899         else
2900           {
2901              layer = 100;
2902              stacking = E_STACKING_NONE;
2903           }
2904
2905         e_border_layer_set(bd, layer);
2906         e_hints_window_stacking_set(bd, stacking);
2907
2908         bd->client.border.changed = 1;
2909         bd->changed = 1;
2910      }
2911 }
2912
2913 EAPI E_Border *
2914 e_border_find_by_client_window(Ecore_X_Window win)
2915 {
2916    E_Border *bd;
2917
2918    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
2919    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
2920        (bd->client.win == win))
2921      return bd;
2922    return NULL;
2923 }
2924
2925 EAPI E_Border *
2926 e_border_find_all_by_client_window(Ecore_X_Window win)
2927 {
2928    E_Border *bd;
2929
2930    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
2931    if ((bd) && (bd->client.win == win))
2932      return bd;
2933    return NULL;
2934 }
2935
2936 EAPI E_Border *
2937 e_border_find_by_frame_window(Ecore_X_Window win)
2938 {
2939    E_Border *bd;
2940
2941    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
2942    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
2943        (bd->bg_win == win))
2944      return bd;
2945    return NULL;
2946 }
2947
2948 EAPI E_Border *
2949 e_border_find_by_window(Ecore_X_Window win)
2950 {
2951    E_Border *bd;
2952
2953    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
2954    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
2955        (bd->win == win))
2956      return bd;
2957    return NULL;
2958 }
2959
2960 EAPI E_Border *
2961 e_border_find_by_alarm(Ecore_X_Sync_Alarm alarm)
2962 {
2963    Eina_List *l;
2964    E_Border *bd;
2965
2966    EINA_LIST_FOREACH(borders, l, bd)
2967      {
2968         if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
2969             (bd->client.netwm.sync.alarm == alarm))
2970           return bd;
2971      }
2972    return NULL;
2973 }
2974
2975 EAPI E_Border *
2976 e_border_focused_get(void)
2977 {
2978    return focused;
2979 }
2980
2981 static void
2982 _e_border_shape_input_rectangle_set(E_Border* bd)
2983 {
2984    if (!bd) return;
2985
2986    if ((bd->visible) && (bd->shaped_input))
2987      {
2988         Ecore_X_Rectangle rects[4];
2989         Ecore_X_Window twin, twin2;
2990         int x, y;
2991
2992         twin = ecore_x_window_override_new(bd->zone->container->scratch_win,
2993                                            0, 0, bd->w, bd->h);
2994         rects[0].x = 0;
2995         rects[0].y = 0;
2996         rects[0].width = bd->w;
2997         rects[0].height = bd->client_inset.t;
2998         rects[1].x = 0;
2999         rects[1].y = bd->client_inset.t;
3000         rects[1].width = bd->client_inset.l;
3001         rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
3002         rects[2].x = bd->w - bd->client_inset.r;
3003         rects[2].y = bd->client_inset.t;
3004         rects[2].width = bd->client_inset.r;
3005         rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
3006         rects[3].x = 0;
3007         rects[3].y = bd->h - bd->client_inset.b;
3008         rects[3].width = bd->w;
3009         rects[3].height = bd->client_inset.b;
3010         ecore_x_window_shape_input_rectangles_set(twin, rects, 4);
3011
3012         twin2 = ecore_x_window_override_new
3013            (bd->zone->container->scratch_win, 0, 0,
3014                bd->w - bd->client_inset.l - bd->client_inset.r,
3015                bd->h - bd->client_inset.t - bd->client_inset.b);
3016         x = 0;
3017         y = 0;
3018         if ((bd->shading) || (bd->shaded))
3019           {
3020              if (bd->shade.dir == E_DIRECTION_UP)
3021                 y = bd->h - bd->client_inset.t - bd->client_inset.b -
3022                 bd->client.h;
3023              else if (bd->shade.dir == E_DIRECTION_LEFT)
3024                 x = bd->w - bd->client_inset.l - bd->client_inset.r -
3025                 bd->client.w;
3026           }
3027         ecore_x_window_shape_input_window_set_xy(twin2, bd->client.win,
3028                                                  x, y);
3029         ecore_x_window_shape_input_rectangle_clip(twin2, 0, 0,
3030                                                   bd->w - bd->client_inset.l - bd->client_inset.r,
3031                                                   bd->h - bd->client_inset.t - bd->client_inset.b);
3032         ecore_x_window_shape_input_window_add_xy(twin, twin2,
3033                                                  bd->client_inset.l,
3034                                                  bd->client_inset.t);
3035         ecore_x_window_shape_input_window_set(bd->win, twin);
3036         ecore_x_window_free(twin2);
3037         ecore_x_window_free(twin);
3038      }
3039    else
3040      {
3041         if (bd->visible) // not shaped input
3042           {
3043              if (!bd->comp_hidden)
3044                 ecore_x_composite_window_events_enable(bd->win);
3045              else
3046                 ecore_x_composite_window_events_disable(bd->win);
3047           }
3048         else
3049           {
3050              if (!e_manager_comp_evas_get(bd->zone->container->manager))
3051                 ecore_x_composite_window_events_enable(bd->win);
3052              else
3053                 ecore_x_composite_window_events_disable(bd->win);
3054           }
3055      }
3056 }
3057
3058 EAPI void
3059 e_border_idler_before(void)
3060 {
3061    Eina_List *ml, *cl;
3062    E_Manager *man;
3063    E_Container *con;
3064
3065    if (!borders)
3066      return;
3067
3068    EINA_LIST_FOREACH(e_manager_list(), ml, man)
3069      {
3070         EINA_LIST_FOREACH(man->containers, cl, con)
3071           {
3072              E_Border_List *bl;
3073              E_Border *bd;
3074
3075              // pass 1 - eval0. fetch properties on new or on change and
3076              // call hooks to decide what to do - maybe move/resize
3077              bl = e_container_border_list_last(con);
3078              while ((bd = e_container_border_list_prev(bl)))
3079                {
3080                   if (bd->changed) _e_border_eval0(bd);
3081                }
3082              e_container_border_list_free(bl);
3083
3084              // layout hook - this is where a hook gets to figure out what to
3085              // do if anything.
3086              _e_border_container_layout_hook(con);
3087
3088              // pass 2 - show windows needing show
3089              bl = e_container_border_list_last(con);
3090              while ((bd = e_container_border_list_prev(bl)))
3091                {
3092                   if ((bd->changes.visible) && (bd->visible) &&
3093                       (!bd->new_client) && (!bd->changes.pos) &&
3094                       (!bd->changes.size))
3095                     {
3096                        _e_border_show(bd);
3097                        bd->changes.visible = 0;
3098                     }
3099                }
3100              e_container_border_list_free(bl);
3101
3102              // pass 3 - hide windows needing hide and eval (main eval)
3103              bl = e_container_border_list_first(con);
3104              while ((bd = e_container_border_list_next(bl)))
3105                {
3106                   if (e_object_is_del(E_OBJECT(bd))) continue;
3107
3108                   if ((bd->changes.visible) && (!bd->visible))
3109                     {
3110                        _e_border_hide(bd);
3111                        bd->changes.visible = 0;
3112                     }
3113
3114                   if (bd->changed) _e_border_eval(bd);
3115
3116                   if ((bd->changes.visible) && (bd->visible))
3117                     {
3118                        _e_border_show(bd);
3119                        bd->changes.visible = 0;
3120                     }
3121                }
3122              e_container_border_list_free(bl);
3123           }
3124      }
3125
3126    if (focus_next)
3127      {
3128         E_Border *bd = NULL, *bd2;
3129
3130         EINA_LIST_FREE(focus_next, bd2)
3131           if ((!bd) && (bd2->visible)) bd = bd2;
3132
3133         if (!bd)
3134           {
3135              /* TODO revert focus when lost here ? */
3136              return;
3137           }
3138 #ifdef INOUTDEBUG_FOCUS
3139         printf("%s idler focus\n", e_border_name_get(bd));
3140 #endif
3141         if (bd == focused)
3142           return;
3143
3144         focus_time = ecore_x_current_time_get();
3145
3146         if ((bd->client.icccm.take_focus) &&
3147             (bd->client.icccm.accepts_focus))
3148           {
3149              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_LOCALLY_ACTIVE);
3150              /* TODO what if the client doesnt took focus ? */
3151           }
3152         else if (!bd->client.icccm.accepts_focus)
3153           {
3154              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_GLOBALLY_ACTIVE);
3155           }
3156         else if (!bd->client.icccm.take_focus)
3157           {
3158              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_PASSIVE);
3159              /* e_border_focus_set(bd, 1, 0); */
3160           }
3161      }
3162 }
3163
3164 EAPI Eina_List *
3165 e_border_client_list()
3166 {
3167    /* FIXME: This should be a somewhat ordered list */
3168     return borders;
3169 }
3170
3171 static Ecore_X_Window action_input_win = 0;
3172 static E_Border *action_border = NULL;
3173 static Ecore_Event_Handler *action_handler_key = NULL;
3174 static Ecore_Event_Handler *action_handler_mouse = NULL;
3175 static Ecore_Timer *action_timer = NULL;
3176 static Ecore_X_Rectangle action_orig;
3177
3178 static void
3179 _e_border_show(E_Border *bd)
3180 {
3181    ecore_evas_show(bd->bg_ecore_evas);
3182
3183    if (bd->post_job)
3184      {
3185         bd->post_show = 1;
3186         return;
3187      }
3188
3189    if (!bd->comp_hidden)
3190      {
3191         _e_border_shape_input_rectangle_set(bd);
3192 // not anymore
3193 //      ecore_x_composite_window_events_enable(bd->win);
3194         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
3195      }
3196
3197    ecore_x_window_show(bd->win);
3198 }
3199
3200 static void
3201 _e_border_hide(E_Border *bd)
3202 {
3203    if (!e_manager_comp_evas_get(bd->zone->container->manager))
3204      {
3205         ecore_x_window_hide(bd->win);
3206         ecore_evas_hide(bd->bg_ecore_evas);
3207      }
3208    else
3209      {
3210         ecore_x_composite_window_events_disable(bd->win);
3211         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
3212      }
3213 }
3214
3215 static int
3216 _e_border_action_input_win_del(void)
3217 {
3218    if (!action_input_win)
3219      return 0;
3220
3221    e_grabinput_release(action_input_win, action_input_win);
3222    ecore_x_window_free(action_input_win);
3223    action_input_win = 0;
3224    return 1;
3225 }
3226
3227 static int
3228 _e_border_action_input_win_new(E_Border *bd)
3229 {
3230    if (!action_input_win)
3231      {
3232         Ecore_X_Window parent = bd->zone->container->win;
3233         action_input_win = ecore_x_window_input_new(parent, 0, 0, 1, 1);
3234         if (!action_input_win)
3235           return 0;
3236      }
3237
3238    ecore_x_window_show(action_input_win);
3239    if (e_grabinput_get(action_input_win, 0, action_input_win))
3240      return 1;
3241
3242    _e_border_action_input_win_del();
3243    return 0;
3244 }
3245
3246 static void
3247 _e_border_action_finish(void)
3248 {
3249    _e_border_action_input_win_del();
3250
3251    if (action_timer)
3252      {
3253         ecore_timer_del(action_timer);
3254         action_timer = NULL;
3255      }
3256
3257    if (action_handler_key)
3258      {
3259         ecore_event_handler_del(action_handler_key);
3260         action_handler_key = NULL;
3261      }
3262
3263    if (action_handler_mouse)
3264      {
3265         ecore_event_handler_del(action_handler_mouse);
3266         action_handler_mouse = NULL;
3267      }
3268
3269    action_border = NULL;
3270 }
3271
3272 static void
3273 _e_border_action_init(E_Border *bd)
3274 {
3275    action_orig.x = bd->x;
3276    action_orig.y = bd->y;
3277    action_orig.width = bd->w;
3278    action_orig.height = bd->h;
3279
3280    action_border = bd;
3281 }
3282
3283 static void
3284 _e_border_action_restore_orig(E_Border *bd)
3285 {
3286    if (action_border != bd)
3287      return;
3288
3289    e_border_move_resize(bd, action_orig.x, action_orig.y, action_orig.width, action_orig.height);
3290 }
3291
3292 static int
3293 _e_border_key_down_modifier_apply(int modifier,
3294                                   int value)
3295 {
3296    if (modifier & ECORE_EVENT_MODIFIER_CTRL)
3297      return value * 2;
3298    else if (modifier & ECORE_EVENT_MODIFIER_ALT)
3299      {
3300         value /= 2;
3301         if (value)
3302           return value;
3303         else
3304           return 1;
3305      }
3306
3307    return value;
3308 }
3309
3310 static Eina_Bool
3311 _e_border_action_move_timeout(void *data __UNUSED__)
3312 {
3313    _e_border_move_end(action_border);
3314    _e_border_action_finish();
3315    return ECORE_CALLBACK_CANCEL;
3316 }
3317
3318 static void
3319 _e_border_action_move_timeout_add(void)
3320 {
3321    if (action_timer)
3322      ecore_timer_del(action_timer);
3323    action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_border_action_move_timeout, NULL);
3324 }
3325
3326 static Eina_Bool
3327 _e_border_move_key_down(void *data __UNUSED__,
3328                         int type   __UNUSED__,
3329                         void      *event)
3330 {
3331    Ecore_Event_Key *ev = event;
3332    int x, y;
3333
3334    if (ev->event_window != action_input_win)
3335      return ECORE_CALLBACK_PASS_ON;
3336    if (!action_border)
3337      {
3338         fputs("ERROR: no action_border!\n", stderr);
3339         goto stop;
3340      }
3341
3342    x = action_border->x;
3343    y = action_border->y;
3344
3345    if ((strcmp(ev->key, "Up") == 0) || (strcmp(ev->key, "k") == 0))
3346      y -= _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dy);
3347    else if ((strcmp(ev->key, "Down") == 0) || (strcmp(ev->key, "j") == 0))
3348      y += _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dy);
3349    else if ((strcmp(ev->key, "Left") == 0) || (strcmp(ev->key, "h") == 0))
3350      x -= _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dx);
3351    else if ((strcmp(ev->key, "Right") == 0) || (strcmp(ev->key, "l") == 0))
3352      x += _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dx);
3353    else if (strcmp(ev->key, "Return") == 0)
3354      goto stop;
3355    else if (strcmp(ev->key, "Escape") == 0)
3356      {
3357         _e_border_action_restore_orig(action_border);
3358         goto stop;
3359      }
3360    else if ((strncmp(ev->key, "Control", sizeof("Control") - 1) != 0) &&
3361             (strncmp(ev->key, "Alt", sizeof("Alt") - 1) != 0))
3362      goto stop;
3363
3364    e_border_move(action_border, x, y);
3365    _e_border_action_move_timeout_add();
3366
3367    return ECORE_CALLBACK_PASS_ON;
3368
3369 stop:
3370    _e_border_move_end(action_border);
3371    _e_border_action_finish();
3372    return ECORE_CALLBACK_DONE;
3373 }
3374
3375 static Eina_Bool
3376 _e_border_move_mouse_down(void *data __UNUSED__,
3377                           int type   __UNUSED__,
3378                           void      *event)
3379 {
3380    Ecore_Event_Mouse_Button *ev = event;
3381
3382    if (ev->event_window != action_input_win)
3383      return ECORE_CALLBACK_PASS_ON;
3384
3385    if (!action_border)
3386      fputs("ERROR: no action_border!\n", stderr);
3387
3388    _e_border_move_end(action_border);
3389    _e_border_action_finish();
3390    return ECORE_CALLBACK_DONE;
3391 }
3392
3393 EAPI void
3394 e_border_act_move_keyboard(E_Border *bd)
3395 {
3396    if (!bd)
3397      return;
3398
3399    if (!_e_border_move_begin(bd))
3400      return;
3401
3402    if (!_e_border_action_input_win_new(bd))
3403      {
3404         _e_border_move_end(bd);
3405         return;
3406      }
3407
3408    _e_border_action_init(bd);
3409    _e_border_action_move_timeout_add();
3410    _e_border_move_update(bd);
3411
3412    if (action_handler_key)
3413      ecore_event_handler_del(action_handler_key);
3414    action_handler_key = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_border_move_key_down, NULL);
3415
3416    if (action_handler_mouse)
3417      ecore_event_handler_del(action_handler_mouse);
3418    action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_move_mouse_down, NULL);
3419 }
3420
3421 static Eina_Bool
3422 _e_border_action_resize_timeout(void *data __UNUSED__)
3423 {
3424    _e_border_resize_end(action_border);
3425    _e_border_action_finish();
3426    return ECORE_CALLBACK_CANCEL;
3427 }
3428
3429 static void
3430 _e_border_action_resize_timeout_add(void)
3431 {
3432    if (action_timer)
3433      ecore_timer_del(action_timer);
3434    action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_border_action_resize_timeout, NULL);
3435 }
3436
3437 static Eina_Bool
3438 _e_border_resize_key_down(void *data __UNUSED__,
3439                           int type   __UNUSED__,
3440                           void      *event)
3441 {
3442    Ecore_Event_Key *ev = event;
3443    int w, h, dx, dy;
3444
3445    if (ev->event_window != action_input_win)
3446      return ECORE_CALLBACK_PASS_ON;
3447    if (!action_border)
3448      {
3449         fputs("ERROR: no action_border!\n", stderr);
3450         goto stop;
3451      }
3452
3453    w = action_border->w;
3454    h = action_border->h;
3455
3456    dx = e_config->border_keyboard.resize.dx;
3457    if (dx < action_border->client.icccm.step_w)
3458      dx = action_border->client.icccm.step_w;
3459    dx = _e_border_key_down_modifier_apply(ev->modifiers, dx);
3460    if (dx < action_border->client.icccm.step_w)
3461      dx = action_border->client.icccm.step_w;
3462
3463    dy = e_config->border_keyboard.resize.dy;
3464    if (dy < action_border->client.icccm.step_h)
3465      dy = action_border->client.icccm.step_h;
3466    dy = _e_border_key_down_modifier_apply(ev->modifiers, dy);
3467    if (dy < action_border->client.icccm.step_h)
3468      dy = action_border->client.icccm.step_h;
3469
3470    if ((strcmp(ev->key, "Up") == 0) || (strcmp(ev->key, "k") == 0))
3471      h -= dy;
3472    else if ((strcmp(ev->key, "Down") == 0) || (strcmp(ev->key, "j") == 0))
3473      h += dy;
3474    else if ((strcmp(ev->key, "Left") == 0) || (strcmp(ev->key, "h") == 0))
3475      w -= dx;
3476    else if ((strcmp(ev->key, "Right") == 0) || (strcmp(ev->key, "l") == 0))
3477      w += dx;
3478    else if (strcmp(ev->key, "Return") == 0)
3479      goto stop;
3480    else if (strcmp(ev->key, "Escape") == 0)
3481      {
3482         _e_border_action_restore_orig(action_border);
3483         goto stop;
3484      }
3485    else if ((strncmp(ev->key, "Control", sizeof("Control") - 1) != 0) &&
3486             (strncmp(ev->key, "Alt", sizeof("Alt") - 1) != 0))
3487      goto stop;
3488
3489    e_border_resize_limit(action_border, &w, &h);
3490    e_border_resize(action_border, w, h);
3491    _e_border_action_resize_timeout_add();
3492
3493    return ECORE_CALLBACK_PASS_ON;
3494
3495 stop:
3496    _e_border_resize_end(action_border);
3497    _e_border_action_finish();
3498    return ECORE_CALLBACK_DONE;
3499 }
3500
3501 static Eina_Bool
3502 _e_border_resize_mouse_down(void *data __UNUSED__,
3503                             int type   __UNUSED__,
3504                             void      *event)
3505 {
3506    Ecore_Event_Mouse_Button *ev = event;
3507
3508    if (ev->event_window != action_input_win)
3509      return ECORE_CALLBACK_PASS_ON;
3510
3511    if (!action_border)
3512      fputs("ERROR: no action_border!\n", stderr);
3513
3514    _e_border_resize_end(action_border);
3515    _e_border_action_finish();
3516    return ECORE_CALLBACK_DONE;
3517 }
3518
3519 EAPI void
3520 e_border_act_resize_keyboard(E_Border *bd)
3521 {
3522    if (!bd)
3523      return;
3524
3525    if (!_e_border_resize_begin(bd))
3526      return;
3527
3528    if (!_e_border_action_input_win_new(bd))
3529      {
3530         _e_border_resize_end(bd);
3531         return;
3532      }
3533
3534    _e_border_action_init(bd);
3535    _e_border_action_resize_timeout_add();
3536    _e_border_resize_update(bd);
3537
3538    if (action_handler_key)
3539      ecore_event_handler_del(action_handler_key);
3540    action_handler_key = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_border_resize_key_down, NULL);
3541
3542    if (action_handler_mouse)
3543      ecore_event_handler_del(action_handler_mouse);
3544    action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_resize_mouse_down, NULL);
3545 }
3546
3547 EAPI void
3548 e_border_act_move_begin(E_Border                 *bd,
3549                         Ecore_Event_Mouse_Button *ev)
3550 {
3551    E_OBJECT_CHECK(bd);
3552    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3553    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
3554    if (!_e_border_move_begin(bd))
3555      return;
3556
3557    e_zone_edge_disable();
3558    bd->moving = 1;
3559    _e_border_pointer_move_begin(bd);
3560    if (ev)
3561      {
3562         char source[256];
3563
3564         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->buttons);
3565         _e_border_moveinfo_gather(bd, source);
3566      }
3567 }
3568
3569 EAPI void
3570 e_border_act_move_end(E_Border                    *bd,
3571                       Ecore_Event_Mouse_Button *ev __UNUSED__)
3572 {
3573    E_OBJECT_CHECK(bd);
3574    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3575    if (!bd->moving) return;
3576    bd->moving = 0;
3577    _e_border_pointer_move_end(bd);
3578    e_zone_edge_enable();
3579    _e_border_move_end(bd);
3580    e_zone_flip_coords_handle(bd->zone, -1, -1);
3581 }
3582
3583 EAPI void
3584 e_border_act_resize_begin(E_Border                 *bd,
3585                           Ecore_Event_Mouse_Button *ev)
3586 {
3587    E_OBJECT_CHECK(bd);
3588    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3589    if (bd->lock_user_size) return;
3590    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
3591    if (!_e_border_resize_begin(bd))
3592      return;
3593    if (bd->mouse.current.mx < (bd->x + bd->w / 2))
3594      {
3595         if (bd->mouse.current.my < (bd->y + bd->h / 2))
3596           {
3597              bd->resize_mode = RESIZE_TL;
3598              GRAV_SET(bd, ECORE_X_GRAVITY_SE);
3599           }
3600         else
3601           {
3602              bd->resize_mode = RESIZE_BL;
3603              GRAV_SET(bd, ECORE_X_GRAVITY_NE);
3604           }
3605      }
3606    else
3607      {
3608         if (bd->mouse.current.my < (bd->y + bd->h / 2))
3609           {
3610              bd->resize_mode = RESIZE_TR;
3611              GRAV_SET(bd, ECORE_X_GRAVITY_SW);
3612           }
3613         else
3614           {
3615              bd->resize_mode = RESIZE_BR;
3616              GRAV_SET(bd, ECORE_X_GRAVITY_NW);
3617           }
3618      }
3619    _e_border_pointer_resize_begin(bd);
3620    if (ev)
3621      {
3622         char source[256];
3623
3624         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->buttons);
3625         _e_border_moveinfo_gather(bd, source);
3626      }
3627 }
3628
3629 EAPI void
3630 e_border_act_resize_end(E_Border                    *bd,
3631                         Ecore_Event_Mouse_Button *ev __UNUSED__)
3632 {
3633    E_OBJECT_CHECK(bd);
3634    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3635    if (bd->resize_mode != RESIZE_NONE)
3636      {
3637         _e_border_pointer_resize_end(bd);
3638         bd->resize_mode = RESIZE_NONE;
3639         _e_border_resize_end(bd);
3640         bd->changes.reset_gravity = 1;
3641         bd->changed = 1;
3642      }
3643 }
3644
3645 EAPI void
3646 e_border_act_menu_begin(E_Border                 *bd,
3647                         Ecore_Event_Mouse_Button *ev,
3648                         int                       key)
3649 {
3650    E_OBJECT_CHECK(bd);
3651    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3652    if (ev)
3653      {
3654         e_int_border_menu_show(bd,
3655                                bd->x + bd->fx.x + ev->x - bd->zone->container->x,
3656                                bd->y + bd->fx.y + ev->y - bd->zone->container->y, key,
3657                                ev->timestamp);
3658      }
3659    else
3660      {
3661         int x, y;
3662
3663         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
3664         e_int_border_menu_show(bd, x, y, key, 0);
3665      }
3666 }
3667
3668 EAPI void
3669 e_border_act_close_begin(E_Border *bd)
3670 {
3671    E_OBJECT_CHECK(bd);
3672    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3673    if (bd->lock_close) return;
3674    if (bd->client.icccm.delete_request)
3675      {
3676         bd->delete_requested = 1;
3677         ecore_x_window_delete_request_send(bd->client.win);
3678         if (bd->client.netwm.ping)
3679           e_border_ping(bd);
3680      }
3681    else if (e_config->kill_if_close_not_possible)
3682      {
3683         printf("KILL win %x (dead)\n", bd->client.win);
3684         e_border_act_kill_begin(bd);
3685      }
3686 }
3687
3688 EAPI void
3689 e_border_act_kill_begin(E_Border *bd)
3690 {
3691    E_OBJECT_CHECK(bd);
3692    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3693    if (bd->internal) return;
3694    if (bd->lock_close) return;
3695    if ((bd->client.netwm.pid > 1) && (e_config->kill_process))
3696      {
3697         kill(bd->client.netwm.pid, SIGINT);
3698         bd->kill_timer = ecore_timer_add(e_config->kill_timer_wait,
3699                                          _e_border_cb_kill_timer, bd);
3700      }
3701    else
3702      {
3703         if (!bd->internal) ecore_x_kill(bd->client.win);
3704      }
3705 }
3706
3707 EAPI Evas_Object *
3708 e_border_icon_add(E_Border *bd,
3709                   Evas     *evas)
3710 {
3711    Evas_Object *o;
3712
3713    E_OBJECT_CHECK_RETURN(bd, NULL);
3714    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, NULL);
3715
3716    o = NULL;
3717    if (bd->internal)
3718      {
3719         o = edje_object_add(evas);
3720         if (!bd->internal_icon)
3721           e_util_edje_icon_set(o, "enlightenment");
3722         else
3723           {
3724              if (!bd->internal_icon_key)
3725                {
3726                   char *ext;
3727
3728                   ext = strrchr(bd->internal_icon, '.');
3729                   if ((ext) && ((!strcmp(ext, ".edj"))))
3730                     {
3731                        if (!edje_object_file_set(o, bd->internal_icon, "icon"))
3732                          e_util_edje_icon_set(o, "enlightenment");
3733                     }
3734                   else if (ext)
3735                     {
3736                        evas_object_del(o);
3737                        o = e_icon_add(evas);
3738                        e_icon_file_set(o, bd->internal_icon);
3739                     }
3740                   else
3741                     {
3742                        evas_object_del(o);
3743                        o = e_icon_add(evas);
3744                        if (!e_util_icon_theme_set(o, bd->internal_icon))
3745                          e_util_icon_theme_set(o, "enlightenment");
3746                     }
3747                }
3748              else
3749                {
3750                   edje_object_file_set(o, bd->internal_icon,
3751                                        bd->internal_icon_key);
3752                }
3753           }
3754         return o;
3755      }
3756    if ((e_config->use_app_icon) && (bd->icon_preference != E_ICON_PREF_USER))
3757      {
3758         if (bd->client.netwm.icons)
3759           {
3760              o = e_icon_add(evas);
3761              e_icon_data_set(o, bd->client.netwm.icons[0].data,
3762                              bd->client.netwm.icons[0].width,
3763                              bd->client.netwm.icons[0].height);
3764              e_icon_alpha_set(o, 1);
3765              return o;
3766           }
3767      }
3768    if (!o)
3769      {
3770         if ((bd->desktop) && (bd->icon_preference != E_ICON_PREF_NETWM))
3771           {
3772              o = e_icon_add(evas);
3773              if (o)
3774                {
3775                   e_icon_fdo_icon_set(o, bd->desktop->icon);
3776                   return o;
3777                }
3778           }
3779         else if (bd->client.netwm.icons)
3780           {
3781              o = e_icon_add(evas);
3782              e_icon_data_set(o, bd->client.netwm.icons[0].data,
3783                              bd->client.netwm.icons[0].width,
3784                              bd->client.netwm.icons[0].height);
3785              e_icon_alpha_set(o, 1);
3786              return o;
3787           }
3788      }
3789
3790    o = e_icon_add(evas);
3791    e_util_icon_theme_set(o, "unknown");
3792    return o;
3793 }
3794
3795 EAPI void
3796 e_border_button_bindings_ungrab_all(void)
3797 {
3798    Eina_List *l;
3799    E_Border *bd;
3800
3801    EINA_LIST_FOREACH(borders, l, bd)
3802      {
3803         e_focus_setdown(bd);
3804         e_bindings_mouse_ungrab(E_BINDING_CONTEXT_BORDER, bd->win);
3805         e_bindings_wheel_ungrab(E_BINDING_CONTEXT_BORDER, bd->win);
3806      }
3807 }
3808
3809 EAPI void
3810 e_border_button_bindings_grab_all(void)
3811 {
3812    Eina_List *l;
3813    E_Border *bd;
3814
3815    EINA_LIST_FOREACH(borders, l, bd)
3816      {
3817         e_bindings_mouse_grab(E_BINDING_CONTEXT_BORDER, bd->win);
3818         e_bindings_wheel_grab(E_BINDING_CONTEXT_BORDER, bd->win);
3819         e_focus_setup(bd);
3820      }
3821 }
3822
3823 EAPI Eina_List *
3824 e_border_focus_stack_get(void)
3825 {
3826    return focus_stack;
3827 }
3828
3829 EAPI Eina_List *
3830 e_border_raise_stack_get(void)
3831 {
3832    return raise_stack;
3833 }
3834
3835 EAPI Eina_List *
3836 e_border_lost_windows_get(E_Zone *zone)
3837 {
3838    Eina_List *list = NULL, *l;
3839    E_Border *bd;
3840    int loss_overlap = 5;
3841
3842    E_OBJECT_CHECK_RETURN(zone, NULL);
3843    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
3844    EINA_LIST_FOREACH(borders, l, bd)
3845      {
3846         if (bd->zone)
3847           {
3848              if ((bd->zone == zone) ||
3849                  (bd->zone->container == zone->container))
3850                {
3851                   if (!E_INTERSECTS(bd->zone->x + loss_overlap,
3852                                     bd->zone->y + loss_overlap,
3853                                     bd->zone->w - (2 * loss_overlap),
3854                                     bd->zone->h - (2 * loss_overlap),
3855                                     bd->x, bd->y, bd->w, bd->h))
3856                     {
3857                        list = eina_list_append(list, bd);
3858                     }
3859                   else if ((!E_CONTAINS(bd->zone->x, bd->zone->y,
3860                                         bd->zone->w, bd->zone->h,
3861                                         bd->x, bd->y, bd->w, bd->h)) &&
3862                            (bd->shaped))
3863                     {
3864                        Ecore_X_Rectangle *rect;
3865                        int i, num;
3866
3867                        rect = ecore_x_window_shape_rectangles_get(bd->win, &num);
3868                        if (rect)
3869                          {
3870                             int ok;
3871
3872                             ok = 0;
3873                             for (i = 0; i < num; i++)
3874                               {
3875                                  if (E_INTERSECTS(bd->zone->x + loss_overlap,
3876                                                   bd->zone->y + loss_overlap,
3877                                                   bd->zone->w - (2 * loss_overlap),
3878                                                   bd->zone->h - (2 * loss_overlap),
3879                                                   rect[i].x, rect[i].y,
3880                                                   (int)rect[i].width, (int)rect[i].height))
3881                                    {
3882                                       ok = 1;
3883                                       break;
3884                                    }
3885                               }
3886                             free(rect);
3887                             if (!ok)
3888                               list = eina_list_append(list, bd);
3889                          }
3890                     }
3891                }
3892           }
3893      }
3894    return list;
3895 }
3896
3897 EAPI void
3898 e_border_ping(E_Border *bd)
3899 {
3900    E_OBJECT_CHECK(bd);
3901    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3902    if (!e_config->ping_clients) return;
3903    bd->ping_ok = 0;
3904    ecore_x_netwm_ping_send(bd->client.win);
3905    bd->ping = ecore_loop_time_get();
3906    if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
3907    bd->ping_poller = ecore_poller_add(ECORE_POLLER_CORE,
3908                                       e_config->ping_clients_interval,
3909                                       _e_border_cb_ping_poller, bd);
3910 }
3911
3912 EAPI void
3913 e_border_move_cancel(void)
3914 {
3915    if (move)
3916      {
3917         if (move->cur_mouse_action)
3918           {
3919              E_Border *bd;
3920
3921              bd = move;
3922              e_object_ref(E_OBJECT(bd));
3923              if (bd->cur_mouse_action->func.end_mouse)
3924                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", NULL);
3925              else if (bd->cur_mouse_action->func.end)
3926                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
3927              e_object_unref(E_OBJECT(bd->cur_mouse_action));
3928              bd->cur_mouse_action = NULL;
3929              e_object_unref(E_OBJECT(bd));
3930           }
3931         else
3932           _e_border_move_end(move);
3933      }
3934 }
3935
3936 EAPI void
3937 e_border_resize_cancel(void)
3938 {
3939    if (resize)
3940      {
3941         if (resize->cur_mouse_action)
3942           {
3943              E_Border *bd;
3944
3945              bd = resize;
3946              e_object_ref(E_OBJECT(bd));
3947              if (bd->cur_mouse_action->func.end_mouse)
3948                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", NULL);
3949              else if (bd->cur_mouse_action->func.end)
3950                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
3951              e_object_unref(E_OBJECT(bd->cur_mouse_action));
3952              bd->cur_mouse_action = NULL;
3953              e_object_unref(E_OBJECT(bd));
3954           }
3955         else
3956           {
3957              resize->resize_mode = RESIZE_NONE;
3958              _e_border_resize_end(resize);
3959           }
3960      }
3961 }
3962
3963 EAPI void
3964 e_border_frame_recalc(E_Border *bd)
3965 {
3966    Evas_Coord cx, cy, cw, ch;
3967
3968    if (!bd->bg_object) return;
3969
3970    bd->w -= (bd->client_inset.l + bd->client_inset.r);
3971    bd->h -= (bd->client_inset.t + bd->client_inset.b);
3972
3973    evas_object_resize(bd->bg_object, 1000, 1000);
3974    edje_object_calc_force(bd->bg_object);
3975    edje_object_part_geometry_get(bd->bg_object, "e.swallow.client", &cx, &cy, &cw, &ch);
3976    bd->client_inset.l = cx;
3977    bd->client_inset.r = 1000 - (cx + cw);
3978    bd->client_inset.t = cy;
3979    bd->client_inset.b = 1000 - (cy + ch);
3980    ecore_x_netwm_frame_size_set(bd->client.win,
3981                                 bd->client_inset.l, bd->client_inset.r,
3982                                 bd->client_inset.t, bd->client_inset.b);
3983    ecore_x_e_frame_size_set(bd->client.win,
3984                             bd->client_inset.l, bd->client_inset.r,
3985                             bd->client_inset.t, bd->client_inset.b);
3986
3987    bd->w += (bd->client_inset.l + bd->client_inset.r);
3988    bd->h += (bd->client_inset.t + bd->client_inset.b);
3989
3990    bd->changed = 1;
3991    bd->changes.size = 1;
3992    if ((bd->shaped) || (bd->client.shaped))
3993      {
3994         bd->need_shape_merge = 1;
3995         bd->need_shape_export = 1;
3996      }
3997    if (bd->shaped_input)
3998      {
3999         bd->need_shape_merge = 1;
4000      }
4001    _e_border_client_move_resize_send(bd);
4002 }
4003
4004 EAPI Eina_List *
4005 e_border_immortal_windows_get(void)
4006 {
4007    Eina_List *list = NULL, *l;
4008    E_Border *bd;
4009
4010    EINA_LIST_FOREACH(borders, l, bd)
4011      {
4012         if (bd->lock_life)
4013           list = eina_list_append(list, bd);
4014      }
4015    return list;
4016 }
4017
4018 EAPI const char *
4019 e_border_name_get(const E_Border *bd)
4020 {
4021    E_OBJECT_CHECK_RETURN(bd, "");
4022    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, "");
4023    if (bd->client.netwm.name)
4024      return bd->client.netwm.name;
4025    else if (bd->client.icccm.title)
4026      return bd->client.icccm.title;
4027    return "";
4028 }
4029
4030 EAPI void
4031 e_border_signal_move_begin(E_Border       *bd,
4032                            const char     *sig,
4033                            const char *src __UNUSED__)
4034 {
4035    E_OBJECT_CHECK(bd);
4036    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4037    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
4038    if (!_e_border_move_begin(bd)) return;
4039    bd->moving = 1;
4040    _e_border_pointer_move_begin(bd);
4041    e_zone_edge_disable();
4042    _e_border_moveinfo_gather(bd, sig);
4043 }
4044
4045 EAPI void
4046 e_border_signal_move_end(E_Border       *bd,
4047                          const char *sig __UNUSED__,
4048                          const char *src __UNUSED__)
4049 {
4050    E_OBJECT_CHECK(bd);
4051    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4052    if (!bd->moving) return;
4053    bd->moving = 0;
4054    _e_border_pointer_move_end(bd);
4055    e_zone_edge_enable();
4056    _e_border_move_end(bd);
4057    e_zone_flip_coords_handle(bd->zone, -1, -1);
4058 }
4059
4060 EAPI int
4061 e_border_resizing_get(E_Border *bd)
4062 {
4063    E_OBJECT_CHECK_RETURN(bd, 0);
4064    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, 0);
4065    if (bd->resize_mode == RESIZE_NONE) return 0;
4066    return 1;
4067 }
4068
4069 EAPI void
4070 e_border_signal_resize_begin(E_Border       *bd,
4071                              const char     *dir,
4072                              const char     *sig,
4073                              const char *src __UNUSED__)
4074 {
4075    Ecore_X_Gravity grav = ECORE_X_GRAVITY_NW;
4076    int resize_mode = RESIZE_BR;
4077
4078    E_OBJECT_CHECK(bd);
4079    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4080
4081    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
4082    if (!_e_border_resize_begin(bd))
4083      return;
4084    if (!strcmp(dir, "tl"))
4085      {
4086         resize_mode = RESIZE_TL;
4087         grav = ECORE_X_GRAVITY_SE;
4088      }
4089    else if (!strcmp(dir, "t"))
4090      {
4091         resize_mode = RESIZE_T;
4092         grav = ECORE_X_GRAVITY_S;
4093      }
4094    else if (!strcmp(dir, "tr"))
4095      {
4096         resize_mode = RESIZE_TR;
4097         grav = ECORE_X_GRAVITY_SW;
4098      }
4099    else if (!strcmp(dir, "r"))
4100      {
4101         resize_mode = RESIZE_R;
4102         grav = ECORE_X_GRAVITY_W;
4103      }
4104    else if (!strcmp(dir, "br"))
4105      {
4106         resize_mode = RESIZE_BR;
4107         grav = ECORE_X_GRAVITY_NW;
4108      }
4109    else if (!strcmp(dir, "b"))
4110      {
4111         resize_mode = RESIZE_B;
4112         grav = ECORE_X_GRAVITY_N;
4113      }
4114    else if (!strcmp(dir, "bl"))
4115      {
4116         resize_mode = RESIZE_BL;
4117         grav = ECORE_X_GRAVITY_NE;
4118      }
4119    else if (!strcmp(dir, "l"))
4120      {
4121         resize_mode = RESIZE_L;
4122         grav = ECORE_X_GRAVITY_E;
4123      }
4124    bd->resize_mode = resize_mode;
4125    _e_border_pointer_resize_begin(bd);
4126    _e_border_moveinfo_gather(bd, sig);
4127    GRAV_SET(bd, grav);
4128 }
4129
4130 EAPI void
4131 e_border_signal_resize_end(E_Border       *bd,
4132                            const char *dir __UNUSED__,
4133                            const char *sig __UNUSED__,
4134                            const char *src __UNUSED__)
4135 {
4136    E_OBJECT_CHECK(bd);
4137    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4138    if (bd->resize_mode == RESIZE_NONE) return;
4139    _e_border_resize_handle(bd);
4140    _e_border_pointer_resize_end(bd);
4141    bd->resize_mode = RESIZE_NONE;
4142    _e_border_resize_end(bd);
4143    bd->changes.reset_gravity = 1;
4144    bd->changed = 1;
4145 }
4146
4147 EAPI void
4148 e_border_resize_limit(E_Border *bd,
4149                       int      *w,
4150                       int      *h)
4151 {
4152    double a;
4153
4154    E_OBJECT_CHECK(bd);
4155    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4156    *w -= bd->client_inset.l + bd->client_inset.r;
4157    *h -= bd->client_inset.t + bd->client_inset.b;
4158    if (*h < 1) *h = 1;
4159    if (*w < 1) *w = 1;
4160    if ((bd->client.icccm.base_w >= 0) &&
4161        (bd->client.icccm.base_h >= 0))
4162      {
4163         int tw, th;
4164
4165         tw = *w - bd->client.icccm.base_w;
4166         th = *h - bd->client.icccm.base_h;
4167         if (tw < 1) tw = 1;
4168         if (th < 1) th = 1;
4169         a = (double)(tw) / (double)(th);
4170         if ((bd->client.icccm.min_aspect != 0.0) &&
4171             (a < bd->client.icccm.min_aspect))
4172           {
4173              th = tw / bd->client.icccm.max_aspect;
4174              *h = th + bd->client.icccm.base_h;
4175           }
4176         else if ((bd->client.icccm.max_aspect != 0.0) &&
4177                  (a > bd->client.icccm.max_aspect))
4178           {
4179              tw = th * bd->client.icccm.max_aspect;
4180              *w = tw + bd->client.icccm.base_w;
4181           }
4182      }
4183    else
4184      {
4185         a = (double)*w / (double)*h;
4186         if ((bd->client.icccm.min_aspect != 0.0) &&
4187             (a < bd->client.icccm.min_aspect))
4188           *h = *w / bd->client.icccm.min_aspect;
4189         else if ((bd->client.icccm.max_aspect != 0.0) &&
4190                  (a > bd->client.icccm.max_aspect))
4191           *w = *h * bd->client.icccm.max_aspect;
4192      }
4193    if (bd->client.icccm.step_w > 0)
4194      {
4195         if (bd->client.icccm.base_w >= 0)
4196           *w = bd->client.icccm.base_w +
4197             (((*w - bd->client.icccm.base_w) / bd->client.icccm.step_w) *
4198              bd->client.icccm.step_w);
4199         else
4200           *w = bd->client.icccm.min_w +
4201             (((*w - bd->client.icccm.min_w) / bd->client.icccm.step_w) *
4202              bd->client.icccm.step_w);
4203      }
4204    if (bd->client.icccm.step_h > 0)
4205      {
4206         if (bd->client.icccm.base_h >= 0)
4207           *h = bd->client.icccm.base_h +
4208             (((*h - bd->client.icccm.base_h) / bd->client.icccm.step_h) *
4209              bd->client.icccm.step_h);
4210         else
4211           *h = bd->client.icccm.min_h +
4212             (((*h - bd->client.icccm.min_h) / bd->client.icccm.step_h) *
4213              bd->client.icccm.step_h);
4214      }
4215
4216    if (*h < 1) *h = 1;
4217    if (*w < 1) *w = 1;
4218
4219    if      (*w > bd->client.icccm.max_w) *w = bd->client.icccm.max_w;
4220    else if (*w < bd->client.icccm.min_w)
4221      *w = bd->client.icccm.min_w;
4222    if      (*h > bd->client.icccm.max_h) *h = bd->client.icccm.max_h;
4223    else if (*h < bd->client.icccm.min_h)
4224      *h = bd->client.icccm.min_h;
4225
4226    *w += bd->client_inset.l + bd->client_inset.r;
4227    *h += bd->client_inset.t + bd->client_inset.b;
4228 }
4229
4230 /* local subsystem functions */
4231 static void
4232 _e_border_free(E_Border *bd)
4233 {
4234    if (bd->desktop)
4235      {
4236         efreet_desktop_free(bd->desktop);
4237         bd->desktop = NULL;
4238      }
4239    if (bd->post_job)
4240      {
4241         ecore_idle_enterer_del(bd->post_job);
4242         bd->post_job = NULL;
4243      }
4244    if (bd->pointer)
4245      {
4246         e_object_del(E_OBJECT(bd->pointer));
4247         bd->pointer = NULL;
4248      }
4249    if (resize == bd)
4250      _e_border_resize_end(bd);
4251    if (move == bd)
4252      _e_border_move_end(bd);
4253    /* TODO: Other states to end before dying? */
4254
4255    if (bd->cur_mouse_action)
4256      {
4257         e_object_unref(E_OBJECT(bd->cur_mouse_action));
4258         bd->cur_mouse_action = NULL;
4259      }
4260
4261    E_FREE(bd->shape_rects);
4262    bd->shape_rects_num = 0;
4263 /*
4264    if (bd->dangling_ref_check)
4265      {
4266         ecore_timer_del(bd->dangling_ref_check);
4267         bd->dangling_ref_check = NULL;
4268      }
4269  */
4270    if (bd->kill_timer)
4271      {
4272         ecore_timer_del(bd->kill_timer);
4273         bd->kill_timer = NULL;
4274      }
4275    if (bd->ping_poller)
4276      {
4277         ecore_poller_del(bd->ping_poller);
4278         bd->ping_poller = NULL;
4279      }
4280    E_FREE_LIST(bd->pending_move_resize, free);
4281
4282    if (bd->shade.anim) ecore_animator_del(bd->shade.anim);
4283    if (bd->border_menu) e_menu_deactivate(bd->border_menu);
4284
4285    if (bd->border_locks_dialog)
4286      {
4287         e_object_del(E_OBJECT(bd->border_locks_dialog));
4288         bd->border_locks_dialog = NULL;
4289      }
4290    if (bd->border_remember_dialog)
4291      {
4292         e_object_del(E_OBJECT(bd->border_remember_dialog));
4293         bd->border_remember_dialog = NULL;
4294      }
4295    if (bd->border_border_dialog)
4296      {
4297         e_object_del(E_OBJECT(bd->border_border_dialog));
4298         bd->border_border_dialog = NULL;
4299      }
4300    if (bd->border_prop_dialog)
4301      {
4302         e_object_del(E_OBJECT(bd->border_prop_dialog));
4303         bd->border_prop_dialog = NULL;
4304      }
4305
4306    e_int_border_menu_del(bd);
4307
4308    if (focused == bd)
4309      {
4310 //      ecore_x_window_focus(bd->zone->container->manager->root);
4311           e_grabinput_focus(bd->zone->container->bg_win, E_FOCUS_METHOD_PASSIVE);
4312           e_hints_active_window_set(bd->zone->container->manager, NULL);
4313           focused = NULL;
4314      }
4315    E_FREE_LIST(bd->handlers, ecore_event_handler_del);
4316    if (bd->remember)
4317      {
4318         E_Remember *rem;
4319
4320         rem = bd->remember;
4321         bd->remember = NULL;
4322         e_remember_unuse(rem);
4323      }
4324    if (!bd->already_unparented)
4325      {
4326         ecore_x_window_reparent(bd->client.win, bd->zone->container->manager->root,
4327                                 bd->x + bd->client_inset.l, bd->y + bd->client_inset.t);
4328         ecore_x_window_save_set_del(bd->client.win);
4329         bd->already_unparented = 1;
4330      }
4331    if (bd->group) eina_list_free(bd->group);
4332    if (bd->transients) eina_list_free(bd->transients);
4333    if (bd->stick_desks) eina_list_free(bd->stick_desks);
4334    if (bd->client.netwm.icons)
4335      {
4336         int i;
4337         for (i = 0; i < bd->client.netwm.num_icons; i++)
4338           free(bd->client.netwm.icons[i].data);
4339         free(bd->client.netwm.icons);
4340      }
4341    if (bd->client.netwm.extra_types)
4342      free(bd->client.netwm.extra_types);
4343    if (bd->client.border.name) eina_stringshare_del(bd->client.border.name);
4344    if (bd->bordername) eina_stringshare_del(bd->bordername);
4345    if (bd->client.icccm.title) free(bd->client.icccm.title);
4346    if (bd->client.icccm.name) free(bd->client.icccm.name);
4347    if (bd->client.icccm.class) free(bd->client.icccm.class);
4348    if (bd->client.icccm.icon_name) free(bd->client.icccm.icon_name);
4349    if (bd->client.icccm.machine) free(bd->client.icccm.machine);
4350    if (bd->client.icccm.window_role) free(bd->client.icccm.window_role);
4351    if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
4352      {
4353         int i;
4354
4355         for (i = 0; i < bd->client.icccm.command.argc; i++)
4356           free(bd->client.icccm.command.argv[i]);
4357         free(bd->client.icccm.command.argv);
4358      }
4359    if (bd->client.netwm.name) free(bd->client.netwm.name);
4360    if (bd->client.netwm.icon_name) free(bd->client.netwm.icon_name);
4361    e_object_del(E_OBJECT(bd->shape));
4362    if (bd->internal_icon) eina_stringshare_del(bd->internal_icon);
4363    if (bd->internal_icon_key) eina_stringshare_del(bd->internal_icon_key);
4364    if (bd->icon_object) evas_object_del(bd->icon_object);
4365    evas_object_del(bd->bg_object);
4366    e_canvas_del(bd->bg_ecore_evas);
4367    ecore_evas_free(bd->bg_ecore_evas);
4368    ecore_x_window_free(bd->client.shell_win);
4369    e_focus_setdown(bd);
4370    e_bindings_mouse_ungrab(E_BINDING_CONTEXT_BORDER, bd->win);
4371    e_bindings_wheel_ungrab(E_BINDING_CONTEXT_BORDER, bd->win);
4372    ecore_x_window_free(bd->win);
4373
4374    eina_hash_del(borders_hash, e_util_winid_str_get(bd->client.win), bd);
4375    eina_hash_del(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
4376    eina_hash_del(borders_hash, e_util_winid_str_get(bd->win), bd);
4377    borders = eina_list_remove(borders, bd);
4378    focus_stack = eina_list_remove(focus_stack, bd);
4379    raise_stack = eina_list_remove(raise_stack, bd);
4380
4381    e_container_border_remove(bd);
4382    free(bd);
4383 }
4384
4385 /*
4386    static int
4387    _e_border_del_dangling_ref_check(void *data)
4388    {
4389    E_Border *bd;
4390
4391    bd = data;
4392    printf("---\n");
4393    printf("EEK EEK border still around 1 second after being deleted!\n");
4394    printf("%p, %i, \"%s\" [\"%s\" \"%s\"]\n",
4395           bd, e_object_ref_get(E_OBJECT(bd)), bd->client.icccm.title,
4396           bd->client.icccm.name, bd->client.icccm.class);
4397    //   e_object_breadcrumb_debug(E_OBJECT(bd));
4398    printf("---\n");
4399    return 1;
4400    }
4401  */
4402
4403 static void
4404 _e_border_del(E_Border *bd)
4405 {
4406    E_Event_Border_Remove *ev;
4407    E_Border *child;
4408
4409    if (bd == focused)
4410      focused = NULL;
4411
4412    focus_next = eina_list_remove(focus_next, bd);
4413
4414    if (bd->fullscreen) bd->desk->fullscreen_borders--;
4415
4416    if ((drag_border) && (drag_border->data == bd))
4417      {
4418         e_object_del(E_OBJECT(drag_border));
4419         drag_border = NULL;
4420      }
4421    if (bd->border_menu) e_menu_deactivate(bd->border_menu);
4422
4423    if (bd->border_locks_dialog)
4424      {
4425         e_object_del(E_OBJECT(bd->border_locks_dialog));
4426         bd->border_locks_dialog = NULL;
4427      }
4428    if (bd->border_remember_dialog)
4429      {
4430         e_object_del(E_OBJECT(bd->border_remember_dialog));
4431         bd->border_remember_dialog = NULL;
4432      }
4433    if (bd->border_border_dialog)
4434      {
4435         e_object_del(E_OBJECT(bd->border_border_dialog));
4436         bd->border_border_dialog = NULL;
4437      }
4438    if (bd->border_prop_dialog)
4439      {
4440         e_object_del(E_OBJECT(bd->border_prop_dialog));
4441         bd->border_prop_dialog = NULL;
4442      }
4443
4444    e_int_border_menu_del(bd);
4445
4446    if (bd->raise_timer)
4447      {
4448         ecore_timer_del(bd->raise_timer);
4449         bd->raise_timer = NULL;
4450      }
4451    if (!bd->already_unparented)
4452      {
4453         ecore_x_window_reparent(bd->client.win,
4454                                 bd->zone->container->manager->root,
4455                                 bd->x + bd->client_inset.l,
4456                                 bd->y + bd->client_inset.t);
4457         ecore_x_window_save_set_del(bd->client.win);
4458         bd->already_unparented = 1;
4459 //      bd->client.win = 0;
4460      }
4461    bd->already_unparented = 1;
4462
4463    if ((!bd->new_client) && (!stopping))
4464      {
4465         ev = E_NEW(E_Event_Border_Remove, 1);
4466         ev->border = bd;
4467         e_object_ref(E_OBJECT(bd));
4468         // e_object_breadcrumb_add(E_OBJECT(bd), "border_remove_event");
4469         ecore_event_add(E_EVENT_BORDER_REMOVE, ev, _e_border_event_border_remove_free, NULL);
4470      }
4471
4472    if (bd->parent)
4473      {
4474         bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
4475         if (bd->parent->modal == bd)
4476           bd->parent->modal = NULL;
4477         bd->parent = NULL;
4478      }
4479    EINA_LIST_FREE(bd->transients, child)
4480      {
4481         child->parent = NULL;
4482      }
4483
4484    if (bd->leader)
4485      {
4486         bd->leader->group = eina_list_remove(bd->leader->group, bd);
4487         if (bd->leader->modal == bd)
4488           bd->leader->modal = NULL;
4489         bd->leader = NULL;
4490      }
4491    EINA_LIST_FREE(bd->group, child)
4492      {
4493         child->leader = NULL;
4494      }
4495 }
4496
4497 #ifdef PRINT_LOTS_OF_DEBUG
4498 static void
4499 _e_border_print(E_Border   *bd,
4500                 const char *func)
4501 {
4502    if (!bd) return;
4503
4504    printf("*Window Info*"
4505           "\tPointer: %p\n"
4506           "\tName: %s\n"
4507           "\tTitle: %s\n"
4508           "\tBorderless: %s\n",
4509           bd, bd->client.icccm.name, bd->client.icccm.title,
4510           bd->borderless ? "TRUE" : "FALSE");
4511 }
4512
4513 #endif
4514
4515 static Eina_Bool
4516 _e_border_cb_window_show_request(void *data  __UNUSED__,
4517                                  int ev_type __UNUSED__,
4518                                  void       *ev)
4519 {
4520    E_Border *bd;
4521    Ecore_X_Event_Window_Show_Request *e;
4522
4523    e = ev;
4524    bd = e_border_find_by_client_window(e->win);
4525    if (!bd) return ECORE_CALLBACK_PASS_ON;
4526    if (bd->iconic)
4527      {
4528         if (!bd->lock_client_iconify)
4529           e_border_uniconify(bd);
4530      }
4531    else
4532      {
4533         /* FIXME: make border "urgent" for a bit - it wants attention */
4534 /*      e_border_show(bd); */
4535           if (!bd->lock_client_stacking)
4536             e_border_raise(bd);
4537      }
4538    return ECORE_CALLBACK_PASS_ON;
4539 }
4540
4541 static Eina_Bool
4542 _e_border_cb_window_destroy(void *data  __UNUSED__,
4543                             int ev_type __UNUSED__,
4544                             void       *ev)
4545 {
4546    E_Border *bd;
4547    Ecore_X_Event_Window_Destroy *e;
4548
4549    e = ev;
4550    bd = e_border_find_by_client_window(e->win);
4551    if (!bd) return ECORE_CALLBACK_PASS_ON;
4552    e_border_hide(bd, 0);
4553    e_object_del(E_OBJECT(bd));
4554    return ECORE_CALLBACK_PASS_ON;
4555 }
4556
4557 static Eina_Bool
4558 _e_border_cb_window_hide(void *data  __UNUSED__,
4559                          int ev_type __UNUSED__,
4560                          void       *ev)
4561 {
4562    E_Border *bd;
4563    Ecore_X_Event_Window_Hide *e;
4564
4565    e = ev;
4566 //   printf("HIDE: %x, event %x\n", e->win, e->event_win);
4567 // not interested in hide events from windows other than the window in question
4568    if (e->win != e->event_win) return ECORE_CALLBACK_PASS_ON;
4569    bd = e_border_find_by_client_window(e->win);
4570 //   printf("  bd = %p\n", bd);
4571    if (!bd) return ECORE_CALLBACK_PASS_ON;
4572 //   printf("  bd->ignore_first_unmap = %i\n", bd->ignore_first_unmap);
4573    if (bd->ignore_first_unmap > 0)
4574      {
4575         bd->ignore_first_unmap--;
4576         return ECORE_CALLBACK_PASS_ON;
4577      }
4578    /* Don't delete hidden or iconified windows */
4579    if ((bd->iconic) || ((!bd->visible) && (!bd->new_client)) ||
4580        (bd->await_hide_event > 0))
4581      {
4582 //        printf("  Don't delete hidden or iconified windows\n");
4583 //        printf("  bd->iconic = %i, bd->visible = %i, bd->new_client = %i, bd->await_hide_event = %i\n",
4584 //               bd->iconic, bd->visible, bd->new_client, bd->await_hide_event);
4585               if (bd->await_hide_event > 0)
4586                 {
4587                    bd->await_hide_event--;
4588                 }
4589               else
4590                 {
4591 //             printf("  hide really\n");
4592      /* Only hide the border if it is visible */
4593                       if (bd->visible) e_border_hide(bd, 1);
4594                 }
4595      }
4596    else
4597      {
4598 //             printf("  hide2\n");
4599           e_border_hide(bd, 0);
4600           e_object_del(E_OBJECT(bd));
4601      }
4602    return ECORE_CALLBACK_PASS_ON;
4603 }
4604
4605 static Eina_Bool
4606 _e_border_cb_window_reparent(void *data  __UNUSED__,
4607                              int ev_type __UNUSED__,
4608                              void *ev    __UNUSED__)
4609 {
4610 #if 0
4611    E_Border *bd;
4612    Ecore_X_Event_Window_Reparent *e;
4613
4614    e = ev;
4615    bd = e_border_find_by_client_window(e->win);
4616    if (!bd) return 1;
4617    if (e->parent == bd->client.shell_win) return 1;
4618    if (ecore_x_window_parent_get(e->win) == bd->client.shell_win)
4619      {
4620         return 1;
4621      }
4622    e_border_hide(bd, 0);
4623    e_object_del(E_OBJECT(bd));
4624 #endif
4625    return ECORE_CALLBACK_PASS_ON;
4626 }
4627
4628 static Eina_Bool
4629 _e_border_cb_window_configure_request(void *data  __UNUSED__,
4630                                       int ev_type __UNUSED__,
4631                                       void       *ev)
4632 {
4633    E_Border *bd;
4634    Ecore_X_Event_Window_Configure_Request *e;
4635
4636    e = ev;
4637    bd = e_border_find_by_client_window(e->win);
4638    if (!bd)
4639      {
4640         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
4641         if (!e_util_container_window_find(e->win))
4642           ecore_x_window_configure(e->win, e->value_mask,
4643                                    e->x, e->y, e->w, e->h, e->border,
4644                                    e->abovewin, e->detail);
4645         return ECORE_CALLBACK_PASS_ON;
4646      }
4647
4648    if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
4649        (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
4650      {
4651         int x, y;
4652
4653         x = bd->x;
4654         y = bd->y;
4655         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
4656           x = e->x;
4657         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
4658           y = e->y;
4659         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
4660             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
4661           {
4662              int w, h;
4663
4664              h = bd->h;
4665              w = bd->w;
4666              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
4667                w = e->w + bd->client_inset.l + bd->client_inset.r;
4668              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
4669                h = e->h + bd->client_inset.t + bd->client_inset.b;
4670              if ((!bd->lock_client_location) && (!bd->lock_client_size))
4671                {
4672                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
4673                     {
4674                        bd->saved.x = x - bd->zone->x;
4675                        bd->saved.y = y - bd->zone->y;
4676                        bd->saved.w = w;
4677                        bd->saved.h = h;
4678                     }
4679                   else
4680                     e_border_move_resize(bd, x, y, w, h);
4681                }
4682              else if (!bd->lock_client_location)
4683                {
4684                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
4685                     {
4686                        bd->saved.x = x - bd->zone->x;
4687                        bd->saved.y = y - bd->zone->y;
4688                     }
4689                   else
4690                     e_border_move(bd, x, y);
4691                }
4692              else if (!bd->lock_client_size)
4693                {
4694                   if ((bd->shaded) || (bd->shading))
4695                     {
4696                        int pw, ph;
4697
4698                        pw = bd->client.w;
4699                        ph = bd->client.h;
4700                        if ((bd->shade.dir == E_DIRECTION_UP) ||
4701                            (bd->shade.dir == E_DIRECTION_DOWN))
4702                          {
4703                             e_border_resize(bd, w, bd->h);
4704                             bd->client.h = ph;
4705                          }
4706                        else
4707                          {
4708                             e_border_resize(bd, bd->w, h);
4709                             bd->client.w = pw;
4710                          }
4711                     }
4712                   else
4713                     {
4714                        if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
4715                          {
4716                             bd->saved.w = w;
4717                             bd->saved.h = h;
4718                          }
4719                        else
4720                          e_border_resize(bd, w, h);
4721                     }
4722                }
4723           }
4724         else
4725           {
4726              if (!bd->lock_client_location)
4727                {
4728                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
4729                     {
4730                        bd->saved.x = x - bd->zone->x;
4731                        bd->saved.y = y - bd->zone->y;
4732                     }
4733                   else
4734                     e_border_move(bd, x, y);
4735                }
4736           }
4737      }
4738    else if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
4739             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
4740      {
4741         int w, h;
4742
4743         h = bd->h;
4744         w = bd->w;
4745         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
4746           w = e->w + bd->client_inset.l + bd->client_inset.r;
4747         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
4748           h = e->h + bd->client_inset.t + bd->client_inset.b;
4749         if (!bd->lock_client_size)
4750           {
4751              if ((bd->shaded) || (bd->shading))
4752                {
4753                   int pw, ph;
4754
4755                   pw = bd->client.w;
4756                   ph = bd->client.h;
4757                   if ((bd->shade.dir == E_DIRECTION_UP) ||
4758                       (bd->shade.dir == E_DIRECTION_DOWN))
4759                     {
4760                        e_border_resize(bd, w, bd->h);
4761                        bd->client.h = ph;
4762                     }
4763                   else
4764                     {
4765                        e_border_resize(bd, bd->w, h);
4766                        bd->client.w = pw;
4767                     }
4768                }
4769              else
4770                {
4771                   if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_NONE)
4772                     {
4773                        int zx, zy, zw, zh;
4774                        int rx = bd->x;
4775                        int ry = bd->y;
4776
4777      /*
4778       * This code does resize and move a window on a
4779       * X configure request into an useful geometry.
4780       * This is really useful for size jumping file dialogs.
4781       */
4782
4783                        if (bd->zone)
4784                          {
4785                             e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
4786
4787                             if (e_config->geometry_auto_resize_limit == 1)
4788                               {
4789                                  if (w > zw)
4790                                    w = zw;
4791
4792                                  if (h > zh)
4793                                    h = zh;
4794                               }
4795                          }
4796                        e_border_resize(bd, w, h);
4797
4798                        if (e_config->geometry_auto_move == 1)
4799                          {
4800                              /* z{x,y,w,h} are only set here; FIXME! */
4801                              if (bd->zone)
4802                                {
4803                                   // move window horizontal if resize to not useful geometry
4804                                   if (bd->x + bd->w > zx + zw)
4805                                     rx = zx + zw - bd->w;
4806                                   else if (bd->x < zx)
4807                                     rx = zx;
4808
4809                                   // move window vertical if resize to not useful geometry
4810                                   if (bd->y + bd->h > zy + zh)
4811                                     ry = zy + zh - bd->h;
4812                                   else if (bd->y < zy)
4813                                     ry = zy;
4814                                }
4815                              e_border_move(bd, rx, ry);
4816                          }
4817                     }
4818                }
4819           }
4820      }
4821    if (!bd->lock_client_stacking)
4822      {
4823         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE) &&
4824             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING))
4825           {
4826              E_Border *obd;
4827
4828              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
4829                {
4830                   obd = e_border_find_by_client_window(e->abovewin);
4831                   if (obd)
4832                     e_border_stack_above(bd, obd);
4833                }
4834              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
4835                {
4836                   obd = e_border_find_by_client_window(e->abovewin);
4837                   if (obd)
4838                     e_border_stack_below(bd, obd);
4839                }
4840              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
4841                {
4842      /* FIXME: do */
4843                }
4844              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
4845                {
4846      /* FIXME: do */
4847                }
4848              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
4849                {
4850      /* FIXME: do */
4851                }
4852           }
4853         else if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE)
4854           {
4855              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
4856                {
4857                   e_border_raise(bd);
4858                }
4859              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
4860                {
4861                   e_border_lower(bd);
4862                }
4863              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
4864                {
4865      /* FIXME: do */
4866                }
4867              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
4868                {
4869      /* FIXME: do */
4870                }
4871              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
4872                {
4873      /* FIXME: do */
4874                }
4875           }
4876      }
4877
4878    _e_border_client_move_resize_send(bd);
4879    return ECORE_CALLBACK_PASS_ON;
4880 }
4881
4882 static Eina_Bool
4883 _e_border_cb_window_resize_request(void *data  __UNUSED__,
4884                                    int ev_type __UNUSED__,
4885                                    void       *ev)
4886 {
4887    E_Border *bd;
4888    Ecore_X_Event_Window_Resize_Request *e;
4889
4890    e = ev;
4891    bd = e_border_find_by_client_window(e->win);
4892    if (!bd)
4893      {
4894         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
4895         ecore_x_window_resize(e->win, e->w, e->h);
4896         return ECORE_CALLBACK_PASS_ON;
4897      }
4898    {
4899       int w, h;
4900
4901       w = e->w + bd->client_inset.l + bd->client_inset.r;
4902       h = e->h + bd->client_inset.t + bd->client_inset.b;
4903       if ((bd->shaded) || (bd->shading))
4904         {
4905            int pw, ph;
4906
4907            pw = bd->client.w;
4908            ph = bd->client.h;
4909            if ((bd->shade.dir == E_DIRECTION_UP) ||
4910                (bd->shade.dir == E_DIRECTION_DOWN))
4911              {
4912                 e_border_resize(bd, w, bd->h);
4913                 bd->client.h = ph;
4914              }
4915            else
4916              {
4917                 e_border_resize(bd, bd->w, h);
4918                 bd->client.w = pw;
4919              }
4920         }
4921       else
4922         e_border_resize(bd, w, h);
4923    }
4924
4925    _e_border_client_move_resize_send(bd);
4926    return ECORE_CALLBACK_PASS_ON;
4927 }
4928
4929 static Eina_Bool
4930 _e_border_cb_window_gravity(void *data  __UNUSED__,
4931                             int ev_type __UNUSED__,
4932                             void *ev    __UNUSED__)
4933 {
4934 //   E_Border *bd;
4935 //   Ecore_X_Event_Window_Gravity *e;
4936
4937 //   e = ev;
4938 //   bd = e_border_find_by_client_window(e->win);
4939 //   if (!bd) return 1;
4940              return 1;
4941 }
4942
4943 static Eina_Bool
4944 _e_border_cb_window_stack_request(void *data  __UNUSED__,
4945                                   int ev_type __UNUSED__,
4946                                   void       *ev)
4947 {
4948    E_Border *bd;
4949    Ecore_X_Event_Window_Stack_Request *e;
4950
4951    e = ev;
4952    bd = e_border_find_by_client_window(e->win);
4953    if (!bd)
4954      {
4955         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
4956         if (!e_util_container_window_find(e->win))
4957           {
4958              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
4959                ecore_x_window_raise(e->win);
4960              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
4961                ecore_x_window_lower(e->win);
4962           }
4963         return ECORE_CALLBACK_PASS_ON;
4964      }
4965    if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
4966      e_border_raise(bd);
4967    else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
4968      e_border_lower(bd);
4969    return ECORE_CALLBACK_PASS_ON;
4970 }
4971
4972 static Eina_Bool
4973 _e_border_cb_window_property(void *data  __UNUSED__,
4974                              int ev_type __UNUSED__,
4975                              void       *ev)
4976 {
4977    E_Border *bd;
4978    Ecore_X_Event_Window_Property *e;
4979
4980    e = ev;
4981    bd = e_border_find_by_client_window(e->win);
4982    if (!bd) return ECORE_CALLBACK_PASS_ON;
4983    if (e->atom == ECORE_X_ATOM_WM_NAME)
4984      {
4985         if ((!bd->client.netwm.name) &&
4986             (!bd->client.netwm.fetch.name))
4987           {
4988              bd->client.icccm.fetch.title = 1;
4989              bd->changed = 1;
4990           }
4991      }
4992    else if (e->atom == ECORE_X_ATOM_NET_WM_NAME)
4993      {
4994         bd->client.netwm.fetch.name = 1;
4995         bd->changed = 1;
4996      }
4997    else if (e->atom == ECORE_X_ATOM_WM_CLASS)
4998      {
4999         bd->client.icccm.fetch.name_class = 1;
5000         bd->changed = 1;
5001      }
5002    else if (e->atom == ECORE_X_ATOM_WM_ICON_NAME)
5003      {
5004         if ((!bd->client.netwm.icon_name) &&
5005             (!bd->client.netwm.fetch.icon_name))
5006           {
5007              bd->client.icccm.fetch.icon_name = 1;
5008              bd->changed = 1;
5009           }
5010      }
5011    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON_NAME)
5012      {
5013         bd->client.netwm.fetch.icon_name = 1;
5014         bd->changed = 1;
5015      }
5016    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
5017      {
5018         bd->client.icccm.fetch.machine = 1;
5019         bd->changed = 1;
5020      }
5021    else if (e->atom == ECORE_X_ATOM_WM_PROTOCOLS)
5022      {
5023         bd->client.icccm.fetch.protocol = 1;
5024         bd->changed = 1;
5025      }
5026    else if (e->atom == ECORE_X_ATOM_WM_HINTS)
5027      {
5028         bd->client.icccm.fetch.hints = 1;
5029         bd->changed = 1;
5030      }
5031    else if (e->atom == ECORE_X_ATOM_WM_NORMAL_HINTS)
5032      {
5033         bd->client.icccm.fetch.size_pos_hints = 1;
5034         bd->changed = 1;
5035      }
5036    else if (e->atom == ECORE_X_ATOM_MOTIF_WM_HINTS)
5037      {
5038         /*
5039            if ((bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UNKNOWN) &&
5040             (!bd->client.netwm.fetch.type))
5041            {
5042          */
5043           bd->client.mwm.fetch.hints = 1;
5044           bd->changed = 1;
5045           /*
5046              }
5047            */
5048      }
5049    else if (e->atom == ECORE_X_ATOM_WM_TRANSIENT_FOR)
5050      {
5051         bd->client.icccm.fetch.transient_for = 1;
5052         bd->changed = 1;
5053      }
5054    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_LEADER)
5055      {
5056         bd->client.icccm.fetch.client_leader = 1;
5057         bd->changed = 1;
5058      }
5059    else if (e->atom == ECORE_X_ATOM_WM_WINDOW_ROLE)
5060      {
5061         bd->client.icccm.fetch.window_role = 1;
5062         bd->changed = 1;
5063      }
5064    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON)
5065      {
5066         bd->client.netwm.fetch.icon = 1;
5067         bd->changed = 1;
5068      }
5069    else if (e->atom == ATM__QTOPIA_SOFT_MENU)
5070      {
5071         bd->client.qtopia.fetch.soft_menu = 1;
5072         bd->changed = 1;
5073      }
5074    else if (e->atom == ATM__QTOPIA_SOFT_MENUS)
5075      {
5076         bd->client.qtopia.fetch.soft_menus = 1;
5077         bd->changed = 1;
5078      }
5079    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
5080      {
5081         bd->client.vkbd.fetch.state = 1;
5082         bd->changed = 1;
5083      }
5084    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
5085      {
5086         bd->client.vkbd.fetch.vkbd = 1;
5087         bd->changed = 1;
5088      }
5089    else if (e->atom == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
5090      {
5091         bd->client.illume.conformant.fetch.conformant = 1;
5092         bd->changed = 1;
5093      }
5094    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
5095      {
5096         bd->client.illume.quickpanel.fetch.state = 1;
5097         bd->changed = 1;
5098      }
5099    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
5100      {
5101         bd->client.illume.quickpanel.fetch.quickpanel = 1;
5102         bd->changed = 1;
5103      }
5104    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
5105      {
5106         bd->client.illume.quickpanel.fetch.priority.major = 1;
5107         bd->changed = 1;
5108      }
5109    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
5110      {
5111         bd->client.illume.quickpanel.fetch.priority.minor = 1;
5112         bd->changed = 1;
5113      }
5114    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
5115      {
5116         bd->client.illume.quickpanel.fetch.zone = 1;
5117         bd->changed = 1;
5118      }
5119    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
5120      {
5121         bd->client.illume.drag.fetch.locked = 1;
5122         bd->changed = 1;
5123      }
5124    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG)
5125      {
5126         bd->client.illume.drag.fetch.drag = 1;
5127         bd->changed = 1;
5128      }
5129    /*
5130       else if (e->atom == ECORE_X_ATOM_NET_WM_USER_TIME)
5131       {
5132         bd->client.netwm.fetch.user_time = 1;
5133         bd->changed = 1;
5134       }
5135       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT)
5136       {
5137         bd->client.netwm.fetch.strut = 1;
5138         bd->changed = 1;
5139       }
5140       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
5141       {
5142         bd->client.netwm.fetch.strut = 1;
5143         bd->changed = 1;
5144       }
5145     */
5146    else if (e->atom == ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER)
5147      {
5148         printf("ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER\n");
5149      }
5150
5151    return ECORE_CALLBACK_PASS_ON;
5152 }
5153
5154 static Eina_Bool
5155 _e_border_cb_window_colormap(void *data  __UNUSED__,
5156                              int ev_type __UNUSED__,
5157                              void       *ev)
5158 {
5159    E_Border *bd;
5160    Ecore_X_Event_Window_Colormap *e;
5161
5162    e = ev;
5163    bd = e_border_find_by_client_window(e->win);
5164    if (!bd) return ECORE_CALLBACK_PASS_ON;
5165    return ECORE_CALLBACK_PASS_ON;
5166 }
5167
5168 static Eina_Bool
5169 _e_border_cb_window_shape(void *data  __UNUSED__,
5170                           int ev_type __UNUSED__,
5171                           void       *ev)
5172 {
5173    E_Border *bd;
5174    Ecore_X_Event_Window_Shape *e;
5175
5176    e = ev;
5177    bd = e_border_find_by_client_window(e->win);
5178
5179    if (e->type == ECORE_X_SHAPE_INPUT)
5180      {
5181         if (bd)
5182           {
5183              bd->need_shape_merge = 1;
5184 // YYY             bd->shaped_input = 1;
5185              bd->changes.shape_input = 1;
5186              bd->changed = 1;
5187           }
5188
5189         return ECORE_CALLBACK_PASS_ON;
5190      }
5191
5192    if (bd)
5193      {
5194         bd->changes.shape = 1;
5195         bd->changed = 1;
5196         return ECORE_CALLBACK_PASS_ON;
5197      }
5198    bd = e_border_find_by_window(e->win);
5199    if (bd)
5200      {
5201         bd->need_shape_export = 1;
5202         bd->changed = 1;
5203         return ECORE_CALLBACK_PASS_ON;
5204      }
5205    bd = e_border_find_by_frame_window(e->win);
5206    if (bd)
5207      {
5208         bd->need_shape_merge = 1;
5209         bd->changed = 1;
5210         return ECORE_CALLBACK_PASS_ON;
5211      }
5212    return ECORE_CALLBACK_PASS_ON;
5213 }
5214
5215 static Eina_Bool
5216 _e_border_cb_window_focus_in(void *data  __UNUSED__,
5217                              int ev_type __UNUSED__,
5218                              void       *ev)
5219 {
5220    E_Border *bd;
5221    Ecore_X_Event_Window_Focus_In *e;
5222
5223    e = ev;
5224    bd = e_border_find_by_client_window(e->win);
5225    if (!bd) return ECORE_CALLBACK_PASS_ON;
5226 #ifdef INOUTDEBUG_FOCUS
5227    {
5228       time_t t;
5229       char *ct;
5230
5231       const char *modes[] = {
5232          "MODE_NORMAL",
5233          "MODE_WHILE_GRABBED",
5234          "MODE_GRAB",
5235          "MODE_UNGRAB"
5236       };
5237       const char *details[] = {
5238          "DETAIL_ANCESTOR",
5239          "DETAIL_VIRTUAL",
5240          "DETAIL_INFERIOR",
5241          "DETAIL_NON_LINEAR",
5242          "DETAIL_NON_LINEAR_VIRTUAL",
5243          "DETAIL_POINTER",
5244          "DETAIL_POINTER_ROOT",
5245          "DETAIL_DETAIL_NONE"
5246       };
5247       t = time(NULL);
5248       ct = ctime(&t);
5249       ct[strlen(ct) - 1] = 0;
5250       printf("FF ->IN %i 0x%x %s md=%s dt=%s\n",
5251              e->time,
5252              e->win,
5253              ct,
5254              modes[e->mode],
5255              details[e->detail]);
5256
5257       printf("%s cb focus in %d %d\n",
5258              e_border_name_get(bd),
5259              bd->client.icccm.accepts_focus,
5260              bd->client.icccm.take_focus);
5261    }
5262 #endif
5263    if (e->mode == ECORE_X_EVENT_MODE_GRAB)
5264      {
5265         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
5266      }
5267    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
5268      {
5269         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
5270      }
5271
5272    /* ignore focus in from !take_focus windows, we just gave it em */
5273    /* if (!bd->client.icccm.take_focus)
5274     *   return ECORE_CALLBACK_PASS_ON; */
5275
5276    /* should be equal, maybe some clients dont reply with the proper timestamp ? */
5277    if (e->time >= focus_time)
5278      e_border_focus_set(bd, 1, 0);
5279    return ECORE_CALLBACK_PASS_ON;
5280 }
5281
5282 static Eina_Bool
5283 _e_border_cb_window_focus_out(void *data  __UNUSED__,
5284                               int ev_type __UNUSED__,
5285                               void       *ev)
5286 {
5287    E_Border *bd;
5288    Ecore_X_Event_Window_Focus_Out *e;
5289
5290    e = ev;
5291    bd = e_border_find_by_client_window(e->win);
5292    if (!bd) return ECORE_CALLBACK_PASS_ON;
5293 #ifdef INOUTDEBUG_FOCUS
5294    {
5295       time_t t;
5296       char *ct;
5297
5298       const char *modes[] = {
5299          "MODE_NORMAL",
5300          "MODE_WHILE_GRABBED",
5301          "MODE_GRAB",
5302          "MODE_UNGRAB"
5303       };
5304       const char *details[] = {
5305          "DETAIL_ANCESTOR",
5306          "DETAIL_VIRTUAL",
5307          "DETAIL_INFERIOR",
5308          "DETAIL_NON_LINEAR",
5309          "DETAIL_NON_LINEAR_VIRTUAL",
5310          "DETAIL_POINTER",
5311          "DETAIL_POINTER_ROOT",
5312          "DETAIL_DETAIL_NONE"
5313       };
5314       t = time(NULL);
5315       ct = ctime(&t);
5316       ct[strlen(ct) - 1] = 0;
5317       printf("FF <-OUT %i 0x%x %s md=%s dt=%s\n",
5318              e->time,
5319              e->win,
5320              ct,
5321              modes[e->mode],
5322              details[e->detail]);
5323
5324       printf("%s cb focus out %d %d\n",
5325              e_border_name_get(bd),
5326              bd->client.icccm.accepts_focus,
5327              bd->client.icccm.take_focus);
5328    }
5329 #endif
5330    if (e->mode == ECORE_X_EVENT_MODE_NORMAL)
5331      {
5332         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
5333         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
5334           return ECORE_CALLBACK_PASS_ON;
5335         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
5336           return ECORE_CALLBACK_PASS_ON;
5337      }
5338    else if (e->mode == ECORE_X_EVENT_MODE_GRAB)
5339      {
5340         if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR) return ECORE_CALLBACK_PASS_ON;
5341         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
5342           return ECORE_CALLBACK_PASS_ON;
5343         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
5344           return ECORE_CALLBACK_PASS_ON;
5345         else if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
5346           return ECORE_CALLBACK_PASS_ON;
5347         else if (e->detail == ECORE_X_EVENT_DETAIL_VIRTUAL)
5348           return ECORE_CALLBACK_PASS_ON;
5349      }
5350    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
5351      {
5352         /* for firefox/thunderbird (xul) menu walking */
5353         /* NB: why did i disable this before? */
5354           if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
5355           else if (e->detail == ECORE_X_EVENT_DETAIL_POINTER)
5356             return ECORE_CALLBACK_PASS_ON;
5357      }
5358    else if (e->mode == ECORE_X_EVENT_MODE_WHILE_GRABBED)
5359      {
5360         if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR) return ECORE_CALLBACK_PASS_ON;
5361         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
5362           return ECORE_CALLBACK_PASS_ON;
5363      }
5364    e_border_focus_set(bd, 0, 0);
5365    return ECORE_CALLBACK_PASS_ON;
5366 }
5367
5368 static Eina_Bool
5369 _e_border_cb_client_message(void *data  __UNUSED__,
5370                             int ev_type __UNUSED__,
5371                             void *ev    __UNUSED__)
5372 {
5373    /*
5374       E_Border *bd;
5375       Ecore_X_Event_Client_Message *e;
5376
5377       e = ev;
5378       bd = e_border_find_by_client_window(e->win);
5379       if (!bd) return 1;
5380     */
5381      return 1;
5382 }
5383
5384 static Eina_Bool
5385 _e_border_cb_window_state_request(void *data  __UNUSED__,
5386                                   int ev_type __UNUSED__,
5387                                   void       *ev)
5388 {
5389    E_Border *bd;
5390    Ecore_X_Event_Window_State_Request *e;
5391    int i;
5392
5393    e = ev;
5394    bd = e_border_find_by_client_window(e->win);
5395    if (!bd) return ECORE_CALLBACK_PASS_ON;
5396
5397    for (i = 0; i < 2; i++)
5398      e_hints_window_state_update(bd, e->state[i], e->action);
5399
5400    return ECORE_CALLBACK_PASS_ON;
5401 }
5402
5403 static Eina_Bool
5404 _e_border_cb_window_move_resize_request(void *data  __UNUSED__,
5405                                         int ev_type __UNUSED__,
5406                                         void       *ev)
5407 {
5408    E_Border *bd;
5409    Ecore_X_Event_Window_Move_Resize_Request *e;
5410
5411    e = ev;
5412    bd = e_border_find_by_client_window(e->win);
5413    if (!bd) return ECORE_CALLBACK_PASS_ON;
5414
5415    if ((bd->shaded) || (bd->shading) ||
5416        (bd->fullscreen) || (bd->moving) ||
5417        (bd->resize_mode != RESIZE_NONE))
5418      return ECORE_CALLBACK_PASS_ON;
5419
5420    if ((e->button >= 1) && (e->button <= 3))
5421      {
5422         bd->mouse.last_down[e->button - 1].mx = e->x;
5423         bd->mouse.last_down[e->button - 1].my = e->y;
5424         bd->mouse.last_down[e->button - 1].x = bd->x;
5425         bd->mouse.last_down[e->button - 1].y = bd->y;
5426         bd->mouse.last_down[e->button - 1].w = bd->w;
5427         bd->mouse.last_down[e->button - 1].h = bd->h;
5428      }
5429    else
5430      {
5431         bd->moveinfo.down.x = bd->x;
5432         bd->moveinfo.down.y = bd->y;
5433         bd->moveinfo.down.w = bd->w;
5434         bd->moveinfo.down.h = bd->h;
5435      }
5436    bd->mouse.current.mx = e->x;
5437    bd->mouse.current.my = e->y;
5438    bd->moveinfo.down.button = e->button;
5439    bd->moveinfo.down.mx = e->x;
5440    bd->moveinfo.down.my = e->y;
5441    grabbed = 1;
5442
5443    if (!bd->lock_user_stacking)
5444      e_border_raise(bd);
5445
5446    if (e->direction == MOVE)
5447      {
5448         bd->cur_mouse_action = e_action_find("window_move");
5449         if (bd->cur_mouse_action)
5450           {
5451              if ((!bd->cur_mouse_action->func.end_mouse) &&
5452                  (!bd->cur_mouse_action->func.end))
5453                bd->cur_mouse_action = NULL;
5454              if (bd->cur_mouse_action)
5455                {
5456                   e_object_ref(E_OBJECT(bd->cur_mouse_action));
5457                   bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
5458                }
5459           }
5460         return ECORE_CALLBACK_PASS_ON;
5461      }
5462
5463    if (!_e_border_resize_begin(bd))
5464      return ECORE_CALLBACK_PASS_ON;
5465
5466    switch(e->direction)
5467      {
5468       case RESIZE_TL:
5469         bd->resize_mode = RESIZE_TL;
5470         GRAV_SET(bd, ECORE_X_GRAVITY_SE);
5471         break;
5472
5473       case RESIZE_T:
5474         bd->resize_mode = RESIZE_T;
5475         GRAV_SET(bd, ECORE_X_GRAVITY_S);
5476         break;
5477
5478       case RESIZE_TR:
5479         bd->resize_mode = RESIZE_TR;
5480         GRAV_SET(bd, ECORE_X_GRAVITY_SW);
5481         break;
5482
5483       case RESIZE_R:
5484         bd->resize_mode = RESIZE_R;
5485         GRAV_SET(bd, ECORE_X_GRAVITY_W);
5486         break;
5487
5488       case RESIZE_BR:
5489         bd->resize_mode = RESIZE_BR;
5490         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
5491         break;
5492
5493       case RESIZE_B:
5494         bd->resize_mode = RESIZE_B;
5495         GRAV_SET(bd, ECORE_X_GRAVITY_N);
5496         break;
5497
5498       case RESIZE_BL:
5499         bd->resize_mode = RESIZE_BL;
5500         GRAV_SET(bd, ECORE_X_GRAVITY_NE);
5501         break;
5502
5503       case RESIZE_L:
5504         bd->resize_mode = RESIZE_L;
5505         GRAV_SET(bd, ECORE_X_GRAVITY_E);
5506         break;
5507
5508       default:
5509         return ECORE_CALLBACK_PASS_ON;
5510      }
5511
5512    bd->cur_mouse_action = e_action_find("window_resize");
5513    if (bd->cur_mouse_action)
5514      {
5515         if ((!bd->cur_mouse_action->func.end_mouse) &&
5516             (!bd->cur_mouse_action->func.end))
5517           bd->cur_mouse_action = NULL;
5518      }
5519    if (bd->cur_mouse_action)
5520      e_object_ref(E_OBJECT(bd->cur_mouse_action));
5521
5522    return ECORE_CALLBACK_PASS_ON;
5523 }
5524
5525 static Eina_Bool
5526 _e_border_cb_desktop_change(void *data  __UNUSED__,
5527                             int ev_type __UNUSED__,
5528                             void       *ev)
5529 {
5530    E_Border *bd;
5531    Ecore_X_Event_Desktop_Change *e;
5532
5533    e = ev;
5534    bd = e_border_find_by_client_window(e->win);
5535    if (bd)
5536      {
5537         if (e->desk == 0xffffffff)
5538           e_border_stick(bd);
5539         else if ((int)e->desk < (bd->zone->desk_x_count * bd->zone->desk_y_count))
5540           {
5541              E_Desk *desk;
5542
5543              desk = e_desk_at_pos_get(bd->zone, e->desk);
5544              if (desk)
5545                e_border_desk_set(bd, desk);
5546           }
5547      }
5548    else
5549      {
5550         ecore_x_netwm_desktop_set(e->win, e->desk);
5551      }
5552    return ECORE_CALLBACK_PASS_ON;
5553 }
5554
5555 static Eina_Bool
5556 _e_border_cb_sync_alarm(void *data  __UNUSED__,
5557                         int ev_type __UNUSED__,
5558                         void       *ev)
5559 {
5560    E_Border *bd;
5561    Ecore_X_Event_Sync_Alarm *e;
5562    unsigned int serial;
5563
5564    e = ev;
5565    bd = e_border_find_by_alarm(e->alarm);
5566    if (!bd) return ECORE_CALLBACK_PASS_ON;
5567
5568    if (bd->client.netwm.sync.wait)
5569      bd->client.netwm.sync.wait--;
5570
5571    if (ecore_x_sync_counter_query(bd->client.netwm.sync.counter, &serial))
5572      {
5573         E_Border_Pending_Move_Resize *pnd = NULL;
5574
5575         /* skip pending for which we didn't get a reply */
5576         while (bd->pending_move_resize)
5577           {
5578              pnd = bd->pending_move_resize->data;
5579              bd->pending_move_resize = eina_list_remove(bd->pending_move_resize, pnd);
5580
5581              if (serial == pnd->serial)
5582                break;
5583
5584              E_FREE(pnd);
5585           }
5586
5587         if (pnd)
5588           {
5589              bd->x = pnd->x;
5590              bd->y = pnd->y;
5591              bd->w = pnd->w;
5592              bd->h = pnd->h;
5593              bd->client.w = bd->w - (bd->client_inset.l + bd->client_inset.r);
5594              bd->client.h = bd->h - (bd->client_inset.t + bd->client_inset.b);
5595              E_FREE(pnd);
5596           }
5597      }
5598
5599    bd->changes.size = 1;
5600    bd->changes.pos = 1;
5601
5602    _e_border_eval(bd);
5603    evas_render(bd->bg_evas);
5604
5605    ecore_x_pointer_xy_get(e_manager_current_get()->root,
5606                           &bd->mouse.current.mx,
5607                           &bd->mouse.current.my);
5608
5609    bd->client.netwm.sync.send_time = ecore_loop_time_get();
5610    _e_border_resize_handle(bd);
5611
5612    return ECORE_CALLBACK_PASS_ON;
5613 }
5614
5615 static Eina_Bool
5616 _e_border_cb_efreet_cache_update(void *data  __UNUSED__,
5617                                  int ev_type __UNUSED__,
5618                                  void *ev    __UNUSED__)
5619 {
5620    Eina_List *l;
5621    E_Border *bd;
5622
5623    /* mark all borders for desktop/icon updates */
5624    EINA_LIST_FOREACH(borders, l, bd)
5625      {
5626         if (bd->desktop)
5627           {
5628              efreet_desktop_free(bd->desktop);
5629              bd->desktop = NULL;
5630           }
5631         bd->changes.icon = 1;
5632         bd->changed = 1;
5633      }
5634    /*
5635       e_init_status_set(_("Desktop files scan done"));
5636       e_init_done();
5637     */
5638    return ECORE_CALLBACK_PASS_ON;
5639 }
5640
5641 static Eina_Bool
5642 _e_border_cb_config_icon_theme(void *data  __UNUSED__,
5643                                int ev_type __UNUSED__,
5644                                void *ev    __UNUSED__)
5645 {
5646    Eina_List *l;
5647    E_Border *bd;
5648
5649    /* mark all borders for desktop/icon updates */
5650    EINA_LIST_FOREACH(borders, l, bd)
5651      {
5652         bd->changes.icon = 1;
5653         bd->changed = 1;
5654      }
5655    return ECORE_CALLBACK_PASS_ON;
5656 }
5657
5658 /* FIXME:
5659  * Using '2' is bad, may change in zone flip code.
5660  * Calculate pos from e->x and e->y
5661  */
5662 static Eina_Bool
5663 _e_border_cb_pointer_warp(void *data  __UNUSED__,
5664                           int ev_type __UNUSED__,
5665                           void       *ev)
5666 {
5667    E_Event_Pointer_Warp *e;
5668
5669    e = ev;
5670    if (!move) return ECORE_CALLBACK_PASS_ON;
5671    e_border_move(move, move->x + (e->curr.x - e->prev.x), move->y + (e->curr.y - e->prev.y));
5672    return ECORE_CALLBACK_PASS_ON;
5673 }
5674
5675 static void
5676 _e_border_cb_signal_bind(void            *data,
5677                          Evas_Object *obj __UNUSED__,
5678                          const char      *emission,
5679                          const char      *source)
5680 {
5681    E_Border *bd;
5682
5683    bd = data;
5684    if (e_dnd_active()) return;
5685    e_bindings_signal_handle(E_BINDING_CONTEXT_BORDER, E_OBJECT(bd),
5686                             emission, source);
5687 }
5688
5689 static Eina_Bool
5690 _e_border_cb_mouse_in(void    *data,
5691                       int type __UNUSED__,
5692                       void    *event)
5693 {
5694    Ecore_X_Event_Mouse_In *ev;
5695    E_Border *bd;
5696
5697    ev = event;
5698    bd = data;
5699 #ifdef INOUTDEBUG_MOUSE
5700    {
5701       time_t t;
5702       char *ct;
5703
5704       const char *modes[] = {
5705          "MODE_NORMAL",
5706          "MODE_WHILE_GRABBED",
5707          "MODE_GRAB",
5708          "MODE_UNGRAB"
5709       };
5710       const char *details[] = {
5711          "DETAIL_ANCESTOR",
5712          "DETAIL_VIRTUAL",
5713          "DETAIL_INFERIOR",
5714          "DETAIL_NON_LINEAR",
5715          "DETAIL_NON_LINEAR_VIRTUAL",
5716          "DETAIL_POINTER",
5717          "DETAIL_POINTER_ROOT",
5718          "DETAIL_DETAIL_NONE"
5719       };
5720       t = time(NULL);
5721       ct = ctime(&t);
5722       ct[strlen(ct) - 1] = 0;
5723       printf("@@ ->IN 0x%x 0x%x %s md=%s dt=%s\n",
5724              ev->win, ev->event_win,
5725              ct,
5726              modes[ev->mode],
5727              details[ev->detail]);
5728    }
5729 #endif
5730    if (grabbed) return ECORE_CALLBACK_PASS_ON;
5731    if (ev->event_win == bd->win)
5732      {
5733         e_focus_event_mouse_in(bd);
5734      }
5735 #if 0
5736    if ((ev->win != bd->win) &&
5737        (ev->win != bd->event_win) &&
5738        (ev->event_win != bd->win) &&
5739        (ev->event_win != bd->event_win))
5740      return ECORE_CALLBACK_PASS_ON;
5741 #else
5742    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
5743 #endif
5744    bd->mouse.current.mx = ev->root.x;
5745    bd->mouse.current.my = ev->root.y;
5746    evas_event_feed_mouse_in(bd->bg_evas, ev->time, NULL);
5747    return ECORE_CALLBACK_PASS_ON;
5748 }
5749
5750 static Eina_Bool
5751 _e_border_cb_mouse_out(void    *data,
5752                        int type __UNUSED__,
5753                        void    *event)
5754 {
5755    Ecore_X_Event_Mouse_Out *ev;
5756    E_Border *bd;
5757
5758    ev = event;
5759    bd = data;
5760 #ifdef INOUTDEBUG_MOUSE
5761    {
5762       time_t t;
5763       char *ct;
5764
5765       const char *modes[] = {
5766          "MODE_NORMAL",
5767          "MODE_WHILE_GRABBED",
5768          "MODE_GRAB",
5769          "MODE_UNGRAB"
5770       };
5771       const char *details[] = {
5772          "DETAIL_ANCESTOR",
5773          "DETAIL_VIRTUAL",
5774          "DETAIL_INFERIOR",
5775          "DETAIL_NON_LINEAR",
5776          "DETAIL_NON_LINEAR_VIRTUAL",
5777          "DETAIL_POINTER",
5778          "DETAIL_POINTER_ROOT",
5779          "DETAIL_DETAIL_NONE"
5780       };
5781       t = time(NULL);
5782       ct = ctime(&t);
5783       ct[strlen(ct) - 1] = 0;
5784       printf("@@ <-OUT 0x%x 0x%x %s md=%s dt=%s\n",
5785              ev->win, ev->event_win,
5786              ct,
5787              modes[ev->mode],
5788              details[ev->detail]);
5789    }
5790 #endif
5791    if (grabbed) return ECORE_CALLBACK_PASS_ON;
5792 #if 0
5793    if (ev->event_win == bd->win)
5794      {
5795         if (bd->fullscreen)
5796           return ECORE_CALLBACK_PASS_ON;
5797         if ((ev->mode == ECORE_X_EVENT_MODE_UNGRAB) &&
5798             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
5799           return ECORE_CALLBACK_PASS_ON;
5800         if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
5801           return ECORE_CALLBACK_PASS_ON;
5802         if ((ev->mode == ECORE_X_EVENT_MODE_NORMAL) &&
5803             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
5804           return ECORE_CALLBACK_PASS_ON;
5805         e_focus_event_mouse_out(bd);
5806      }
5807 #endif
5808 #if 0
5809    if ((ev->win != bd->win) &&
5810        (ev->win != bd->event_win) &&
5811        (ev->event_win != bd->win) &&
5812        (ev->event_win != bd->event_win))
5813      return ECORE_CALLBACK_PASS_ON;
5814 #else
5815    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
5816 #endif
5817    bd->mouse.current.mx = ev->root.x;
5818    bd->mouse.current.my = ev->root.y;
5819    if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
5820      evas_event_feed_mouse_cancel(bd->bg_evas, ev->time, NULL);
5821    evas_event_feed_mouse_out(bd->bg_evas, ev->time, NULL);
5822    return ECORE_CALLBACK_PASS_ON;
5823 }
5824
5825 static Eina_Bool
5826 _e_border_cb_mouse_wheel(void    *data,
5827                          int type __UNUSED__,
5828                          void    *event)
5829 {
5830    Ecore_Event_Mouse_Wheel *ev;
5831    E_Border *bd;
5832
5833    ev = event;
5834    bd = data;
5835    if (ev->event_window == bd->win)
5836      {
5837         bd->mouse.current.mx = ev->root.x;
5838         bd->mouse.current.my = ev->root.y;
5839         if (!bd->cur_mouse_action)
5840           e_bindings_wheel_event_handle(E_BINDING_CONTEXT_BORDER,
5841                                         E_OBJECT(bd), ev);
5842      }
5843    evas_event_feed_mouse_wheel(bd->bg_evas, ev->direction, ev->z, ev->timestamp, NULL);
5844    return ECORE_CALLBACK_PASS_ON;
5845 }
5846
5847 static Eina_Bool
5848 _e_border_cb_mouse_down(void    *data,
5849                         int type __UNUSED__,
5850                         void    *event)
5851 {
5852    Ecore_Event_Mouse_Button *ev;
5853    E_Border *bd;
5854
5855    ev = event;
5856    bd = data;
5857    if (ev->event_window == bd->win)
5858      {
5859         if ((ev->buttons >= 1) && (ev->buttons <= 3))
5860           {
5861              bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
5862              bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
5863              bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
5864              bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
5865              bd->mouse.last_down[ev->buttons - 1].w = bd->w;
5866              bd->mouse.last_down[ev->buttons - 1].h = bd->h;
5867           }
5868         else
5869           {
5870              bd->moveinfo.down.x = bd->x + bd->fx.x;
5871              bd->moveinfo.down.y = bd->y + bd->fx.y;
5872              bd->moveinfo.down.w = bd->w;
5873              bd->moveinfo.down.h = bd->h;
5874           }
5875         bd->mouse.current.mx = ev->root.x;
5876         bd->mouse.current.my = ev->root.y;
5877         if (!bd->cur_mouse_action)
5878           {
5879              bd->cur_mouse_action =
5880                e_bindings_mouse_down_event_handle(E_BINDING_CONTEXT_BORDER,
5881                                                   E_OBJECT(bd), ev);
5882              if (bd->cur_mouse_action)
5883                {
5884                   if ((!bd->cur_mouse_action->func.end_mouse) &&
5885                       (!bd->cur_mouse_action->func.end))
5886                     bd->cur_mouse_action = NULL;
5887                   if (bd->cur_mouse_action)
5888                     e_object_ref(E_OBJECT(bd->cur_mouse_action));
5889                }
5890           }
5891         e_focus_event_mouse_down(bd);
5892      }
5893    if (ev->window != ev->event_window)
5894      {
5895         return 1;
5896      }
5897    if ((ev->window != bd->event_win) && (ev->event_window != bd->win))
5898      {
5899         return 1;
5900      }
5901    if ((ev->buttons >= 1) && (ev->buttons <= 3))
5902      {
5903         bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
5904         bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
5905         bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
5906         bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
5907         bd->mouse.last_down[ev->buttons - 1].w = bd->w;
5908         bd->mouse.last_down[ev->buttons - 1].h = bd->h;
5909      }
5910    else
5911      {
5912         bd->moveinfo.down.x = bd->x + bd->fx.x;
5913         bd->moveinfo.down.y = bd->y + bd->fx.y;
5914         bd->moveinfo.down.w = bd->w;
5915         bd->moveinfo.down.h = bd->h;
5916      }
5917    bd->mouse.current.mx = ev->root.x;
5918    bd->mouse.current.my = ev->root.y;
5919 /*
5920    if (bd->moving)
5921      {
5922      }
5923    else if (bd->resize_mode != RESIZE_NONE)
5924      {
5925      }
5926    else
5927  */
5928    {
5929       Evas_Button_Flags flags = EVAS_BUTTON_NONE;
5930
5931       if (ev->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK;
5932       if (ev->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK;
5933       evas_event_feed_mouse_down(bd->bg_evas, ev->buttons, flags, ev->timestamp, NULL);
5934    }
5935    return ECORE_CALLBACK_PASS_ON;
5936 }
5937
5938 static Eina_Bool
5939 _e_border_cb_mouse_up(void    *data,
5940                       int type __UNUSED__,
5941                       void    *event)
5942 {
5943    Ecore_Event_Mouse_Button *ev;
5944    E_Border *bd;
5945
5946    ev = event;
5947    bd = data;
5948    if (ev->event_window == bd->win)
5949      {
5950         if ((ev->buttons >= 1) && (ev->buttons <= 3))
5951           {
5952              bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
5953              bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
5954              bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
5955              bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
5956           }
5957         bd->mouse.current.mx = ev->root.x;
5958         bd->mouse.current.my = ev->root.y;
5959         /* also we dont pass the same params that went in - then again that */
5960         /* should be ok as we are just ending the action if it has an end */
5961         if (bd->cur_mouse_action)
5962           {
5963              if (bd->cur_mouse_action->func.end_mouse)
5964                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", ev);
5965              else if (bd->cur_mouse_action->func.end)
5966                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
5967              e_object_unref(E_OBJECT(bd->cur_mouse_action));
5968              bd->cur_mouse_action = NULL;
5969           }
5970         else
5971           {
5972              if (!e_bindings_mouse_up_event_handle(E_BINDING_CONTEXT_BORDER, E_OBJECT(bd), ev))
5973                e_focus_event_mouse_up(bd);
5974           }
5975      }
5976    if (ev->window != bd->event_win) return ECORE_CALLBACK_PASS_ON;
5977    if ((ev->buttons >= 1) && (ev->buttons <= 3))
5978      {
5979         bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
5980         bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
5981         bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
5982         bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
5983      }
5984    bd->mouse.current.mx = ev->root.x;
5985    bd->mouse.current.my = ev->root.y;
5986
5987    bd->drag.start = 0;
5988
5989    evas_event_feed_mouse_up(bd->bg_evas, ev->buttons, EVAS_BUTTON_NONE, ev->timestamp, NULL);
5990    return ECORE_CALLBACK_PASS_ON;
5991 }
5992
5993 static Eina_Bool
5994 _e_border_cb_mouse_move(void    *data,
5995                         int type __UNUSED__,
5996                         void    *event)
5997 {
5998    Ecore_Event_Mouse_Move *ev;
5999    E_Border *bd;
6000
6001    ev = event;
6002    bd = data;
6003    if ((ev->window != bd->event_win) &&
6004        (ev->event_window != bd->win)) return ECORE_CALLBACK_PASS_ON;
6005    bd->mouse.current.mx = ev->root.x;
6006    bd->mouse.current.my = ev->root.y;
6007    if (bd->moving)
6008      {
6009         int x, y, new_x, new_y;
6010         int new_w, new_h;
6011         Eina_List *skiplist = NULL;
6012 #if 0
6013         // FIXME: remove? sync what for when only moving?
6014         if ((ecore_loop_time_get() - bd->client.netwm.sync.time) > 0.5)
6015           bd->client.netwm.sync.wait = 0;
6016         if ((bd->client.netwm.sync.request) &&
6017             (bd->client.netwm.sync.alarm) &&
6018             (bd->client.netwm.sync.wait > 1)) return ECORE_CALLBACK_PASS_ON;
6019 #endif
6020         if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
6021           {
6022              x = bd->mouse.last_down[bd->moveinfo.down.button - 1].x +
6023                (bd->mouse.current.mx - bd->moveinfo.down.mx);
6024              y = bd->mouse.last_down[bd->moveinfo.down.button - 1].y +
6025                (bd->mouse.current.my - bd->moveinfo.down.my);
6026           }
6027         else
6028           {
6029              x = bd->moveinfo.down.x +
6030                (bd->mouse.current.mx - bd->moveinfo.down.mx);
6031              y = bd->moveinfo.down.y +
6032                (bd->mouse.current.my - bd->moveinfo.down.my);
6033           }
6034         new_x = x;
6035         new_y = y;
6036         skiplist = eina_list_append(skiplist, bd);
6037         e_resist_container_border_position(bd->zone->container, skiplist,
6038                                            bd->x, bd->y, bd->w, bd->h,
6039                                            x, y, bd->w, bd->h,
6040                                            &new_x, &new_y, &new_w, &new_h);
6041         eina_list_free(skiplist);
6042         bd->shelf_fix.x = 0;
6043         bd->shelf_fix.y = 0;
6044         bd->shelf_fix.modified = 0;
6045         e_border_move(bd, new_x, new_y);
6046         e_zone_flip_coords_handle(bd->zone, ev->root.x, ev->root.y);
6047      }
6048    else if (bd->resize_mode != RESIZE_NONE)
6049      {
6050         if ((bd->client.netwm.sync.request) &&
6051             (bd->client.netwm.sync.alarm))
6052           {
6053              if ((ecore_loop_time_get() - bd->client.netwm.sync.send_time) > 0.5)
6054                {
6055                   E_Border_Pending_Move_Resize *pnd;
6056
6057                   if (bd->pending_move_resize)
6058                     {
6059                        bd->changes.pos = 1;
6060                        bd->changes.size = 1;
6061                        bd->changed = 1;
6062                        _e_border_client_move_resize_send(bd);
6063                     }
6064                   EINA_LIST_FREE(bd->pending_move_resize, pnd)
6065                     E_FREE(pnd);
6066
6067                   bd->client.netwm.sync.wait = 0;
6068                }
6069              /* sync.wait is incremented when resize_handle sends
6070               * sync-request and decremented by sync-alarm cb. so
6071               * we resize here either on initial resize, timeout or
6072               * when no new resize-request was added by sync-alarm cb.
6073               */
6074              if (!bd->client.netwm.sync.wait)
6075                _e_border_resize_handle(bd);
6076           }
6077         else
6078           _e_border_resize_handle(bd);
6079      }
6080    else
6081      {
6082         if (bd->drag.start)
6083           {
6084              if ((bd->drag.x == -1) && (bd->drag.y == -1))
6085                {
6086                   bd->drag.x = ev->root.x;
6087                   bd->drag.y = ev->root.y;
6088                }
6089              else
6090                {
6091                   int dx, dy;
6092
6093                   dx = bd->drag.x - ev->root.x;
6094                   dy = bd->drag.y - ev->root.y;
6095                   if (((dx * dx) + (dy * dy)) >
6096                       (e_config->drag_resist * e_config->drag_resist))
6097                     {
6098      /* start drag! */
6099                         if (bd->icon_object)
6100                           {
6101                              Evas_Object *o = NULL;
6102                              Evas_Coord x, y, w, h;
6103                              const char *drag_types[] = { "enlightenment/border" };
6104
6105                              e_object_ref(E_OBJECT(bd));
6106                              evas_object_geometry_get(bd->icon_object,
6107                                                       &x, &y, &w, &h);
6108                              drag_border = e_drag_new(bd->zone->container,
6109                                                       bd->x + bd->fx.x + x,
6110                                                       bd->y + bd->fx.y + y,
6111                                                       drag_types, 1, bd, -1,
6112                                                       NULL,
6113                                                       _e_border_cb_drag_finished);
6114                              o = e_border_icon_add(bd, drag_border->evas);
6115                              if (!o)
6116                                {
6117      /* FIXME: fallback icon for drag */
6118                                    o = evas_object_rectangle_add(drag_border->evas);
6119                                    evas_object_color_set(o, 255, 255, 255, 255);
6120                                }
6121                              e_drag_object_set(drag_border, o);
6122
6123                              e_drag_resize(drag_border, w, h);
6124                              e_drag_start(drag_border, bd->drag.x, bd->drag.y);
6125                           }
6126                         bd->drag.start = 0;
6127                     }
6128                }
6129           }
6130         evas_event_feed_mouse_move(bd->bg_evas, ev->x, ev->y, ev->timestamp, NULL);
6131      }
6132    return ECORE_CALLBACK_PASS_ON;
6133 }
6134
6135 static Eina_Bool
6136 _e_border_cb_grab_replay(void *data __UNUSED__,
6137                          int        type,
6138                          void      *event)
6139 {
6140    Ecore_Event_Mouse_Button *ev;
6141
6142    if (type != ECORE_EVENT_MOUSE_BUTTON_DOWN) return ECORE_CALLBACK_DONE;
6143    ev = event;
6144    if ((e_config->pass_click_on) || (e_config->always_click_to_raise) ||
6145        (e_config->always_click_to_focus))
6146      {
6147         E_Border *bd;
6148
6149         bd = e_border_find_by_window(ev->event_window);
6150         if (bd)
6151           {
6152              if (bd->cur_mouse_action)
6153                return ECORE_CALLBACK_DONE;
6154              if (ev->event_window == bd->win)
6155                {
6156                   if (!e_bindings_mouse_down_find(E_BINDING_CONTEXT_BORDER,
6157                                                   E_OBJECT(bd), ev, NULL))
6158                     return ECORE_CALLBACK_PASS_ON;
6159                }
6160           }
6161      }
6162    return ECORE_CALLBACK_DONE;
6163 }
6164
6165 static void
6166 _e_border_cb_drag_finished(E_Drag     *drag,
6167                            int dropped __UNUSED__)
6168 {
6169    E_Border *bd;
6170
6171    bd = drag->data;
6172    e_object_unref(E_OBJECT(bd));
6173    drag_border = NULL;
6174 }
6175
6176 static Eina_Bool
6177 _e_border_post_move_resize_job(void *data)
6178 {
6179    E_Border *bd;
6180
6181    bd = (E_Border *)data;
6182    if ((bd->post_move) && (bd->post_resize))
6183      {
6184         ecore_x_window_move_resize(bd->win,
6185                                    bd->x + bd->fx.x,
6186                                    bd->y + bd->fx.y,
6187                                    bd->w, bd->h);
6188      }
6189    else if (bd->post_move)
6190      {
6191         ecore_x_window_move(bd->win, bd->x + bd->fx.x, bd->y + bd->fx.y);
6192      }
6193    else if (bd->post_resize)
6194      {
6195         ecore_x_window_resize(bd->win, bd->w, bd->h);
6196      }
6197
6198    if (bd->post_show)
6199      {
6200         if (bd->visible)
6201           {
6202              bd->post_job = NULL;
6203              _e_border_show(bd);
6204           }
6205      }
6206    bd->post_show = 0;
6207    bd->post_move = 0;
6208    bd->post_resize = 0;
6209    bd->post_job = NULL;
6210    return ECORE_CALLBACK_CANCEL;
6211 }
6212
6213 static void
6214 _e_border_container_layout_hook(E_Container *con)
6215 {
6216    _e_border_hook_call(E_BORDER_HOOK_CONTAINER_LAYOUT, con);
6217 }
6218
6219 static void
6220 _e_border_eval0(E_Border *bd)
6221 {
6222    int change_urgent = 0;
6223    int rem_change = 0;
6224
6225    if (e_object_is_del(E_OBJECT(bd)))
6226      {
6227         fprintf(stderr, "ERROR: _e_border_eval(%p) with deleted border!\n", bd);
6228         return;
6229      }
6230
6231    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_FETCH, bd);
6232
6233    bd->changes.border = 0;
6234
6235    /* fetch any info queued to be fetched */
6236    if (bd->client.netwm.fetch.state)
6237      {
6238         e_hints_window_state_get(bd);
6239         bd->client.netwm.fetch.state = 0;
6240         rem_change = 1;
6241      }
6242    if (bd->client.icccm.fetch.client_leader)
6243      {
6244         /* TODO: What do to if the client leader isn't mapped yet? */
6245          E_Border *bd_leader = NULL;
6246
6247          bd->client.icccm.client_leader = ecore_x_icccm_client_leader_get(bd->client.win);
6248          if (bd->client.icccm.client_leader)
6249            bd_leader = e_border_find_by_client_window(bd->client.icccm.client_leader);
6250          if (bd->leader)
6251            {
6252               if (bd->leader != bd_leader)
6253                 {
6254                    bd->leader->group = eina_list_remove(bd->leader->group, bd);
6255                    if (bd->leader->modal == bd) bd->leader->modal = NULL;
6256                    bd->leader = NULL;
6257                 }
6258               else
6259                 bd_leader = NULL;
6260            }
6261          /* If this border is the leader of the group, don't register itself */
6262          if ((bd_leader) && (bd_leader != bd))
6263            {
6264               bd_leader->group = eina_list_append(bd_leader->group, bd);
6265               bd->leader = bd_leader;
6266               /* Only set the window modal to the leader it there is no parent */
6267               if ((e_config->modal_windows) && (bd->client.netwm.state.modal) &&
6268                   ((!bd->parent) || (bd->parent->modal != bd)))
6269                 {
6270                    bd->leader->modal = bd;
6271                    if (bd->leader->focused)
6272                      e_border_focus_set(bd, 1, 1);
6273                    else
6274                      {
6275                         Eina_List *l;
6276                         E_Border *child;
6277
6278                         EINA_LIST_FOREACH(bd->leader->group, l, child)
6279                           {
6280                              if ((child != bd) && (child->focused))
6281                                e_border_focus_set(bd, 1, 1);
6282                           }
6283                      }
6284                 }
6285            }
6286          bd->client.icccm.fetch.client_leader = 0;
6287          rem_change = 1;
6288      }
6289    if (bd->client.icccm.fetch.title)
6290      {
6291         if (bd->client.icccm.title) free(bd->client.icccm.title);
6292         bd->client.icccm.title = ecore_x_icccm_title_get(bd->client.win);
6293
6294         bd->client.icccm.fetch.title = 0;
6295         if (bd->bg_object)
6296           edje_object_part_text_set(bd->bg_object, "e.text.title",
6297                                     bd->client.icccm.title);
6298         rem_change = 1;
6299      }
6300    if (bd->client.netwm.fetch.name)
6301      {
6302         if (bd->client.netwm.name) free(bd->client.netwm.name);
6303         ecore_x_netwm_name_get(bd->client.win, &bd->client.netwm.name);
6304
6305         bd->client.netwm.fetch.name = 0;
6306         if (bd->bg_object)
6307           edje_object_part_text_set(bd->bg_object, "e.text.title",
6308                                     bd->client.netwm.name);
6309         rem_change = 1;
6310      }
6311    if (bd->client.icccm.fetch.name_class)
6312      {
6313         int nc_change = 0;
6314         char *pname, *pclass;
6315
6316         pname = bd->client.icccm.name;
6317         pclass = bd->client.icccm.class;
6318         ecore_x_icccm_name_class_get(bd->client.win, &bd->client.icccm.name, &bd->client.icccm.class);
6319         if ((pname) && (bd->client.icccm.name) &&
6320             (pclass) && (bd->client.icccm.class))
6321           {
6322              if (!((!strcmp(bd->client.icccm.name, pname)) &&
6323                    (!strcmp(bd->client.icccm.class, pclass))))
6324                nc_change = 1;
6325           }
6326         else if (((!pname) || (!pclass)) &&
6327                  ((bd->client.icccm.name) || (bd->client.icccm.class)))
6328           nc_change = 1;
6329         else if (((bd->client.icccm.name) || (bd->client.icccm.class)) &&
6330                  ((!pname) || (!pclass)))
6331           nc_change = 1;
6332         if (pname) free(pname);
6333         if (pclass) free(pclass);
6334         if (nc_change)
6335           bd->changes.icon = 1;
6336         bd->client.icccm.fetch.name_class = 0;
6337         rem_change = 1;
6338      }
6339    if (bd->client.icccm.fetch.state)
6340      {
6341         bd->client.icccm.state = ecore_x_icccm_state_get(bd->client.win);
6342         bd->client.icccm.fetch.state = 0;
6343         rem_change = 1;
6344      }
6345    if (bd->client.e.fetch.state)
6346      {
6347         e_hints_window_e_state_get(bd);
6348         bd->client.e.fetch.state = 0;
6349         rem_change = 1;
6350      }
6351    if (bd->client.netwm.fetch.type)
6352      {
6353         e_hints_window_type_get(bd);
6354         if ((!bd->lock_border) || (!bd->client.border.name))
6355           bd->client.border.changed = 1;
6356
6357         if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
6358           {
6359              if (!bd->client.netwm.state.skip_pager)
6360                {
6361                   bd->client.netwm.state.skip_pager = 1;
6362                   bd->client.netwm.update.state = 1;
6363                }
6364              if (!bd->client.netwm.state.skip_taskbar)
6365                {
6366                   bd->client.netwm.state.skip_taskbar = 1;
6367                   bd->client.netwm.update.state = 1;
6368                }
6369           }
6370         bd->client.netwm.fetch.type = 0;
6371      }
6372    if (bd->client.icccm.fetch.machine)
6373      {
6374         if (bd->client.icccm.machine) free(bd->client.icccm.machine);
6375         bd->client.icccm.machine = ecore_x_icccm_client_machine_get(bd->client.win);
6376         if ((bd->client.icccm.client_leader) &&
6377             (!bd->client.icccm.machine))
6378           ecore_x_icccm_client_machine_get(bd->client.icccm.client_leader);
6379         bd->client.icccm.fetch.machine = 0;
6380         rem_change = 1;
6381      }
6382    if (bd->client.icccm.fetch.command)
6383      {
6384         if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
6385           {
6386              int i;
6387
6388              for (i = 0; i < bd->client.icccm.command.argc; i++)
6389                free(bd->client.icccm.command.argv[i]);
6390              free(bd->client.icccm.command.argv);
6391           }
6392         bd->client.icccm.command.argc = 0;
6393         bd->client.icccm.command.argv = NULL;
6394         ecore_x_icccm_command_get(bd->client.win,
6395                                   &(bd->client.icccm.command.argc),
6396                                   &(bd->client.icccm.command.argv));
6397         if ((bd->client.icccm.client_leader) &&
6398             (!bd->client.icccm.command.argv))
6399           ecore_x_icccm_command_get(bd->client.icccm.client_leader,
6400                                     &(bd->client.icccm.command.argc),
6401                                     &(bd->client.icccm.command.argv));
6402         bd->client.icccm.fetch.command = 0;
6403         rem_change = 1;
6404      }
6405    if (bd->client.icccm.fetch.hints)
6406      {
6407         Eina_Bool accepts_focus, is_urgent;
6408
6409         accepts_focus = EINA_TRUE;
6410         is_urgent = EINA_FALSE;
6411         bd->client.icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
6412         if (ecore_x_icccm_hints_get(bd->client.win,
6413                                     &accepts_focus,
6414                                     &bd->client.icccm.initial_state,
6415                                     &bd->client.icccm.icon_pixmap,
6416                                     &bd->client.icccm.icon_mask,
6417                                     &bd->client.icccm.icon_window,
6418                                     &bd->client.icccm.window_group,
6419                                     &is_urgent))
6420           {
6421              bd->client.icccm.accepts_focus = accepts_focus;
6422              if (bd->client.icccm.urgent != is_urgent)
6423                change_urgent = 1;
6424              bd->client.icccm.urgent = is_urgent;
6425
6426              /* If this is a new window, set the state as requested. */
6427              if ((bd->new_client) &&
6428                  (bd->client.icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
6429                {
6430                   e_border_iconify(bd);
6431                   e_border_hide(bd, 1);
6432                }
6433           }
6434         bd->client.icccm.fetch.hints = 0;
6435         rem_change = 1;
6436      }
6437    if (bd->client.icccm.fetch.size_pos_hints)
6438      {
6439         Eina_Bool request_pos;
6440
6441         request_pos = EINA_FALSE;
6442         if (ecore_x_icccm_size_pos_hints_get(bd->client.win,
6443                                              &request_pos,
6444                                              &bd->client.icccm.gravity,
6445                                              &bd->client.icccm.min_w,
6446                                              &bd->client.icccm.min_h,
6447                                              &bd->client.icccm.max_w,
6448                                              &bd->client.icccm.max_h,
6449                                              &bd->client.icccm.base_w,
6450                                              &bd->client.icccm.base_h,
6451                                              &bd->client.icccm.step_w,
6452                                              &bd->client.icccm.step_h,
6453                                              &bd->client.icccm.min_aspect,
6454                                              &bd->client.icccm.max_aspect))
6455           {
6456              bd->client.icccm.request_pos = request_pos;
6457           }
6458         else
6459           {
6460           }
6461         if (bd->client.icccm.min_w > 32767) bd->client.icccm.min_w = 32767;
6462         if (bd->client.icccm.min_h > 32767) bd->client.icccm.min_h = 32767;
6463         if (bd->client.icccm.max_w > 32767) bd->client.icccm.max_w = 32767;
6464         if (bd->client.icccm.max_h > 32767) bd->client.icccm.max_h = 32767;
6465         if (bd->client.icccm.base_w > 32767) bd->client.icccm.base_w = 32767;
6466         if (bd->client.icccm.base_h > 32767) bd->client.icccm.base_h = 32767;
6467 //      if (bd->client.icccm.step_w < 1) bd->client.icccm.step_w = 1;
6468 //      if (bd->client.icccm.step_h < 1) bd->client.icccm.step_h = 1;
6469
6470         bd->client.icccm.fetch.size_pos_hints = 0;
6471         rem_change = 1;
6472      }
6473    if (bd->client.icccm.fetch.protocol)
6474      {
6475         int i, num;
6476         Ecore_X_WM_Protocol *proto;
6477
6478         proto = ecore_x_window_prop_protocol_list_get(bd->client.win, &num);
6479         if (proto)
6480           {
6481              for (i = 0; i < num; i++)
6482                {
6483                   if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
6484                     bd->client.icccm.delete_request = 1;
6485                   else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
6486                     bd->client.icccm.take_focus = 1;
6487                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
6488                     bd->client.netwm.ping = 1;
6489                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
6490                     {
6491                        bd->client.netwm.sync.request = 1;
6492                        if (!ecore_x_netwm_sync_counter_get(bd->client.win,
6493                                                            &bd->client.netwm.sync.counter))
6494                          bd->client.netwm.sync.request = 0;
6495                     }
6496                }
6497              free(proto);
6498           }
6499         if (bd->client.netwm.ping)
6500           e_border_ping(bd);
6501         else
6502           {
6503              if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
6504              bd->ping_poller = NULL;
6505           }
6506         bd->client.icccm.fetch.protocol = 0;
6507      }
6508    if (bd->client.icccm.fetch.transient_for)
6509      {
6510         /* TODO: What do to if the transient for isn't mapped yet? */
6511          E_Border *bd_parent = NULL;
6512
6513          bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win);
6514          if (bd->client.icccm.transient_for)
6515            bd_parent = e_border_find_by_client_window(bd->client.icccm.transient_for);
6516          /* If we already have a parent, remove it */
6517          if (bd->parent)
6518            {
6519               if (bd_parent != bd->parent)
6520                 {
6521                    bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
6522                    if (bd->parent->modal == bd) bd->parent->modal = NULL;
6523                    bd->parent = NULL;
6524                 }
6525               else
6526                 bd_parent = NULL;
6527            }
6528          if ((bd_parent) && (bd_parent != bd))
6529            {
6530               bd_parent->transients = eina_list_append(bd_parent->transients, bd);
6531               bd->parent = bd_parent;
6532               e_border_layer_set(bd, bd->parent->layer);
6533               if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
6534                 bd->parent->modal = bd;
6535
6536               if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
6537                   (bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
6538                 bd->take_focus = 1;
6539            }
6540          bd->client.icccm.fetch.transient_for = 0;
6541          rem_change = 1;
6542      }
6543    if (bd->client.icccm.fetch.window_role)
6544      {
6545         if (bd->client.icccm.window_role) free(bd->client.icccm.window_role);
6546         bd->client.icccm.window_role = ecore_x_icccm_window_role_get(bd->client.win);
6547         bd->client.icccm.fetch.window_role = 0;
6548         rem_change = 1;
6549      }
6550    if (bd->client.icccm.fetch.icon_name)
6551      {
6552         if (bd->client.icccm.icon_name) free(bd->client.icccm.icon_name);
6553         bd->client.icccm.icon_name = ecore_x_icccm_icon_name_get(bd->client.win);
6554         bd->client.icccm.fetch.icon_name = 0;
6555         rem_change = 1;
6556      }
6557    if (bd->client.netwm.fetch.icon_name)
6558      {
6559         if (bd->client.netwm.icon_name) free(bd->client.netwm.icon_name);
6560         ecore_x_netwm_icon_name_get(bd->client.win, &bd->client.netwm.icon_name);
6561         bd->client.netwm.fetch.icon_name = 0;
6562         rem_change = 1;
6563      }
6564    if (bd->client.netwm.fetch.icon)
6565      {
6566         if (bd->client.netwm.icons)
6567           {
6568              int i;
6569
6570              for (i = 0; i < bd->client.netwm.num_icons; i++)
6571                free(bd->client.netwm.icons[i].data);
6572              free(bd->client.netwm.icons);
6573           }
6574         if (!ecore_x_netwm_icons_get(bd->client.win,
6575                                      &bd->client.netwm.icons, &bd->client.netwm.num_icons))
6576           {
6577              bd->client.netwm.icons = NULL;
6578              bd->client.netwm.num_icons = 0;
6579           }
6580         else
6581           bd->changes.icon = 1;
6582         bd->client.netwm.fetch.icon = 0;
6583      }
6584    if (bd->client.netwm.fetch.user_time)
6585      {
6586         ecore_x_netwm_user_time_get(bd->client.win, &bd->client.netwm.user_time);
6587         bd->client.netwm.fetch.user_time = 0;
6588      }
6589    if (bd->client.netwm.fetch.strut)
6590      {
6591         if (!ecore_x_netwm_strut_partial_get(bd->client.win,
6592                                              &bd->client.netwm.strut.left,
6593                                              &bd->client.netwm.strut.right,
6594                                              &bd->client.netwm.strut.top,
6595                                              &bd->client.netwm.strut.bottom,
6596                                              &bd->client.netwm.strut.left_start_y,
6597                                              &bd->client.netwm.strut.left_end_y,
6598                                              &bd->client.netwm.strut.right_start_y,
6599                                              &bd->client.netwm.strut.right_end_y,
6600                                              &bd->client.netwm.strut.top_start_x,
6601                                              &bd->client.netwm.strut.top_end_x,
6602                                              &bd->client.netwm.strut.bottom_start_x,
6603                                              &bd->client.netwm.strut.bottom_end_x))
6604           {
6605              ecore_x_netwm_strut_get(bd->client.win,
6606                                      &bd->client.netwm.strut.left, &bd->client.netwm.strut.right,
6607                                      &bd->client.netwm.strut.top, &bd->client.netwm.strut.bottom);
6608
6609              bd->client.netwm.strut.left_start_y = 0;
6610              bd->client.netwm.strut.left_end_y = 0;
6611              bd->client.netwm.strut.right_start_y = 0;
6612              bd->client.netwm.strut.right_end_y = 0;
6613              bd->client.netwm.strut.top_start_x = 0;
6614              bd->client.netwm.strut.top_end_x = 0;
6615              bd->client.netwm.strut.bottom_start_x = 0;
6616              bd->client.netwm.strut.bottom_end_x = 0;
6617           }
6618         bd->client.netwm.fetch.strut = 0;
6619      }
6620    if (bd->client.qtopia.fetch.soft_menu)
6621      {
6622         e_hints_window_qtopia_soft_menu_get(bd);
6623         bd->client.qtopia.fetch.soft_menu = 0;
6624         rem_change = 1;
6625      }
6626    if (bd->client.qtopia.fetch.soft_menus)
6627      {
6628         e_hints_window_qtopia_soft_menus_get(bd);
6629         bd->client.qtopia.fetch.soft_menus = 0;
6630         rem_change = 1;
6631      }
6632    if (bd->client.vkbd.fetch.state)
6633      {
6634         e_hints_window_virtual_keyboard_state_get(bd);
6635         bd->client.vkbd.fetch.state = 0;
6636         rem_change = 1;
6637      }
6638    if (bd->client.vkbd.fetch.vkbd)
6639      {
6640         e_hints_window_virtual_keyboard_get(bd);
6641         bd->client.vkbd.fetch.vkbd = 0;
6642         rem_change = 1;
6643      }
6644    if (bd->client.illume.conformant.fetch.conformant)
6645      {
6646         bd->client.illume.conformant.conformant =
6647           ecore_x_e_illume_conformant_get(bd->client.win);
6648         bd->client.illume.conformant.fetch.conformant = 0;
6649      }
6650    if (bd->client.illume.quickpanel.fetch.state)
6651      {
6652         bd->client.illume.quickpanel.state =
6653           ecore_x_e_illume_quickpanel_state_get(bd->client.win);
6654         bd->client.illume.quickpanel.fetch.state = 0;
6655      }
6656    if (bd->client.illume.quickpanel.fetch.quickpanel)
6657      {
6658         bd->client.illume.quickpanel.quickpanel =
6659           ecore_x_e_illume_quickpanel_get(bd->client.win);
6660         bd->client.illume.quickpanel.fetch.quickpanel = 0;
6661      }
6662    if (bd->client.illume.quickpanel.fetch.priority.major)
6663      {
6664         bd->client.illume.quickpanel.priority.major =
6665           ecore_x_e_illume_quickpanel_priority_major_get(bd->client.win);
6666         bd->client.illume.quickpanel.fetch.priority.major = 0;
6667      }
6668    if (bd->client.illume.quickpanel.fetch.priority.minor)
6669      {
6670         bd->client.illume.quickpanel.priority.minor =
6671           ecore_x_e_illume_quickpanel_priority_minor_get(bd->client.win);
6672         bd->client.illume.quickpanel.fetch.priority.minor = 0;
6673      }
6674    if (bd->client.illume.quickpanel.fetch.zone)
6675      {
6676         bd->client.illume.quickpanel.zone =
6677           ecore_x_e_illume_quickpanel_zone_get(bd->client.win);
6678         bd->client.illume.quickpanel.fetch.zone = 0;
6679      }
6680    if (bd->client.illume.drag.fetch.drag)
6681      {
6682         bd->client.illume.drag.drag =
6683           ecore_x_e_illume_drag_get(bd->client.win);
6684         bd->client.illume.drag.fetch.drag = 0;
6685      }
6686    if (bd->client.illume.drag.fetch.locked)
6687      {
6688         bd->client.illume.drag.locked =
6689           ecore_x_e_illume_drag_locked_get(bd->client.win);
6690         bd->client.illume.drag.fetch.locked = 0;
6691      }
6692    if (bd->changes.shape)
6693      {
6694         Ecore_X_Rectangle *rects;
6695         int num;
6696
6697         bd->changes.shape = 0;
6698         rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
6699         if (rects)
6700           {
6701              int cw = 0, ch = 0;
6702
6703              /* This doesn't fix the race, but makes it smaller. we detect
6704               * this and if cw and ch != client w/h then mark this as needing
6705               * a shape change again to fixup next event loop.
6706               */
6707              ecore_x_window_size_get(bd->client.win, &cw, &ch);
6708              if ((cw != bd->client.w) || (ch != bd->client.h))
6709                bd->changes.shape = 1;
6710              if ((num == 1) &&
6711                  (rects[0].x == 0) &&
6712                  (rects[0].y == 0) &&
6713                  ((int)rects[0].width == cw) &&
6714                  ((int)rects[0].height == ch))
6715                {
6716                   if (bd->client.shaped)
6717                     {
6718                        bd->client.shaped = 0;
6719                        if (!bd->bordername)
6720                          bd->client.border.changed = 1;
6721                     }
6722                }
6723              else
6724                {
6725                   if (!bd->client.shaped)
6726                     {
6727                        bd->client.shaped = 1;
6728                        if (!bd->bordername)
6729                          bd->client.border.changed = 1;
6730                     }
6731                }
6732              free(rects);
6733           }
6734         else
6735           {
6736              // FIXME: no rects i think can mean... totally empty window
6737              bd->client.shaped = 0;
6738              if (!bd->bordername)
6739                bd->client.border.changed = 1;
6740           }
6741         bd->need_shape_merge = 1;
6742      }
6743    if (bd->changes.shape_input)
6744      {
6745         Ecore_X_Rectangle *rects;
6746         int num;
6747
6748         bd->changes.shape_input = 0;
6749         rects = ecore_x_window_shape_input_rectangles_get(bd->client.win, &num);
6750         if (rects)
6751           {
6752              int cw = 0, ch = 0;
6753
6754              /* This doesn't fix the race, but makes it smaller. we detect
6755               * this and if cw and ch != client w/h then mark this as needing
6756               * a shape change again to fixup next event loop.
6757               */
6758              ecore_x_window_size_get(bd->client.win, &cw, &ch);
6759              if ((cw != bd->client.w) || (ch != bd->client.h))
6760                 bd->changes.shape_input = 1;
6761              if ((num == 1) &&
6762                  (rects[0].x == 0) &&
6763                  (rects[0].y == 0) &&
6764                  ((int)rects[0].width == cw) &&
6765                  ((int)rects[0].height == ch))
6766                {
6767                   if (bd->shaped_input)
6768                     {
6769                        bd->shaped_input = 0;
6770                        if (!bd->bordername)
6771                           bd->client.border.changed = 1;
6772                     }
6773                }
6774              else
6775                {
6776                   if (!bd->shaped_input)
6777                     {
6778                        bd->shaped_input = 1;
6779                        if (!bd->bordername)
6780                           bd->client.border.changed = 1;
6781                     }
6782                }
6783              free(rects);
6784           }
6785         else
6786           {
6787              bd->shaped_input = 1;
6788              if (!bd->bordername)
6789                 bd->client.border.changed = 1;
6790           }
6791         bd->need_shape_merge = 1;
6792      }
6793    if (bd->client.mwm.fetch.hints)
6794      {
6795         int pb;
6796
6797         bd->client.mwm.exists =
6798           ecore_x_mwm_hints_get(bd->client.win,
6799                                 &bd->client.mwm.func,
6800                                 &bd->client.mwm.decor,
6801                                 &bd->client.mwm.input);
6802         pb = bd->client.mwm.borderless;
6803         bd->client.mwm.borderless = 0;
6804         if (bd->client.mwm.exists)
6805           {
6806              if ((!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
6807                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
6808                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
6809                bd->client.mwm.borderless = 1;
6810           }
6811         if (bd->client.mwm.borderless != pb)
6812           {
6813              if ((!bd->lock_border) || (!bd->client.border.name))
6814                bd->client.border.changed = 1;
6815           }
6816         bd->client.mwm.fetch.hints = 0;
6817         rem_change = 1;
6818      }
6819    if (bd->client.netwm.update.state)
6820      {
6821         e_hints_window_state_set(bd);
6822         /* Some stats might change the border, like modal */
6823         if (((!bd->lock_border) || (!bd->client.border.name)) &&
6824             (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
6825           {
6826              bd->client.border.changed = 1;
6827           }
6828         if (bd->parent)
6829           {
6830              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
6831                {
6832                   bd->parent->modal = bd;
6833                   if (bd->parent->focused)
6834                     e_border_focus_set(bd, 1, 1);
6835                }
6836           }
6837         else if (bd->leader)
6838           {
6839              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
6840                {
6841                   bd->leader->modal = bd;
6842                   if (bd->leader->focused)
6843                     e_border_focus_set(bd, 1, 1);
6844                   else
6845                     {
6846                        Eina_List *l;
6847                        E_Border *child;
6848
6849                        EINA_LIST_FOREACH(bd->leader->group, l, child)
6850                          {
6851                             if ((child != bd) && (child->focused))
6852                               e_border_focus_set(bd, 1, 1);
6853                          }
6854                     }
6855                }
6856           }
6857         bd->client.netwm.update.state = 0;
6858      }
6859
6860    if (bd->new_client)
6861      {
6862         E_Event_Border_Add *ev;
6863
6864         ev = E_NEW(E_Event_Border_Add, 1);
6865         ev->border = bd;
6866         e_object_ref(E_OBJECT(bd));
6867 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_add_event");
6868         ecore_event_add(E_EVENT_BORDER_ADD, ev, _e_border_event_border_add_free, NULL);
6869
6870         if ((!bd->lock_border) || (!bd->client.border.name))
6871           bd->client.border.changed = 1;
6872      }
6873
6874    /* PRE_POST_FETCH calls e_remember apply for new client */
6875    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd);
6876    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd);
6877    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd);
6878
6879    if (bd->need_reparent)
6880      {
6881         if (!bd->internal)
6882           ecore_x_window_save_set_add(bd->client.win);
6883         ecore_x_window_reparent(bd->client.win, bd->client.shell_win, 0, 0);
6884         if (bd->visible)
6885           {
6886              if ((bd->new_client) && (bd->internal) &&
6887                  (bd->internal_ecore_evas))
6888                ecore_evas_show(bd->internal_ecore_evas);
6889              ecore_x_window_show(bd->client.win);
6890           }
6891         bd->need_reparent = 0;
6892      }
6893
6894    if ((bd->client.border.changed) && (!bd->shaded) &&
6895        (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
6896      {
6897         const char *bordername;
6898
6899         if (bd->fullscreen)
6900           bordername = "borderless";
6901         else if (bd->bordername)
6902           bordername = bd->bordername;
6903         else if ((bd->client.mwm.borderless) || (bd->borderless))
6904           bordername = "borderless";
6905         else if (((bd->client.icccm.transient_for != 0) ||
6906                   (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)) &&
6907                  (bd->client.icccm.min_w == bd->client.icccm.max_w) &&
6908                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
6909           bordername = "noresize_dialog";
6910         else if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
6911                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
6912           bordername = "noresize";
6913         else if (bd->client.shaped)
6914           bordername = "shaped";
6915         else if ((!bd->client.icccm.accepts_focus) &&
6916                  (!bd->client.icccm.take_focus))
6917           bordername = "nofocus";
6918         else if (bd->client.icccm.urgent)
6919           bordername = "urgent";
6920         else if ((bd->client.icccm.transient_for != 0) ||
6921                  (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
6922           bordername = "dialog";
6923         else if (bd->client.netwm.state.modal)
6924           bordername = "modal";
6925         else if ((bd->client.netwm.state.skip_taskbar) ||
6926                  (bd->client.netwm.state.skip_pager))
6927           bordername = "skipped";
6928         else
6929           bordername = e_config->theme_default_border_style;
6930         if (!bordername) bordername = "default";
6931
6932         if ((!bd->client.border.name) || (strcmp(bd->client.border.name, bordername)))
6933           {
6934              Evas_Object *o;
6935              char buf[PATH_MAX];
6936              Evas_Coord cx, cy, cw, ch;
6937              int l, r, t, b, ok;
6938
6939              bd->changes.border = 1;
6940              if (bd->client.border.name)
6941                eina_stringshare_del(bd->client.border.name);
6942              bd->client.border.name = eina_stringshare_add(bordername);
6943
6944              if (bd->bg_object)
6945                {
6946                   bd->w -= (bd->client_inset.l + bd->client_inset.r);
6947                   bd->h -= (bd->client_inset.t + bd->client_inset.b);
6948                   bd->client_inset.l = 0;
6949                   bd->client_inset.r = 0;
6950                   bd->client_inset.t = 0;
6951                   bd->client_inset.b = 0;
6952                   bd->changes.size = 1;
6953                   evas_object_del(bd->bg_object);
6954                }
6955              o = edje_object_add(bd->bg_evas);
6956              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border",
6957                       bd->client.border.name);
6958              ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
6959              if ((!ok) && (strcmp(bd->client.border.name, "borderless")))
6960                {
6961                   ok = e_theme_edje_object_set(o, "base/theme/borders",
6962                                                "e/widgets/border/default/border");
6963                   if (ok)
6964                     {
6965                        /* Reset default border style to default */
6966                        if (e_config->theme_default_border_style)
6967                          eina_stringshare_del(e_config->theme_default_border_style);
6968                        e_config->theme_default_border_style = eina_stringshare_add("default");
6969                        e_config_save_queue();
6970                     }
6971                }
6972
6973              bd->shaped = 0;
6974              if (ok)
6975                {
6976                   const char *shape_option, *argb_option;
6977                   int use_argb = 0;
6978
6979                   bd->bg_object = o;
6980
6981                   if (!bd->client.argb)
6982                     {
6983                        argb_option = edje_object_data_get(o, "argb");
6984                        if ((argb_option) && (!strcmp(argb_option, "1")))
6985                          use_argb = 1;
6986
6987                        if (use_argb != bd->argb)
6988                          _e_border_frame_replace(bd, use_argb);
6989
6990                        o = bd->bg_object;
6991                     }
6992
6993                   if (!bd->argb)
6994                     {
6995                        shape_option = edje_object_data_get(o, "shaped");
6996                        if ((shape_option) && (!strcmp(shape_option, "1")))
6997                          bd->shaped = 1;
6998                     }
6999
7000                   if (bd->client.netwm.name)
7001                     edje_object_part_text_set(o, "e.text.title",
7002                                               bd->client.netwm.name);
7003                   else if (bd->client.icccm.title)
7004                     edje_object_part_text_set(o, "e.text.title",
7005                                               bd->client.icccm.title);
7006                   evas_object_resize(o, 1000, 1000);
7007                   edje_object_calc_force(o);
7008                   edje_object_part_geometry_get(o, "e.swallow.client",
7009                                                 &cx, &cy, &cw, &ch);
7010                   l = cx;
7011                   r = 1000 - (cx + cw);
7012                   t = cy;
7013                   b = 1000 - (cy + ch);
7014                }
7015              else
7016                {
7017                   evas_object_del(o);
7018                   bd->bg_object = NULL;
7019                   l = 0;
7020                   r = 0;
7021                   t = 0;
7022                   b = 0;
7023                }
7024              bd->client_inset.l = l;
7025              bd->client_inset.r = r;
7026              bd->client_inset.t = t;
7027              bd->client_inset.b = b;
7028              ecore_x_netwm_frame_size_set(bd->client.win, l, r, t, b);
7029              ecore_x_e_frame_size_set(bd->client.win, l, r, t, b);
7030              bd->w += (bd->client_inset.l + bd->client_inset.r);
7031              bd->h += (bd->client_inset.t + bd->client_inset.b);
7032              ecore_evas_shaped_set(bd->bg_ecore_evas, bd->shaped);
7033              bd->changes.size = 1;
7034              ecore_x_window_move(bd->client.shell_win, l, t);
7035
7036              if (bd->maximized != E_MAXIMIZE_NONE)
7037                {
7038                   int x1, y1, x2, y2;
7039                   int w, h, pw, ph;
7040                   int zx, zy, zw, zh;
7041                   E_Maximize maximized = bd->maximized;
7042
7043                   /* to force possible resizes */
7044                   bd->maximized = E_MAXIMIZE_NONE;
7045
7046                   zx = zy = zw = zh = 0;
7047
7048                   switch (maximized & E_MAXIMIZE_TYPE)
7049                     {
7050                      case E_MAXIMIZE_FULLSCREEN:
7051                         w = bd->zone->w;
7052                         h = bd->zone->h;
7053
7054                         if (bd->bg_object)
7055                           {
7056                              Evas_Coord cx, cy, cw, ch;
7057
7058                              edje_object_signal_emit(bd->bg_object, "e,action,maximize,fullscreen", "e");
7059
7060                              evas_object_resize(bd->bg_object, w, h);
7061                              edje_object_calc_force(bd->bg_object);
7062                              edje_object_part_geometry_get(bd->bg_object, "e.swallow.client", &cx, &cy, &cw, &ch);
7063                              bd->client_inset.l = cx;
7064                              bd->client_inset.r = w - (cx + cw);
7065                              bd->client_inset.t = cy;
7066                              bd->client_inset.b = h - (cy + ch);
7067                              ecore_x_netwm_frame_size_set(bd->client.win,
7068                                                           bd->client_inset.l, bd->client_inset.r,
7069                                                           bd->client_inset.t, bd->client_inset.b);
7070                              ecore_x_e_frame_size_set(bd->client.win,
7071                                                       bd->client_inset.l, bd->client_inset.r,
7072                                                       bd->client_inset.t, bd->client_inset.b);
7073                           }
7074                         e_border_resize_limit(bd, &w, &h);
7075                         /* center x-direction */
7076                         x1 = bd->zone->x + (bd->zone->w - w) / 2;
7077                         /* center y-direction */
7078                         y1 = bd->zone->y + (bd->zone->h - h) / 2;
7079
7080                         if ((maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)
7081                           _e_border_move_resize_internal(bd, x1, y1, w, h, 0, 1);
7082                         else if ((maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
7083                           _e_border_move_resize_internal(bd, bd->x, y1, bd->w, h, 0, 1);
7084
7085                         else if ((maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
7086                           _e_border_move_resize_internal(bd, x1, bd->y, w, bd->h, 0, 1);
7087                         break;
7088
7089                      case E_MAXIMIZE_SMART:
7090                      case E_MAXIMIZE_EXPAND:
7091                         if (bd->zone)
7092                           e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
7093
7094                         if (bd->w < zw)
7095                           w = bd->w;
7096                         else
7097                           w = zw;
7098
7099                         if (bd->h < zh)
7100                           h = bd->h;
7101                         else
7102                           h = zh;
7103
7104                         if (bd->x < zx) // window left not useful coordinates
7105                           x1 = zx;
7106                         else if (bd->x + bd->w > zx + zw) // window right not useful coordinates
7107                           x1 = zx + zw - bd->w;
7108                         else // window normal position
7109                           x1 = bd->x;
7110
7111                         if (bd->y < zy) // window top not useful coordinates
7112                           y1 = zy;
7113                         else if (bd->y + bd->h > zy + zh) // window bottom not useful coordinates
7114                           y1 = zy + zh - bd->h;
7115                         else // window normal position
7116                           y1 = bd->y;
7117
7118                         if ((maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)
7119                           _e_border_move_resize_internal(bd, zx, zy, zw, zh, 0, 1);
7120                         else if ((maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
7121                           _e_border_move_resize_internal(bd, x1, zy, w, zh, 0, 1);
7122                         else if ((maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
7123                           _e_border_move_resize_internal(bd, zx, y1, zw, h, 0, 1);
7124                         break;
7125
7126                      case E_MAXIMIZE_FILL:
7127                         x1 = bd->zone->x;
7128                         y1 = bd->zone->y;
7129                         x2 = bd->zone->x + bd->zone->w;
7130                         y2 = bd->zone->y + bd->zone->h;
7131
7132                         /* walk through all shelves */
7133                         e_maximize_border_shelf_fill(bd, &x1, &y1, &x2, &y2, maximized);
7134
7135                         /* walk through all windows */
7136                         e_maximize_border_border_fill(bd, &x1, &y1, &x2, &y2, maximized);
7137
7138                         w = x2 - x1;
7139                         h = y2 - y1;
7140                         pw = w;
7141                         ph = h;
7142                         e_border_resize_limit(bd, &w, &h);
7143                         /* center x-direction */
7144                         x1 = x1 + (pw - w) / 2;
7145                         /* center y-direction */
7146                         y1 = y1 + (ph - h) / 2;
7147                         if ((maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)
7148                           _e_border_move_resize_internal(bd, x1, y1, w, h, 0, 1);
7149                         else if ((maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
7150                           _e_border_move_resize_internal(bd, bd->x, y1, bd->w, h, 0, 1);
7151                         else if ((maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
7152                           _e_border_move_resize_internal(bd, x1, bd->y, w, bd->h, 0, 1);
7153                         break;
7154                     }
7155                   /* restore maximized state */
7156                   bd->maximized = maximized;
7157
7158                   e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
7159                                                bd->maximized & E_MAXIMIZE_VERTICAL);
7160                }
7161              if (bd->bg_object)
7162                {
7163                   edje_object_signal_callback_add(bd->bg_object, "*", "*",
7164                                                   _e_border_cb_signal_bind, bd);
7165                   if (bd->focused)
7166                     {
7167                        edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
7168                        if (bd->icon_object)
7169                          edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
7170                     }
7171                   if (bd->shaded)
7172                     edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
7173                   if (bd->sticky)
7174                     edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
7175                   if (bd->hung)
7176                     edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
7177                   if (bd->client.icccm.urgent)
7178                     edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
7179 // FIXME: in eval -do differently
7180 //           edje_object_message_signal_process(bd->bg_object);
7181 //           e_border_frame_recalc(bd);
7182
7183                   evas_object_move(bd->bg_object, 0, 0);
7184                   evas_object_resize(bd->bg_object, bd->w, bd->h);
7185                   evas_object_show(bd->bg_object);
7186                }
7187           }
7188         bd->client.border.changed = 0;
7189
7190         if (bd->icon_object)
7191           {
7192              if (bd->bg_object)
7193                {
7194                   evas_object_show(bd->icon_object);
7195                   edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
7196                }
7197              else
7198                evas_object_hide(bd->icon_object);
7199           }
7200      }
7201
7202    if (rem_change) e_remember_update(bd);
7203
7204    if (change_urgent)
7205      {
7206         E_Event_Border_Urgent_Change *ev;
7207
7208         if (bd->client.icccm.urgent)
7209           edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
7210         else
7211           edje_object_signal_emit(bd->bg_object, "e,state,not_urgent", "e");
7212
7213         ev = E_NEW(E_Event_Border_Urgent_Change, 1);
7214         ev->border = bd;
7215         e_object_ref(E_OBJECT(bd));
7216         ecore_event_add(E_EVENT_BORDER_URGENT_CHANGE, ev,
7217                         _e_border_event_border_urgent_change_free, NULL);
7218      }
7219
7220    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, bd);
7221 }
7222
7223 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
7224 static void
7225 _e_border_latest_stacked_focus (E_Border* bd)
7226 {
7227    Eina_List *l = NULL;
7228    E_Border *temp_bd;
7229    int root_w, root_h;
7230
7231    root_w = bd->zone->w;
7232    root_h = bd->zone->h;
7233
7234    E_Border_List *bl;
7235    bl = e_container_border_list_last(bd->zone->container);
7236    while ((temp_bd = e_container_border_list_prev(bl)))
7237      {
7238         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
7239         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
7240
7241         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
7242            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
7243            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
7244            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
7245            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
7246            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
7247            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
7248           {
7249              if (bd == temp_bd)
7250                {
7251                   continue;
7252                }
7253              else
7254                {
7255                   /* this border is the top of the latest stack */
7256                   e_border_focus_set (temp_bd, 1, 1);
7257                }
7258              break;
7259           }
7260
7261      }
7262    e_container_border_list_free(bl);
7263 }
7264
7265 static void
7266 _e_border_check_stack (E_Border *bd)
7267 {
7268    Eina_List* l = NULL;
7269    E_Border* temp_bd = NULL;;
7270    E_Border* top_bd = NULL;
7271    int passed_focus = 0;
7272    int passed = 0;
7273    int root_w = bd->zone->w;
7274    int root_h = bd->zone->h;
7275
7276    E_Border_List *bl;
7277    bl = e_container_border_list_last(bd->zone->container);
7278    while ((temp_bd = e_container_border_list_prev(bl)))
7279      {
7280         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
7281         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
7282
7283         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
7284            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
7285            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
7286            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
7287            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
7288            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
7289            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
7290           {
7291              if (bd == temp_bd)
7292                {
7293                   if (!passed)
7294                     {
7295                        e_border_focus_set_with_pointer(bd);
7296                        break;
7297                     }
7298                   else
7299                     {
7300                        if (!passed_focus)
7301                          {
7302                             e_border_focus_set_with_pointer(top_bd);
7303                          }
7304                        break;
7305                     }
7306                }
7307              else
7308                {
7309                   if (!passed)
7310                     {
7311                        if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
7312                          {
7313                             if (!bd->lock_focus_out)
7314                               {
7315                                  e_border_focus_latest_set(bd);
7316                               }
7317                          }
7318                     }
7319                }
7320
7321              if (!passed)
7322                {
7323                   passed = 1;
7324                   top_bd = temp_bd;
7325                }
7326
7327              if (temp_bd == focused)
7328                {
7329                   passed_focus = 1;
7330                }
7331           }
7332      }
7333    e_container_border_list_free(bl);
7334 }
7335
7336 static void
7337 _e_border_focus_top_stack_set (E_Border* bd)
7338 {
7339    Eina_List *l = NULL;
7340    E_Border *temp_bd;
7341    int root_w, root_h;
7342
7343    root_w = bd->zone->w;
7344    root_h = bd->zone->h;
7345
7346    E_Border_List *bl;
7347    bl = e_container_border_list_last(bd->zone->container);
7348    while ((temp_bd = e_container_border_list_prev(bl)))
7349      {
7350         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
7351         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
7352
7353         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
7354            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
7355            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
7356            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
7357            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
7358            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
7359            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
7360           {
7361              if (!temp_bd->focused)
7362                {
7363                   /* this border is the top of the latest stack */
7364                   e_border_focus_set (temp_bd, 1, 1);
7365                }
7366              break;
7367           }
7368      }
7369    e_container_border_list_free(bl);
7370 }
7371 #endif
7372
7373 static void
7374 _e_border_eval(E_Border *bd)
7375 {
7376    E_Event_Border_Property *event;
7377    E_Border_Pending_Move_Resize *pnd;
7378    int rem_change = 0;
7379    int send_event = 1;
7380
7381    if (e_object_is_del(E_OBJECT(bd)))
7382      {
7383         fprintf(stderr, "ERROR: _e_border_eval(%p) with deleted border! - %d\n", bd, bd->new_client);
7384         bd->changed = 0;
7385         return;
7386      }
7387
7388    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_NEW_BORDER, bd);
7389
7390    if (bd->new_client)
7391      {
7392         int zx = 0, zy = 0, zw = 0, zh = 0;
7393
7394         if (bd->zone)
7395           e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
7396
7397         /*
7398          * Limit maximum size of windows to useful geometry
7399          */
7400         // TODO: temoporary limited maximize algorithm
7401         // ->
7402         /*if (bd->w > zw)
7403            rw = zw;
7404            else
7405            rw = bd->w;
7406
7407            if (bd->h > zh)
7408            rh = zh;
7409            else
7410            rh = bd->h;
7411
7412            if ((rw != bd->w) || (rh != bd->h))
7413            {
7414               bd->w = rw;
7415               bd->h = rh;
7416               e_border_resize (bd, bd->w, bd->h);
7417            }*/
7418         // <-
7419
7420         if (bd->re_manage)
7421           {
7422              bd->x -= bd->client_inset.l;
7423              bd->y -= bd->client_inset.t;
7424              bd->changes.pos = 1;
7425              bd->placed = 1;
7426           }
7427         else if (!bd->placed)
7428           {
7429              if (bd->client.icccm.request_pos)
7430                {
7431                   Ecore_X_Window_Attributes *att;
7432                   int bw;
7433
7434                   att = &bd->client.initial_attributes;
7435                   bw = att->border * 2;
7436                   switch (bd->client.icccm.gravity)
7437                     {
7438                      case ECORE_X_GRAVITY_N:
7439                        bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
7440                        bd->y = att->y;
7441                        break;
7442
7443                      case ECORE_X_GRAVITY_NE:
7444                        bd->x = (att->x - (bw)) - (bd->client_inset.l);
7445                        bd->y = att->y;
7446                        break;
7447
7448                      case ECORE_X_GRAVITY_E:
7449                        bd->x = (att->x - (bw)) - (bd->client_inset.l);
7450                        bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
7451                        break;
7452
7453                      case ECORE_X_GRAVITY_SE:
7454                        bd->x = (att->x - (bw)) - (bd->client_inset.l);
7455                        bd->y = (att->y - (bw)) - (bd->client_inset.t);
7456                        break;
7457
7458                      case ECORE_X_GRAVITY_S:
7459                        bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
7460                        bd->y = (att->y - (bw)) - (bd->client_inset.t);
7461                        break;
7462
7463                      case ECORE_X_GRAVITY_SW:
7464                        bd->x = att->x;
7465                        bd->y = (att->y - (bw)) - (bd->client_inset.t);
7466                        break;
7467
7468                      case ECORE_X_GRAVITY_W:
7469                        bd->x = att->x;
7470                        bd->y = (att->y - (bw)) - (bd->client_inset.t);
7471                        break;
7472
7473                      case ECORE_X_GRAVITY_CENTER:
7474                        bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
7475                        bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
7476                        break;
7477
7478                      case ECORE_X_GRAVITY_NW:
7479                      default:
7480                        bd->x = att->x;
7481                        bd->y = att->y;
7482                     }
7483
7484      /*
7485       * This ensures that windows that like to open with a x/y
7486       * position smaller than returned by e_zone_useful_geometry_get()
7487       * are moved to useful positions.
7488       */
7489                   // ->
7490                   if (bd->x < zx)
7491                     bd->x = zx;
7492
7493                   if (bd->y < zy)
7494                     bd->y = zy;
7495
7496                   if (bd->x + bd->w > zw)
7497                     bd->x = zx + zw - bd->w;
7498
7499                   if (bd->y + bd->h > zh)
7500                     bd->y = zy + zh - bd->h;
7501      // <--
7502
7503                   if (bd->zone && e_container_zone_at_point_get(bd->zone->container, bd->x, bd->y))
7504                     {
7505                        bd->changes.pos = 1;
7506                        bd->placed = 1;
7507                     }
7508                }
7509              if (!bd->placed)
7510                {
7511      /* FIXME: special placement for dialogs etc. etc. etc goes
7512       * here */
7513                   /* FIXME: what if parent is not on this desktop - or zone? */
7514                      if ((bd->parent) && (bd->parent->visible))
7515                        {
7516                           bd->x = bd->parent->x + ((bd->parent->w - bd->w) / 2);
7517                           bd->y = bd->parent->y + ((bd->parent->h - bd->h) / 2);
7518                           bd->changes.pos = 1;
7519                           bd->placed = 1;
7520                        }
7521 #if 0
7522                      else if ((bd->leader) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
7523                        {
7524      /* TODO: Place in center of group */
7525                        }
7526 #endif
7527                      else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
7528                        {
7529                           bd->x = zx + ((zw - bd->w) / 2);
7530                           bd->y = zy + ((zh - bd->h) / 2);
7531                           bd->changes.pos = 1;
7532                           bd->placed = 1;
7533                        }
7534                      if (!bd->placed)
7535                        {
7536                           Eina_List *skiplist = NULL;
7537                           int new_x, new_y;
7538
7539                           if (zw > bd->w)
7540                             new_x = zx + (rand() % (zw - bd->w));
7541                           else
7542                             new_x = zx;
7543                           if (zh > bd->h)
7544                             new_y = zy + (rand() % (zh - bd->h));
7545                           else
7546                             new_y = zy;
7547
7548                           if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
7549                             {
7550                                skiplist = eina_list_append(skiplist, bd);
7551                                e_place_zone_region_smart(bd->zone, skiplist,
7552                                                          bd->x, bd->y, bd->w, bd->h,
7553                                                          &new_x, &new_y);
7554                                eina_list_free(skiplist);
7555                             }
7556                           else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
7557                             {
7558                                e_place_zone_manual(bd->zone, bd->w, bd->client_inset.t,
7559                                                    &new_x, &new_y);
7560                             }
7561                           else
7562                             {
7563                                e_place_zone_cursor(bd->zone, bd->x, bd->y, bd->w, bd->h,
7564                                                    bd->client_inset.t, &new_x, &new_y);
7565                             }
7566                           bd->x = new_x;
7567                           bd->y = new_y;
7568                           bd->changes.pos = 1;
7569                        }
7570                }
7571           }
7572         EINA_LIST_FREE(bd->pending_move_resize, pnd)
7573           {
7574              if ((!bd->lock_client_location) && (pnd->move))
7575                {
7576                   bd->x = pnd->x;
7577                   bd->y = pnd->y;
7578                   bd->changes.pos = 1;
7579                   bd->placed = 1;
7580                   if (pnd->without_border)
7581                     {
7582                        bd->x -= bd->client_inset.l;
7583                        bd->y -= bd->client_inset.t;
7584                     }
7585                }
7586              if ((!bd->lock_client_size) && (pnd->resize))
7587                {
7588                   bd->w = pnd->w + (bd->client_inset.l + bd->client_inset.r);
7589                   bd->h = pnd->h + (bd->client_inset.t + bd->client_inset.b);
7590                   bd->client.w = pnd->w;
7591                   bd->client.h = pnd->h;
7592                   bd->changes.size = 1;
7593                }
7594              free(pnd);
7595           }
7596
7597         /* Recreate state */
7598         e_hints_window_init(bd);
7599         if ((bd->client.e.state.centered) &&
7600             ((!bd->remember) ||
7601              ((bd->remember) && (!(bd->remember->apply & E_REMEMBER_APPLY_POS)))))
7602           {
7603              bd->x = zx + (zw - bd->w) / 2;
7604              bd->y = zy + (zh - bd->h) / 2;
7605              bd->changes.pos = 1;
7606              bd->placed = 1;
7607           }
7608
7609         _e_border_client_move_resize_send(bd);
7610
7611         /* if the explicit geometry request asks for the app to be
7612          * in another zone - well move it there */
7613         {
7614            E_Zone *zone;
7615
7616            zone = e_container_zone_at_point_get(bd->zone->container,
7617                                                 bd->x + (bd->w / 2),
7618                                                 bd->y + (bd->h / 2));
7619            if (!zone)
7620              zone = e_container_zone_at_point_get(bd->zone->container,
7621                                                   bd->x,
7622                                                   bd->y);
7623            if (!zone)
7624              zone = e_container_zone_at_point_get(bd->zone->container,
7625                                                   bd->x + bd->w - 1,
7626                                                   bd->y);
7627            if (!zone)
7628              zone = e_container_zone_at_point_get(bd->zone->container,
7629                                                   bd->x + bd->w - 1,
7630                                                   bd->y + bd->h - 1);
7631            if (!zone)
7632              zone = e_container_zone_at_point_get(bd->zone->container,
7633                                                   bd->x,
7634                                                   bd->y + bd->h - 1);
7635            if ((zone) && (zone != bd->zone))
7636              {
7637                 e_border_zone_set(bd, zone);
7638      /* e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh); */
7639              }
7640         }
7641      }
7642
7643    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_NEW_BORDER, bd);
7644
7645    /* effect changes to the window border itself */
7646    if ((bd->changes.shading))
7647      {
7648         /*  show at start of unshade (but don't hide until end of shade) */
7649          if (bd->shaded)
7650            ecore_x_window_raise(bd->client.shell_win);
7651          bd->changes.shading = 0;
7652          rem_change = 1;
7653      }
7654    if ((bd->changes.shaded) && (bd->changes.pos) && (bd->changes.size))
7655      {
7656         if (bd->shaded)
7657           ecore_x_window_lower(bd->client.shell_win);
7658         else
7659           ecore_x_window_raise(bd->client.shell_win);
7660         bd->changes.shaded = 0;
7661         rem_change = 1;
7662      }
7663    else if ((bd->changes.shaded) && (bd->changes.pos))
7664      {
7665         if (bd->shaded)
7666           ecore_x_window_lower(bd->client.shell_win);
7667         else
7668           ecore_x_window_raise(bd->client.shell_win);
7669         bd->changes.size = 1;
7670         bd->changes.shaded = 0;
7671         rem_change = 1;
7672      }
7673    else if ((bd->changes.shaded) && (bd->changes.size))
7674      {
7675         if (bd->shaded)
7676           ecore_x_window_lower(bd->client.shell_win);
7677         else
7678           ecore_x_window_raise(bd->client.shell_win);
7679         bd->changes.shaded = 0;
7680         rem_change = 1;
7681      }
7682    else if (bd->changes.shaded)
7683      {
7684         if (bd->shaded)
7685           ecore_x_window_lower(bd->client.shell_win);
7686         else
7687           ecore_x_window_raise(bd->client.shell_win);
7688         bd->changes.size = 1;
7689         bd->changes.shaded = 0;
7690         rem_change = 1;
7691      }
7692
7693    if (bd->changes.size)
7694      {
7695         int x = 0, y = 0, xx = 0, yy = 0;
7696
7697         if ((bd->shaded) && (!bd->shading))
7698           {
7699              evas_obscured_clear(bd->bg_evas);
7700           }
7701         else
7702           {
7703              xx = bd->w - (bd->client_inset.l + bd->client_inset.r);
7704              yy = bd->h - (bd->client_inset.t + bd->client_inset.b);
7705
7706              evas_obscured_clear(bd->bg_evas);
7707              evas_obscured_rectangle_add(bd->bg_evas,
7708                                          bd->client_inset.l, bd->client_inset.t, xx, yy);
7709
7710              if (bd->shading)
7711                {
7712                   if (bd->shade.dir == E_DIRECTION_UP)
7713                     {
7714                        y = yy - bd->client.h;
7715                     }
7716                   else if (bd->shade.dir == E_DIRECTION_LEFT)
7717                     {
7718                        x = xx - bd->client.w;
7719                     }
7720                }
7721           }
7722
7723         if (!bd->changes.pos)
7724           {
7725              if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
7726              bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
7727              bd->post_resize = 1;
7728           }
7729         else
7730           {
7731              ecore_x_window_move_resize(bd->win,
7732                                         bd->x + bd->fx.x,
7733                                         bd->y + bd->fx.y,
7734                                         bd->w, bd->h);
7735           }
7736
7737         ecore_x_window_move_resize(bd->event_win, 0, 0, bd->w, bd->h);
7738
7739         if ((!bd->shaded) || (bd->shading))
7740           ecore_x_window_move_resize(bd->client.shell_win,
7741                                      bd->client_inset.l, bd->client_inset.t, xx, yy);
7742
7743         if (bd->internal_ecore_evas)
7744           ecore_evas_move_resize(bd->internal_ecore_evas, x, y, bd->client.w, bd->client.h);
7745         else
7746           ecore_x_window_move_resize(bd->client.win, x, y, bd->client.w, bd->client.h);
7747
7748         ecore_evas_move_resize(bd->bg_ecore_evas, 0, 0, bd->w, bd->h);
7749         evas_object_resize(bd->bg_object, bd->w, bd->h);
7750         e_container_shape_resize(bd->shape, bd->w, bd->h);
7751         if (bd->changes.pos)
7752           e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
7753
7754         _e_border_client_move_resize_send(bd);
7755
7756         bd->changes.pos = 0;
7757         bd->changes.size = 0;
7758         rem_change = 1;
7759      }
7760    else if (bd->changes.pos)
7761      {
7762         if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
7763         bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
7764         bd->post_move = 1;
7765
7766         e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
7767
7768         _e_border_client_move_resize_send(bd);
7769
7770         bd->changes.pos = 0;
7771         rem_change = 1;
7772      }
7773
7774    if (bd->changes.reset_gravity)
7775      {
7776         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
7777         bd->changes.reset_gravity = 0;
7778         rem_change = 1;
7779      }
7780
7781    if (bd->need_shape_merge)
7782      {
7783         _e_border_shape_input_rectangle_set(bd);
7784         if ((bd->shaped) || (bd->client.shaped))
7785           {
7786              Ecore_X_Window twin, twin2;
7787              int x, y;
7788
7789              twin = ecore_x_window_override_new
7790                 (bd->zone->container->scratch_win, 0, 0, bd->w, bd->h);
7791              if (bd->shaped)
7792                ecore_x_window_shape_window_set(twin, bd->bg_win);
7793              else
7794                {
7795                   Ecore_X_Rectangle rects[4];
7796
7797                   rects[0].x = 0;
7798                   rects[0].y = 0;
7799                   rects[0].width = bd->w;
7800                   rects[0].height = bd->client_inset.t;
7801                   rects[1].x = 0;
7802                   rects[1].y = bd->client_inset.t;
7803                   rects[1].width = bd->client_inset.l;
7804                   rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
7805                   rects[2].x = bd->w - bd->client_inset.r;
7806                   rects[2].y = bd->client_inset.t;
7807                   rects[2].width = bd->client_inset.r;
7808                   rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
7809                   rects[3].x = 0;
7810                   rects[3].y = bd->h - bd->client_inset.b;
7811                   rects[3].width = bd->w;
7812                   rects[3].height = bd->client_inset.b;
7813                   ecore_x_window_shape_rectangles_set(twin, rects, 4);
7814                }
7815              twin2 = ecore_x_window_override_new
7816                 (bd->zone->container->scratch_win, 0, 0,
7817                     bd->w - bd->client_inset.l - bd->client_inset.r,
7818                     bd->h - bd->client_inset.t - bd->client_inset.b);
7819              x = 0;
7820              y = 0;
7821              if ((bd->shading) || (bd->shaded))
7822                {
7823                   if (bd->shade.dir == E_DIRECTION_UP)
7824                     y = bd->h - bd->client_inset.t - bd->client_inset.b - bd->client.h;
7825                   else if (bd->shade.dir == E_DIRECTION_LEFT)
7826                     x = bd->w - bd->client_inset.l - bd->client_inset.r - bd->client.w;
7827                }
7828              ecore_x_window_shape_window_set_xy(twin2, bd->client.win,
7829                                                 x, y);
7830              ecore_x_window_shape_rectangle_clip(twin2, 0, 0,
7831                                                  bd->w - bd->client_inset.l - bd->client_inset.r,
7832                                                  bd->h - bd->client_inset.t - bd->client_inset.b);
7833              ecore_x_window_shape_window_add_xy(twin, twin2,
7834                                                 bd->client_inset.l,
7835                                                 bd->client_inset.t);
7836              ecore_x_window_free(twin2);
7837              ecore_x_window_shape_window_set(bd->win, twin);
7838              ecore_x_window_free(twin);
7839           }
7840         else
7841           ecore_x_window_shape_mask_set(bd->win, 0);
7842 //      bd->need_shape_export = 1;
7843         bd->need_shape_merge = 0;
7844      }
7845
7846    if (bd->need_shape_export)
7847      {
7848         Ecore_X_Rectangle *rects, *orects;
7849         int num;
7850
7851         rects = ecore_x_window_shape_rectangles_get(bd->win, &num);
7852         if (rects)
7853           {
7854              int changed;
7855
7856              changed = 1;
7857              if ((num == bd->shape_rects_num) && (bd->shape_rects))
7858                {
7859                   int i;
7860
7861                   orects = bd->shape_rects;
7862                   changed = 0;
7863                   for (i = 0; i < num; i++)
7864                     {
7865                        if (rects[i].x < 0)
7866                          {
7867                             rects[i].width -= rects[i].x;
7868                             rects[i].x = 0;
7869                          }
7870                        if ((rects[i].x + (int)rects[i].width) > bd->w)
7871                          rects[i].width = rects[i].width - rects[i].x;
7872                        if (rects[i].y < 0)
7873                          {
7874                             rects[i].height -= rects[i].y;
7875                             rects[i].y = 0;
7876                          }
7877                        if ((rects[i].y + (int)rects[i].height) > bd->h)
7878                          rects[i].height = rects[i].height - rects[i].y;
7879
7880                        if ((orects[i].x != rects[i].x) ||
7881                            (orects[i].y != rects[i].y) ||
7882                            (orects[i].width != rects[i].width) ||
7883                            (orects[i].height != rects[i].height))
7884                          {
7885                             changed = 1;
7886                             break;
7887                          }
7888                     }
7889                }
7890              if (changed)
7891                {
7892                   if (bd->client.shaped)
7893                     e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
7894                   else
7895                     e_container_shape_solid_rect_set(bd->shape, bd->client_inset.l, bd->client_inset.t, bd->client.w, bd->client.h);
7896                   E_FREE(bd->shape_rects);
7897                   bd->shape_rects = rects;
7898                   bd->shape_rects_num = num;
7899                   e_container_shape_rects_set(bd->shape, rects, num);
7900                }
7901              else
7902                free(rects);
7903           }
7904         else
7905           {
7906              E_FREE(bd->shape_rects);
7907              bd->shape_rects = NULL;
7908              bd->shape_rects_num = 0;
7909              e_container_shape_rects_set(bd->shape, NULL, 0);
7910           }
7911         bd->need_shape_export = 0;
7912      }
7913
7914    if ((bd->changes.visible) && (bd->visible) && (bd->new_client))
7915      {
7916         int x, y;
7917
7918         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
7919         if ((!bd->placed) && (!bd->re_manage) &&
7920             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
7921             (!((bd->client.icccm.transient_for != 0) ||
7922                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) &&
7923             (!move) && (!resize))
7924           {
7925              /* Set this window into moving state */
7926
7927               bd->cur_mouse_action = e_action_find("window_move");
7928               if (bd->cur_mouse_action)
7929                 {
7930                    if ((!bd->cur_mouse_action->func.end_mouse) &&
7931                        (!bd->cur_mouse_action->func.end))
7932                      bd->cur_mouse_action = NULL;
7933                    if (bd->cur_mouse_action)
7934                      {
7935                         bd->x = x - (bd->w >> 1);
7936                         bd->y = y - (bd->client_inset.t >> 1);
7937                         bd->changed = 1;
7938                         bd->changes.pos = 1;
7939
7940                         _e_border_client_move_resize_send(bd);
7941                      }
7942                 }
7943           }
7944
7945         _e_border_show(bd);
7946
7947         if (bd->cur_mouse_action)
7948           {
7949              bd->moveinfo.down.x = bd->x + bd->fx.x;
7950              bd->moveinfo.down.y = bd->y + bd->fx.y;
7951              bd->moveinfo.down.w = bd->w;
7952              bd->moveinfo.down.h = bd->h;
7953              bd->mouse.current.mx = x;
7954              bd->mouse.current.my = y;
7955              bd->moveinfo.down.button = 0;
7956              bd->moveinfo.down.mx = x;
7957              bd->moveinfo.down.my = y;
7958
7959              grabbed = 1;
7960              e_object_ref(E_OBJECT(bd->cur_mouse_action));
7961              bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
7962              if (e_config->border_raise_on_mouse_action)
7963                e_border_raise(bd);
7964              e_border_focus_set(bd, 1, 1);
7965           }
7966         bd->changes.visible = 0;
7967         rem_change = 1;
7968      }
7969
7970    if (bd->changes.icon)
7971      {
7972         if (bd->desktop)
7973           {
7974              efreet_desktop_free(bd->desktop);
7975              bd->desktop = NULL;
7976           }
7977         if (bd->icon_object)
7978           {
7979              evas_object_del(bd->icon_object);
7980              bd->icon_object = NULL;
7981           }
7982         if (bd->remember && bd->remember->prop.desktop_file)
7983           {
7984              const char *desktop = bd->remember->prop.desktop_file;
7985
7986              bd->desktop = efreet_desktop_get(desktop);
7987              if (!bd->desktop)
7988                bd->desktop = efreet_util_desktop_name_find(desktop);
7989           }
7990         if (!bd->desktop)
7991           {
7992              if ((bd->client.icccm.name) && (bd->client.icccm.class))
7993                bd->desktop = efreet_util_desktop_wm_class_find(bd->client.icccm.name,
7994                                                                bd->client.icccm.class);
7995           }
7996         if (!bd->desktop)
7997           {
7998              bd->desktop = e_exec_startup_id_pid_find(bd->client.netwm.startup_id,
7999                                                       bd->client.netwm.pid);
8000              if (bd->desktop) efreet_desktop_ref(bd->desktop);
8001           }
8002         if (!bd->desktop && bd->client.icccm.name)
8003           {
8004              /* this works for most cases as fallback. useful when app is
8005                 run from a shell  */
8006                bd->desktop = efreet_util_desktop_exec_find(bd->client.icccm.name);
8007           }
8008         if (!bd->desktop && bd->client.icccm.transient_for)
8009           {
8010              E_Border *bd2 = e_border_find_by_client_window(bd->client.icccm.transient_for);
8011              if (bd2 && bd2->desktop)
8012                {
8013                   efreet_desktop_ref(bd2->desktop);
8014                   bd->desktop = bd2->desktop;
8015                }
8016           }
8017         if (bd->desktop)
8018           {
8019              ecore_x_window_prop_string_set(bd->client.win, E_ATOM_DESKTOP_FILE,
8020                                             bd->desktop->orig_path);
8021           }
8022
8023         bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
8024         if ((bd->focused) && (bd->icon_object))
8025           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
8026         if (bd->bg_object)
8027           {
8028              evas_object_show(bd->icon_object);
8029              edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
8030           }
8031         else
8032           evas_object_hide(bd->icon_object);
8033
8034         {
8035            E_Event_Border_Icon_Change *ev;
8036
8037            ev = E_NEW(E_Event_Border_Icon_Change, 1);
8038            ev->border = bd;
8039            e_object_ref(E_OBJECT(bd));
8040 //           e_object_breadcrumb_add(E_OBJECT(bd), "border_icon_change_event");
8041            ecore_event_add(E_EVENT_BORDER_ICON_CHANGE, ev,
8042                            _e_border_event_border_icon_change_free, NULL);
8043         }
8044         bd->changes.icon = 0;
8045      }
8046
8047    bd->new_client = 0;
8048    bd->changed = 0;
8049    bd->changes.stack = 0;
8050    bd->changes.prop = 0;
8051
8052    if ((bd->take_focus) || (bd->want_focus))
8053      {
8054         bd->take_focus = 0;
8055 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
8056         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
8057             (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
8058             (bd->want_focus))
8059 #else // original
8060         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
8061             (bd->want_focus))
8062 #endif
8063           {
8064              bd->want_focus = 0;
8065 #ifdef INOUTDEBUG_FOCUS
8066              printf("__________ focus new window _________\n");
8067 #endif
8068
8069 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
8070              if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
8071                 _e_border_check_stack(bd);
8072              else
8073 #endif
8074              e_border_focus_set_with_pointer(bd);
8075           }
8076         else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
8077           {
8078              if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
8079                  ((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
8080                   (e_border_find_by_client_window(bd->client.icccm.transient_for) ==
8081                    e_border_focused_get())))
8082                {
8083 #ifdef INOUTDEBUG_FOCUS
8084                   printf("__________ focus new dialog _________\n");
8085 #endif
8086
8087                   e_border_focus_set_with_pointer(bd);
8088                }
8089           }
8090         else
8091           {
8092 #ifdef INOUTDEBUG_FOCUS
8093              printf("__________ window takes focus _________\n");
8094 #endif
8095              /* focus window by default when it is the only one on desk */
8096               E_Border *bd2 = NULL;
8097               Eina_List *l;
8098               EINA_LIST_FOREACH(focus_stack, l, bd2)
8099                 {
8100                    if (bd == bd2) continue;
8101                    if ((!bd2->iconic) && (bd2->visible) && (bd->desk == bd2->desk))
8102                      break;
8103                 }
8104
8105               if (!bd2)
8106                 e_border_focus_set_with_pointer(bd);
8107           }
8108      }
8109
8110    if (bd->need_maximize)
8111      {
8112         E_Maximize max;
8113         max = bd->maximized;
8114         bd->maximized = E_MAXIMIZE_NONE;
8115         e_border_maximize(bd, max);
8116         bd->need_maximize = 0;
8117      }
8118
8119    if (bd->need_fullscreen)
8120      {
8121         e_border_fullscreen(bd, e_config->fullscreen_policy);
8122         bd->need_fullscreen = 0;
8123      }
8124
8125    if (rem_change)
8126      e_remember_update(bd);
8127
8128    if (send_event) // FIXME: send only if a property changed - above need to
8129      { // check on that. for now - always send.
8130          event = E_NEW(E_Event_Border_Property, 1);
8131          event->border = bd;
8132          e_object_ref(E_OBJECT(bd));
8133          ecore_event_add(E_EVENT_BORDER_PROPERTY, event, _e_border_event_border_property_free, NULL);
8134      }
8135    _e_border_hook_call(E_BORDER_HOOK_EVAL_END, bd);
8136 }
8137
8138 static void
8139 _e_border_moveinfo_gather(E_Border   *bd,
8140                           const char *source)
8141 {
8142    if (e_util_glob_match(source, "mouse,*,1")) bd->moveinfo.down.button = 1;
8143    else if (e_util_glob_match(source, "mouse,*,2"))
8144      bd->moveinfo.down.button = 2;
8145    else if (e_util_glob_match(source, "mouse,*,3"))
8146      bd->moveinfo.down.button = 3;
8147    else bd->moveinfo.down.button = 0;
8148    if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
8149      {
8150         bd->moveinfo.down.mx = bd->mouse.last_down[bd->moveinfo.down.button - 1].mx;
8151         bd->moveinfo.down.my = bd->mouse.last_down[bd->moveinfo.down.button - 1].my;
8152      }
8153    else
8154      {
8155         bd->moveinfo.down.mx = bd->mouse.current.mx;
8156         bd->moveinfo.down.my = bd->mouse.current.my;
8157      }
8158 }
8159
8160 static void
8161 _e_border_resize_handle(E_Border *bd)
8162 {
8163    int x, y, w, h;
8164    int new_x, new_y, new_w, new_h;
8165    int tw, th;
8166    Eina_List *skiplist = NULL;
8167
8168    x = bd->x;
8169    y = bd->y;
8170    w = bd->w;
8171    h = bd->h;
8172
8173    if ((bd->resize_mode == RESIZE_TR) ||
8174        (bd->resize_mode == RESIZE_R) ||
8175        (bd->resize_mode == RESIZE_BR))
8176      {
8177         if ((bd->moveinfo.down.button >= 1) &&
8178             (bd->moveinfo.down.button <= 3))
8179           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w +
8180             (bd->mouse.current.mx - bd->moveinfo.down.mx);
8181         else
8182           w = bd->moveinfo.down.w + (bd->mouse.current.mx - bd->moveinfo.down.mx);
8183      }
8184    else if ((bd->resize_mode == RESIZE_TL) ||
8185             (bd->resize_mode == RESIZE_L) ||
8186             (bd->resize_mode == RESIZE_BL))
8187      {
8188         if ((bd->moveinfo.down.button >= 1) &&
8189             (bd->moveinfo.down.button <= 3))
8190           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w -
8191             (bd->mouse.current.mx - bd->moveinfo.down.mx);
8192         else
8193           w = bd->moveinfo.down.w - (bd->mouse.current.mx - bd->moveinfo.down.mx);
8194      }
8195
8196    if ((bd->resize_mode == RESIZE_TL) ||
8197        (bd->resize_mode == RESIZE_T) ||
8198        (bd->resize_mode == RESIZE_TR))
8199      {
8200         if ((bd->moveinfo.down.button >= 1) &&
8201             (bd->moveinfo.down.button <= 3))
8202           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h -
8203             (bd->mouse.current.my - bd->moveinfo.down.my);
8204         else
8205           h = bd->moveinfo.down.h - (bd->mouse.current.my - bd->moveinfo.down.my);
8206      }
8207    else if ((bd->resize_mode == RESIZE_BL) ||
8208             (bd->resize_mode == RESIZE_B) ||
8209             (bd->resize_mode == RESIZE_BR))
8210      {
8211         if ((bd->moveinfo.down.button >= 1) &&
8212             (bd->moveinfo.down.button <= 3))
8213           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h +
8214             (bd->mouse.current.my - bd->moveinfo.down.my);
8215         else
8216           h = bd->moveinfo.down.h + (bd->mouse.current.my - bd->moveinfo.down.my);
8217      }
8218
8219    tw = bd->w;
8220    th = bd->h;
8221
8222    if ((bd->resize_mode == RESIZE_TL) ||
8223        (bd->resize_mode == RESIZE_L) ||
8224        (bd->resize_mode == RESIZE_BL))
8225      x += (tw - w);
8226    if ((bd->resize_mode == RESIZE_TL) ||
8227        (bd->resize_mode == RESIZE_T) ||
8228        (bd->resize_mode == RESIZE_TR))
8229      y += (th - h);
8230
8231    skiplist = eina_list_append(skiplist, bd);
8232    e_resist_container_border_position(bd->zone->container, skiplist,
8233                                       bd->x, bd->y, bd->w, bd->h,
8234                                       x, y, w, h,
8235                                       &new_x, &new_y, &new_w, &new_h);
8236    eina_list_free(skiplist);
8237
8238    w = new_w;
8239    h = new_h;
8240    e_border_resize_limit(bd, &new_w, &new_h);
8241    if ((bd->resize_mode == RESIZE_TL) ||
8242        (bd->resize_mode == RESIZE_L) ||
8243        (bd->resize_mode == RESIZE_BL))
8244      new_x += (w - new_w);
8245    if ((bd->resize_mode == RESIZE_TL) ||
8246        (bd->resize_mode == RESIZE_T) ||
8247        (bd->resize_mode == RESIZE_TR))
8248      new_y += (h - new_h);
8249
8250    e_border_move_resize(bd, new_x, new_y, new_w, new_h);
8251 }
8252
8253 static Eina_Bool
8254 _e_border_shade_animator(void *data)
8255 {
8256    E_Border *bd = data;
8257    double dt, val;
8258    double dur = bd->client.h / e_config->border_shade_speed;
8259
8260    dt = ecore_loop_time_get() - bd->shade.start;
8261    val = dt / dur;
8262
8263    if (val < 0.0) val = 0.0;
8264    else if (val > 1.0)
8265      val = 1.0;
8266
8267    if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
8268      {
8269         if (bd->shaded)
8270           bd->shade.val = (1 - cos(val * M_PI)) / 2.0;
8271         else
8272           bd->shade.val = 0.5 + (cos(val * M_PI) / 2.0);
8273      }
8274    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE)
8275      {
8276         if (bd->shaded)
8277           bd->shade.val = sin(val * M_PI / 2.0);
8278         else
8279           bd->shade.val = 1 - sin(val * M_PI / 2.0);
8280      }
8281    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE)
8282      {
8283         if (bd->shaded)
8284           bd->shade.val = 1 - cos(val * M_PI / 2.0);
8285         else
8286           bd->shade.val = cos(val * M_PI / 2.0);
8287      }
8288    else /* LINEAR if none of the others */
8289      {
8290         if (bd->shaded)
8291           bd->shade.val = val;
8292         else
8293           bd->shade.val = 1 - val;
8294      }
8295
8296    /* due to M_PI's innacuracy, cos(M_PI/2) != 0.0, so we need this */
8297    if (bd->shade.val < 0.001) bd->shade.val = 0.0;
8298    else if (bd->shade.val > .999)
8299      bd->shade.val = 1.0;
8300
8301    if (bd->shade.dir == E_DIRECTION_UP)
8302      bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
8303    else if (bd->shade.dir == E_DIRECTION_DOWN)
8304      {
8305         bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
8306         bd->y = bd->shade.y + bd->client.h * (1 - bd->shade.val);
8307         bd->changes.pos = 1;
8308      }
8309    else if (bd->shade.dir == E_DIRECTION_LEFT)
8310      bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
8311    else if (bd->shade.dir == E_DIRECTION_RIGHT)
8312      {
8313         bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
8314         bd->x = bd->shade.x + bd->client.w * (1 - bd->shade.val);
8315         bd->changes.pos = 1;
8316      }
8317
8318    if ((bd->shaped) || (bd->client.shaped))
8319      {
8320         bd->need_shape_merge = 1;
8321         bd->need_shape_export = 1;
8322      }
8323    if (bd->shaped_input)
8324      {
8325         bd->need_shape_merge = 1;
8326      }
8327    bd->changes.size = 1;
8328    bd->changed = 1;
8329
8330    /* we're done */
8331    if ((bd->shaded && (bd->shade.val == 1)) ||
8332        ((!bd->shaded) && (bd->shade.val == 0)))
8333      {
8334         E_Event_Border_Resize *ev;
8335
8336         bd->shading = 0;
8337         bd->shaded = !(bd->shaded);
8338         bd->changes.size = 1;
8339         bd->changes.shaded = 1;
8340         bd->changes.shading = 1;
8341         bd->changed = 1;
8342         bd->shade.anim = NULL;
8343
8344         if (bd->shaded)
8345           edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
8346         else
8347           edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
8348         edje_object_message_signal_process(bd->bg_object);
8349         e_border_frame_recalc(bd);
8350
8351         ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NW);
8352         ev = E_NEW(E_Event_Border_Resize, 1);
8353         ev->border = bd;
8354         e_object_ref(E_OBJECT(bd));
8355 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
8356         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
8357         return ECORE_CALLBACK_CANCEL;
8358      }
8359    return ECORE_CALLBACK_RENEW;
8360 }
8361
8362 static void
8363 _e_border_event_border_resize_free(void *data __UNUSED__,
8364                                    void      *ev)
8365 {
8366    E_Event_Border_Resize *e;
8367
8368    e = ev;
8369 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_resize_event");
8370    e_object_unref(E_OBJECT(e->border));
8371    E_FREE(e);
8372 }
8373
8374 static void
8375 _e_border_event_border_move_free(void *data __UNUSED__,
8376                                  void      *ev)
8377 {
8378    E_Event_Border_Move *e;
8379
8380    e = ev;
8381 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_move_event");
8382    e_object_unref(E_OBJECT(e->border));
8383    E_FREE(e);
8384 }
8385
8386 static void
8387 _e_border_event_border_add_free(void *data __UNUSED__,
8388                                 void      *ev)
8389 {
8390    E_Event_Border_Add *e;
8391
8392    e = ev;
8393 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_add_event");
8394    e_object_unref(E_OBJECT(e->border));
8395    E_FREE(e);
8396 }
8397
8398 static void
8399 _e_border_event_border_remove_free(void *data __UNUSED__,
8400                                    void      *ev)
8401 {
8402    E_Event_Border_Remove *e;
8403
8404    e = ev;
8405 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_remove_event");
8406    e_object_unref(E_OBJECT(e->border));
8407    E_FREE(e);
8408 }
8409
8410 static void
8411 _e_border_event_border_show_free(void *data __UNUSED__,
8412                                  void      *ev)
8413 {
8414    E_Event_Border_Show *e;
8415
8416    e = ev;
8417 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_show_event");
8418    e_object_unref(E_OBJECT(e->border));
8419    E_FREE(e);
8420 }
8421
8422 static void
8423 _e_border_event_border_hide_free(void *data __UNUSED__,
8424                                  void      *ev)
8425 {
8426    E_Event_Border_Hide *e;
8427
8428    e = ev;
8429 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_hide_event");
8430    e_object_unref(E_OBJECT(e->border));
8431    E_FREE(e);
8432 }
8433
8434 static void
8435 _e_border_event_border_iconify_free(void *data __UNUSED__,
8436                                     void      *ev)
8437 {
8438    E_Event_Border_Iconify *e;
8439
8440    e = ev;
8441 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_iconify_event");
8442    e_object_unref(E_OBJECT(e->border));
8443    E_FREE(e);
8444 }
8445
8446 static void
8447 _e_border_event_border_uniconify_free(void *data __UNUSED__,
8448                                       void      *ev)
8449 {
8450    E_Event_Border_Uniconify *e;
8451
8452    e = ev;
8453 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_uniconify_event");
8454    e_object_unref(E_OBJECT(e->border));
8455    E_FREE(e);
8456 }
8457
8458 static void
8459 _e_border_event_border_stick_free(void *data __UNUSED__,
8460                                   void      *ev)
8461 {
8462    E_Event_Border_Stick *e;
8463
8464    e = ev;
8465 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_stick_event");
8466    e_object_unref(E_OBJECT(e->border));
8467    E_FREE(e);
8468 }
8469
8470 static void
8471 _e_border_event_border_unstick_free(void *data __UNUSED__,
8472                                     void      *ev)
8473 {
8474    E_Event_Border_Unstick *e;
8475
8476    e = ev;
8477 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unstick_event");
8478    e_object_unref(E_OBJECT(e->border));
8479    E_FREE(e);
8480 }
8481
8482 static void
8483 _e_border_event_border_zone_set_free(void *data __UNUSED__,
8484                                      void      *ev)
8485 {
8486    E_Event_Border_Zone_Set *e;
8487
8488    e = ev;
8489 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_zone_set_event");
8490    e_object_unref(E_OBJECT(e->border));
8491    e_object_unref(E_OBJECT(e->zone));
8492    E_FREE(e);
8493 }
8494
8495 static void
8496 _e_border_event_border_desk_set_free(void *data __UNUSED__,
8497                                      void      *ev)
8498 {
8499    E_Event_Border_Desk_Set *e;
8500
8501    e = ev;
8502 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_desk_set_event");
8503    e_object_unref(E_OBJECT(e->border));
8504    e_object_unref(E_OBJECT(e->desk));
8505    E_FREE(e);
8506 }
8507
8508 static void
8509 _e_border_event_border_stack_free(void *data __UNUSED__,
8510                                   void      *ev)
8511 {
8512    E_Event_Border_Stack *e;
8513
8514    e = ev;
8515 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_raise_event");
8516    e_object_unref(E_OBJECT(e->border));
8517    if (e->stack)
8518      {
8519 //      e_object_breadcrumb_del(E_OBJECT(e->above), "border_raise_event.above");
8520           e_object_unref(E_OBJECT(e->stack));
8521      }
8522    E_FREE(e);
8523 }
8524
8525 static void
8526 _e_border_event_border_icon_change_free(void *data __UNUSED__,
8527                                         void      *ev)
8528 {
8529    E_Event_Border_Icon_Change *e;
8530
8531    e = ev;
8532 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
8533    e_object_unref(E_OBJECT(e->border));
8534    E_FREE(e);
8535 }
8536
8537 static void
8538 _e_border_event_border_urgent_change_free(void *data __UNUSED__,
8539                                           void      *ev)
8540 {
8541    E_Event_Border_Urgent_Change *e;
8542
8543    e = ev;
8544    e_object_unref(E_OBJECT(e->border));
8545    E_FREE(e);
8546 }
8547
8548 static void
8549 _e_border_event_border_focus_in_free(void *data __UNUSED__,
8550                                      void      *ev)
8551 {
8552    E_Event_Border_Focus_In *e;
8553
8554    e = ev;
8555    e_object_unref(E_OBJECT(e->border));
8556    E_FREE(e);
8557 }
8558
8559 static void
8560 _e_border_event_border_focus_out_free(void *data __UNUSED__,
8561                                       void      *ev)
8562 {
8563    E_Event_Border_Focus_Out *e;
8564
8565    e = ev;
8566    e_object_unref(E_OBJECT(e->border));
8567    E_FREE(e);
8568 }
8569
8570 static void
8571 _e_border_event_border_property_free(void *data __UNUSED__,
8572                                      void      *ev)
8573 {
8574    E_Event_Border_Property *e;
8575
8576    e = ev;
8577    e_object_unref(E_OBJECT(e->border));
8578    E_FREE(e);
8579 }
8580
8581 static void
8582 _e_border_event_border_fullscreen_free(void *data __UNUSED__,
8583                                        void      *ev)
8584 {
8585    E_Event_Border_Fullscreen *e;
8586
8587    e = ev;
8588 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_fullscreen_event");
8589    e_object_unref(E_OBJECT(e->border));
8590    E_FREE(e);
8591 }
8592
8593 static void
8594 _e_border_event_border_unfullscreen_free(void *data __UNUSED__,
8595                                          void      *ev)
8596 {
8597    E_Event_Border_Unfullscreen *e;
8598
8599    e = ev;
8600 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unfullscreen_event");
8601    e_object_unref(E_OBJECT(e->border));
8602    E_FREE(e);
8603 }
8604
8605 static void
8606 _e_border_zone_update(E_Border *bd)
8607 {
8608    E_Container *con;
8609    Eina_List *l;
8610    E_Zone *zone;
8611
8612    /* still within old zone - leave it there */
8613    if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
8614                     bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
8615      return;
8616    /* find a new zone */
8617    con = bd->zone->container;
8618    EINA_LIST_FOREACH(con->zones, l, zone)
8619      {
8620         if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
8621                          zone->x, zone->y, zone->w, zone->h))
8622           {
8623              e_border_zone_set(bd, zone);
8624              return;
8625           }
8626      }
8627 }
8628
8629 static int
8630 _e_border_resize_begin(E_Border *bd)
8631 {
8632    if (!bd->lock_user_stacking)
8633      {
8634         if (e_config->border_raise_on_mouse_action)
8635           e_border_raise(bd);
8636      }
8637    if ((bd->shaded) || (bd->shading) ||
8638        (bd->fullscreen) || (bd->lock_user_size))
8639      return 0;
8640
8641    if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
8642      {
8643         grabbed = 0;
8644         return 0;
8645      }
8646
8647    if (bd->client.netwm.sync.request)
8648      {
8649         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
8650         bd->client.netwm.sync.serial = 1;
8651         bd->client.netwm.sync.wait = 0;
8652         bd->client.netwm.sync.send_time = ecore_loop_time_get();
8653      }
8654
8655    _e_border_hook_call(E_BORDER_HOOK_RESIZE_BEGIN, bd);
8656
8657    resize = bd;
8658    return 1;
8659 }
8660
8661 static int
8662 _e_border_resize_end(E_Border *bd)
8663 {
8664    if (grabbed)
8665      {
8666         e_grabinput_release(bd->win, bd->win);
8667         grabbed = 0;
8668      }
8669    if (bd->client.netwm.sync.alarm)
8670      {
8671         E_Border_Pending_Move_Resize *pnd;
8672
8673         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
8674         bd->client.netwm.sync.alarm = 0;
8675         /* resize to last geometry if sync alarm for it was not yet handled */
8676         if (bd->pending_move_resize)
8677           {
8678              bd->changed = 1;
8679              bd->changes.pos = 1;
8680              bd->changes.size = 1;
8681              _e_border_client_move_resize_send(bd);
8682           }
8683
8684         EINA_LIST_FREE(bd->pending_move_resize, pnd)
8685           E_FREE(pnd);
8686      }
8687
8688    _e_border_hook_call(E_BORDER_HOOK_RESIZE_END, bd);
8689
8690    resize = NULL;
8691
8692    /* If this border was maximized, we need to unset Maximized state or
8693     * on restart, E still thinks it's maximized */
8694    if (bd->maximized != E_MAXIMIZE_NONE)
8695      e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_NONE,
8696                                   bd->maximized & E_MAXIMIZE_NONE);
8697    return 1;
8698 }
8699
8700 static void
8701 _e_border_resize_update(E_Border *bd)
8702 {
8703    _e_border_hook_call(E_BORDER_HOOK_RESIZE_UPDATE, bd);
8704 }
8705
8706 static int
8707 _e_border_move_begin(E_Border *bd)
8708 {
8709    if (!bd->lock_user_stacking)
8710      {
8711         if (e_config->border_raise_on_mouse_action)
8712           e_border_raise(bd);
8713      }
8714    if ((bd->fullscreen) || (bd->lock_user_location))
8715      return 0;
8716
8717    if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
8718      {
8719         grabbed = 0;
8720         return 0;
8721      }
8722 #if 0
8723    if (bd->client.netwm.sync.request)
8724      {
8725         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
8726         bd->client.netwm.sync.serial = 0;
8727         bd->client.netwm.sync.wait = 0;
8728         bd->client.netwm.sync.time = ecore_loop_time_get();
8729      }
8730 #endif
8731    _e_border_hook_call(E_BORDER_HOOK_MOVE_BEGIN, bd);
8732
8733    move = bd;
8734    return 1;
8735 }
8736
8737 static int
8738 _e_border_move_end(E_Border *bd)
8739 {
8740    if (grabbed)
8741      {
8742         e_grabinput_release(bd->win, bd->win);
8743         grabbed = 0;
8744      }
8745 #if 0
8746    if (bd->client.netwm.sync.alarm)
8747      {
8748         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
8749         bd->client.netwm.sync.alarm = 0;
8750      }
8751 #endif
8752    _e_border_hook_call(E_BORDER_HOOK_MOVE_END, bd);
8753
8754    move = NULL;
8755    return 1;
8756 }
8757
8758 static void
8759 _e_border_move_update(E_Border *bd)
8760 {
8761    _e_border_hook_call(E_BORDER_HOOK_MOVE_UPDATE, bd);
8762 }
8763
8764 static Eina_Bool
8765 _e_border_cb_ping_poller(void *data)
8766 {
8767    E_Border *bd;
8768
8769    bd = data;
8770    if (bd->ping_ok)
8771      {
8772         if (bd->hung)
8773           {
8774              bd->hung = 0;
8775              edje_object_signal_emit(bd->bg_object, "e,state,unhung", "e");
8776              if (bd->kill_timer)
8777                {
8778                   ecore_timer_del(bd->kill_timer);
8779                   bd->kill_timer = NULL;
8780                }
8781           }
8782      }
8783    else
8784      {
8785         if (!bd->hung)
8786           {
8787              bd->hung = 1;
8788              edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
8789              /* FIXME: if below dialog is up - hide it now */
8790           }
8791         if (bd->delete_requested)
8792           {
8793              /* FIXME: pop up dialog saying app is hung - kill client, or pid */
8794               e_border_act_kill_begin(bd);
8795           }
8796      }
8797    bd->ping_poller = NULL;
8798    e_border_ping(bd);
8799    return ECORE_CALLBACK_CANCEL;
8800 }
8801
8802 static Eina_Bool
8803 _e_border_cb_kill_timer(void *data)
8804 {
8805    E_Border *bd;
8806
8807    bd = data;
8808 // dont wait until it's hung -
8809 //   if (bd->hung)
8810 //     {
8811         if (bd->client.netwm.pid > 1)
8812           kill(bd->client.netwm.pid, SIGKILL);
8813 //     }
8814    bd->kill_timer = NULL;
8815    return ECORE_CALLBACK_CANCEL;
8816 }
8817
8818 static void
8819 _e_border_pointer_resize_begin(E_Border *bd)
8820 {
8821    switch (bd->resize_mode)
8822      {
8823       case RESIZE_TL:
8824         e_pointer_type_push(bd->pointer, bd, "resize_tl");
8825         break;
8826
8827       case RESIZE_T:
8828         e_pointer_type_push(bd->pointer, bd, "resize_t");
8829         break;
8830
8831       case RESIZE_TR:
8832         e_pointer_type_push(bd->pointer, bd, "resize_tr");
8833         break;
8834
8835       case RESIZE_R:
8836         e_pointer_type_push(bd->pointer, bd, "resize_r");
8837         break;
8838
8839       case RESIZE_BR:
8840         e_pointer_type_push(bd->pointer, bd, "resize_br");
8841         break;
8842
8843       case RESIZE_B:
8844         e_pointer_type_push(bd->pointer, bd, "resize_b");
8845         break;
8846
8847       case RESIZE_BL:
8848         e_pointer_type_push(bd->pointer, bd, "resize_bl");
8849         break;
8850
8851       case RESIZE_L:
8852         e_pointer_type_push(bd->pointer, bd, "resize_l");
8853         break;
8854      }
8855 }
8856
8857 static void
8858 _e_border_pointer_resize_end(E_Border *bd)
8859 {
8860    switch (bd->resize_mode)
8861      {
8862       case RESIZE_TL:
8863         e_pointer_type_pop(bd->pointer, bd, "resize_tl");
8864         break;
8865
8866       case RESIZE_T:
8867         e_pointer_type_pop(bd->pointer, bd, "resize_t");
8868         break;
8869
8870       case RESIZE_TR:
8871         e_pointer_type_pop(bd->pointer, bd, "resize_tr");
8872         break;
8873
8874       case RESIZE_R:
8875         e_pointer_type_pop(bd->pointer, bd, "resize_r");
8876         break;
8877
8878       case RESIZE_BR:
8879         e_pointer_type_pop(bd->pointer, bd, "resize_br");
8880         break;
8881
8882       case RESIZE_B:
8883         e_pointer_type_pop(bd->pointer, bd, "resize_b");
8884         break;
8885
8886       case RESIZE_BL:
8887         e_pointer_type_pop(bd->pointer, bd, "resize_bl");
8888         break;
8889
8890       case RESIZE_L:
8891         e_pointer_type_pop(bd->pointer, bd, "resize_l");
8892         break;
8893      }
8894 }
8895
8896 static void
8897 _e_border_pointer_move_begin(E_Border *bd)
8898 {
8899    e_pointer_type_push(bd->pointer, bd, "move");
8900 }
8901
8902 static void
8903 _e_border_pointer_move_end(E_Border *bd)
8904 {
8905    e_pointer_type_pop(bd->pointer, bd, "move");
8906 }
8907
8908 static Eina_List *_e_border_hooks = NULL;
8909 static int _e_border_hooks_delete = 0;
8910 static int _e_border_hooks_walking = 0;
8911
8912 static void
8913 _e_border_hooks_clean(void)
8914 {
8915    Eina_List *l, *ln;
8916    E_Border_Hook *bh;
8917
8918    EINA_LIST_FOREACH_SAFE(_e_border_hooks, l, ln, bh)
8919      {
8920         if (bh->delete_me)
8921           {
8922              _e_border_hooks = eina_list_remove_list(_e_border_hooks, l);
8923              free(bh);
8924           }
8925      }
8926 }
8927
8928 static void
8929 _e_border_hook_call(E_Border_Hook_Point hookpoint,
8930                     void               *bd)
8931 {
8932    Eina_List *l;
8933    E_Border_Hook *bh;
8934
8935    _e_border_hooks_walking++;
8936    EINA_LIST_FOREACH(_e_border_hooks, l, bh)
8937      {
8938         if (bh->delete_me) continue;
8939         if (bh->hookpoint == hookpoint) bh->func(bh->data, bd);
8940      }
8941    _e_border_hooks_walking--;
8942    if ((_e_border_hooks_walking == 0) && (_e_border_hooks_delete > 0))
8943      _e_border_hooks_clean();
8944 }
8945
8946 EAPI E_Border_Hook *
8947 e_border_hook_add(E_Border_Hook_Point               hookpoint,
8948                   void                              (*func)(void *data,
8949                                               void *bd),
8950                   void                             *data)
8951 {
8952    E_Border_Hook *bh;
8953
8954    bh = E_NEW(E_Border_Hook, 1);
8955    if (!bh) return NULL;
8956    bh->hookpoint = hookpoint;
8957    bh->func = func;
8958    bh->data = data;
8959    _e_border_hooks = eina_list_append(_e_border_hooks, bh);
8960    return bh;
8961 }
8962
8963 EAPI void
8964 e_border_hook_del(E_Border_Hook *bh)
8965 {
8966    bh->delete_me = 1;
8967    if (_e_border_hooks_walking == 0)
8968      {
8969         _e_border_hooks = eina_list_remove(_e_border_hooks, bh);
8970         free(bh);
8971      }
8972    else
8973      _e_border_hooks_delete++;
8974 }
8975
8976 EAPI void
8977 e_border_focus_track_freeze(void)
8978 {
8979    focus_track_frozen++;
8980 }
8981
8982 EAPI void
8983 e_border_focus_track_thaw(void)
8984 {
8985    focus_track_frozen--;
8986 }
8987
8988 EAPI E_Border *
8989 e_border_under_pointer_get(E_Desk   *desk,
8990                            E_Border *exclude)
8991 {
8992    E_Border *bd = NULL, *cbd;
8993    Eina_List *l;
8994    int x, y;
8995
8996    /* We need to ensure that we can get the container window for the
8997     * zone of either the given desk or the desk of the excluded
8998     * window, so return if neither is given */
8999    if (desk)
9000      ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
9001    else if (exclude)
9002      ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
9003    else
9004      return NULL;
9005
9006    EINA_LIST_FOREACH(e_border_raise_stack_get(), l, cbd)
9007      {
9008         if (!cbd) continue;
9009         /* If a border was specified which should be excluded from the list
9010          * (because it will be closed shortly for example), skip */
9011         if ((exclude) && (cbd == exclude)) continue;
9012         if ((desk) && (cbd->desk != desk)) continue;
9013         if (!E_INSIDE(x, y, cbd->x, cbd->y, cbd->w, cbd->h))
9014           continue;
9015         /* If the layer is higher, the position of the window is higher
9016          * (always on top vs always below) */
9017         if (!bd || (cbd->layer > bd->layer))
9018           {
9019              bd = cbd;
9020              break;
9021           }
9022      }
9023    return bd;
9024 }
9025
9026 static Eina_Bool
9027 _e_border_pointer_warp_to_center_timer(void *data __UNUSED__)
9028 {
9029    if (warp_to)
9030      {
9031         int x, y;
9032         double spd;
9033
9034         ecore_x_pointer_xy_get(warp_to_win, &x, &y);
9035         if ((x - warp_x) > 5 || (x - warp_x) < -5 ||
9036             (y - warp_y) > 5 || (y - warp_y) < -5)
9037           {
9038              /* User moved the mouse, so stop warping */
9039               warp_to = 0;
9040               goto cleanup;
9041           }
9042
9043         /* We just use the same warp speed as configured
9044          * for the windowlist */
9045         spd = e_config->winlist_warp_speed;
9046         x = warp_x;
9047         y = warp_y;
9048         warp_x = (x * (1.0 - spd)) + (warp_to_x * spd);
9049         warp_y = (y * (1.0 - spd)) + (warp_to_y * spd);
9050         if (warp_x == x && warp_y == y)
9051           {
9052              warp_x = warp_to_x;
9053              warp_y = warp_to_y;
9054              warp_to = 0;
9055              goto cleanup;
9056           }
9057         ecore_x_pointer_warp(warp_to_win, warp_x, warp_y);
9058         return ECORE_CALLBACK_RENEW;
9059      }
9060 cleanup:
9061    ecore_timer_del(warp_timer);
9062    warp_timer = NULL;
9063    return ECORE_CALLBACK_CANCEL;
9064 }
9065
9066 EAPI int
9067 e_border_pointer_warp_to_center(E_Border *bd)
9068 {
9069    int x, y;
9070
9071    /* Do not slide pointer when disabled (probably breaks focus
9072     * on sloppy/mouse focus but requested by users). */
9073    if (!e_config->pointer_slide) return 0;
9074    /* Only warp the pointer if it is not already in the area of
9075     * the given border */
9076    ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
9077    if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
9078        (y >= bd->y) && (y <= (bd->y + bd->h)))
9079      return 0;
9080
9081    warp_to_x = bd->x + (bd->w / 2);
9082    if (warp_to_x < (bd->zone->x + 1))
9083      warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
9084    else if (warp_to_x > (bd->zone->x + bd->zone->w))
9085      warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
9086
9087    warp_to_y = bd->y + (bd->h / 2);
9088    if (warp_to_y < (bd->zone->y + 1))
9089      warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
9090    else if (warp_to_y > (bd->zone->y + bd->zone->h))
9091      warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
9092
9093    warp_to = 1;
9094    warp_to_win = bd->zone->container->win;
9095    ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x, &warp_y);
9096    if (!warp_timer)
9097      warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, (const void *)bd);
9098    return 1;
9099 }
9100
9101 EAPI void
9102 e_border_comp_hidden_set(E_Border *bd,
9103                          Eina_Bool hidden)
9104 {
9105    E_OBJECT_CHECK(bd);
9106    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
9107
9108    if (bd->comp_hidden == hidden) return;
9109
9110    bd->comp_hidden = hidden;
9111
9112    if (bd->comp_hidden)
9113      {
9114         ecore_x_composite_window_events_disable(bd->win);
9115         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
9116      }
9117    else
9118      {
9119         _e_border_shape_input_rectangle_set(bd);
9120         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
9121      }
9122 }
9123 /*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/