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