Disabled the logic of pending show.
[platform/core/uifw/e17.git] / src / bin / e_border.c
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * This file is a modified version of BSD licensed file and
5  * licensed under the Flora License, Version 1.1 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://floralicense.org/license/
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an AS IS BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * Please, see the COPYING file for the original copyright owner and
18  * license.
19  */
20 #include "e.h"
21
22 //#define INOUTDEBUG_MOUSE 1
23 //#define INOUTDEBUG_FOCUS 1
24
25 /* These are compatible with netwm */
26 #define RESIZE_TL   0
27 #define RESIZE_T    1
28 #define RESIZE_TR   2
29 #define RESIZE_R    3
30 #define RESIZE_BR   4
31 #define RESIZE_B    5
32 #define RESIZE_BL   6
33 #define RESIZE_L    7
34 #define MOVE        8
35 #define RESIZE_NONE 11
36
37 /* local subsystem functions */
38 static void _e_border_pri_raise(E_Border *bd);
39 static void _e_border_pri_norm(E_Border *bd);
40 static void _e_border_free(E_Border *bd);
41 static void _e_border_del(E_Border *bd);
42
43 #ifdef PRINT_LOTS_OF_DEBUG
44 #define E_PRINT_BORDER_INFO(X) \
45   _e_border_print(X, __PRETTY_FUNC__)
46
47 static void _e_border_print(E_Border   *bd,
48                             const char *func);
49 #endif
50
51 /* FIXME: these likely belong in a separate icccm/client handler */
52 /* and the border needs to become a dumb object that just does what its */
53 /* told to do */
54 static Eina_Bool _e_border_cb_window_show_request(void *data,
55                                                   int   ev_type,
56                                                   void *ev);
57 static Eina_Bool _e_border_cb_window_destroy(void *data,
58                                              int   ev_type,
59                                              void *ev);
60 static Eina_Bool _e_border_cb_window_hide(void *data,
61                                           int   ev_type,
62                                           void *ev);
63 static Eina_Bool _e_border_cb_window_reparent(void *data,
64                                               int   ev_type,
65                                               void *ev);
66 static Eina_Bool _e_border_cb_window_configure_request(void *data,
67                                                        int   ev_type,
68                                                        void *ev);
69 static Eina_Bool _e_border_cb_window_resize_request(void *data,
70                                                     int   ev_type,
71                                                     void *ev);
72 static Eina_Bool _e_border_cb_window_gravity(void *data,
73                                              int   ev_type,
74                                              void *ev);
75 static Eina_Bool _e_border_cb_window_stack_request(void *data,
76                                                    int   ev_type,
77                                                    void *ev);
78 static Eina_Bool _e_border_cb_window_property(void *data,
79                                               int   ev_type,
80                                               void *ev);
81 static Eina_Bool _e_border_cb_window_colormap(void *data,
82                                               int   ev_type,
83                                               void *ev);
84 static Eina_Bool _e_border_cb_window_shape(void *data,
85                                            int   ev_type,
86                                            void *ev);
87 static Eina_Bool _e_border_cb_window_focus_in(void *data,
88                                               int   ev_type,
89                                               void *ev);
90 static Eina_Bool _e_border_cb_window_focus_out(void *data,
91                                                int   ev_type,
92                                                void *ev);
93 static Eina_Bool _e_border_cb_client_message(void *data,
94                                              int   ev_type,
95                                              void *ev);
96
97 static Eina_Bool _e_border_cb_window_state_request(void *data,
98                                                    int   ev_type,
99                                                    void *ev);
100 static Eina_Bool _e_border_cb_window_move_resize_request(void *data,
101                                                          int   ev_type,
102                                                          void *ev);
103 static Eina_Bool _e_border_cb_desktop_change(void *data,
104                                              int   ev_type,
105                                              void *ev);
106 static Eina_Bool _e_border_cb_sync_alarm(void *data,
107                                          int   ev_type,
108                                          void *ev);
109 static Eina_Bool _e_border_cb_efreet_cache_update(void *data,
110                                                   int   ev_type,
111                                                   void *ev);
112 static Eina_Bool _e_border_cb_config_icon_theme(void *data,
113                                                 int   ev_type,
114                                                 void *ev);
115
116 static Eina_Bool _e_border_cb_pointer_warp(void *data,
117                                            int   ev_type,
118                                            void *ev);
119 static void _e_border_cb_signal_bind(void        *data,
120                                      Evas_Object *obj,
121                                      const char  *emission,
122                                      const char  *source);
123 static Eina_Bool _e_border_cb_mouse_in(void *data,
124                                        int   type,
125                                        void *event);
126 static Eina_Bool _e_border_cb_mouse_out(void *data,
127                                         int   type,
128                                         void *event);
129 static Eina_Bool _e_border_cb_mouse_wheel(void *data,
130                                           int   type,
131                                           void *event);
132 static Eina_Bool _e_border_cb_mouse_down(void *data,
133                                          int   type,
134                                          void *event);
135 static Eina_Bool _e_border_cb_mouse_up(void *data,
136                                        int   type,
137                                        void *event);
138 static Eina_Bool _e_border_cb_mouse_move(void *data,
139                                          int   type,
140                                          void *event);
141 static Eina_Bool _e_border_cb_grab_replay(void *data,
142                                           int   type,
143                                           void *event);
144 static void _e_border_cb_drag_finished(E_Drag *drag,
145                                        int     dropped);
146 #ifdef _F_USE_DESK_WINDOW_PROFILE_
147 static Eina_Bool _e_border_cb_desk_window_profile_change(void *data,
148                                                          int   ev_type,
149                                                          void *ev);
150 #endif
151 #ifdef _F_ZONE_WINDOW_ROTATION_
152 static Eina_Bool _e_border_cb_zone_rotation_change_begin(void *data,
153                                                          int   ev_type,
154                                                          void *ev);
155 static void _e_border_cb_rotation_sync_job(void *data);
156 static void _e_border_cb_rotation_async_job(void *data);
157 static Eina_Bool _e_border_rotation_change_prepare_timeout(void *data);
158 static void      _e_border_rotation_change_request(E_Zone *zone);
159 static void      _e_border_rotation_list_flush(Eina_List *list, Eina_Bool flush);
160 static Eina_Bool _e_border_rotation_change_done_timeout(void *data);
161 static void      _e_border_rotation_change_done(void);
162 static Eina_Bool _e_border_rotation_geom_get(E_Border  *bd,
163                                              E_Zone    *zone,
164                                              int        ang,
165                                              int       *x,
166                                              int       *y,
167                                              int       *w,
168                                              int       *h,
169                                              Eina_Bool *move);
170 static void      _e_border_rotation_list_remove(E_Border *bd);
171 static Eina_Bool _e_border_rotation_pre_resize(E_Border *bd, int rotation, int *x, int *y, int *w, int *h);
172 static int       _e_border_rotation_angle_get(E_Border *bd);
173 static Eina_Bool _e_border_rotation_zone_set(E_Zone *zone);
174 static Eina_Bool _e_border_rotatable_check(E_Border *bd, int ang);
175 static Eina_Bool _e_border_is_vkbd(E_Border *bd);
176 static Eina_Bool _e_border_cb_window_configure(void *data,
177                                                int   ev_type,
178                                                void *ev);
179 static Eina_Bool _e_border_vkbd_show_prepare_timeout(void *data);
180 static Eina_Bool _e_border_vkbd_hide_prepare_timeout(void *data);
181 static void      _e_border_vkbd_show(E_Border *bd);
182 static void      _e_border_vkbd_hide(E_Border *bd);
183 #endif
184 static void      _e_border_move_resize_internal(E_Border *bd,
185                                                 int       x,
186                                                 int       y,
187                                                 int       w,
188                                                 int       h,
189                                                 Eina_Bool without_border,
190                                                 Eina_Bool move);
191
192 static void      _e_border_eval(E_Border *bd);
193 static void      _e_border_eval0(E_Border *bd);
194 static void      _e_border_container_layout_hook(E_Container *con);
195
196 static void      _e_border_moveinfo_gather(E_Border   *bd,
197                                            const char *source);
198 static void      _e_border_resize_handle(E_Border *bd);
199
200 static Eina_Bool _e_border_shade_animator(void *data);
201
202 static void      _e_border_event_border_add_free(void *data,
203                                                  void *ev);
204 static void      _e_border_event_border_remove_free(void *data,
205                                                     void *ev);
206 static void      _e_border_event_border_zone_set_free(void *data,
207                                                       void *ev);
208 static void      _e_border_event_border_desk_set_free(void *data,
209                                                       void *ev);
210 static void      _e_border_event_border_stack_free(void *data,
211                                                    void *ev);
212 static void      _e_border_event_border_icon_change_free(void *data,
213                                                          void *ev);
214 static void      _e_border_event_border_urgent_change_free(void *data,
215                                                            void *ev);
216 static void      _e_border_event_border_focus_in_free(void *data,
217                                                       void *ev);
218 static void      _e_border_event_border_focus_out_free(void *data,
219                                                        void *ev);
220 static void      _e_border_event_border_resize_free(void *data,
221                                                     void *ev);
222 static void      _e_border_event_border_move_free(void *data,
223                                                   void *ev);
224 static void      _e_border_event_border_show_free(void *data,
225                                                   void *ev);
226 static void      _e_border_event_border_hide_free(void *data,
227                                                   void *ev);
228 static void      _e_border_event_border_iconify_free(void *data,
229                                                      void *ev);
230 static void      _e_border_event_border_uniconify_free(void *data,
231                                                        void *ev);
232 static void      _e_border_event_border_stick_free(void *data,
233                                                    void *ev);
234 static void      _e_border_event_border_unstick_free(void *data,
235                                                      void *ev);
236 static void      _e_border_event_border_property_free(void *data,
237                                                       void *ev);
238 static void      _e_border_event_border_fullscreen_free(void *data,
239                                                         void *ev);
240 static void      _e_border_event_border_unfullscreen_free(void *data,
241                                                           void *ev);
242 #ifdef _F_ZONE_WINDOW_ROTATION_
243 static void      _e_border_event_border_rotation_change_begin_free(void *data,
244                                                                    void *ev);
245 static void      _e_border_event_border_rotation_change_cancel_free(void *data,
246                                                                     void *ev);
247 static void      _e_border_event_border_rotation_change_end_free(void *data,
248                                                                  void *ev);
249 static void      _e_border_event_border_rotation_change_begin_send(E_Border *bd);
250 #endif
251
252 static void      _e_border_zone_update(E_Border *bd);
253
254 static int       _e_border_resize_begin(E_Border *bd);
255 static int       _e_border_resize_end(E_Border *bd);
256 static void      _e_border_resize_update(E_Border *bd);
257
258 static int       _e_border_move_begin(E_Border *bd);
259 static int       _e_border_move_end(E_Border *bd);
260 static void      _e_border_move_update(E_Border *bd);
261
262 static Eina_Bool _e_border_cb_ping_poller(void *data);
263 static Eina_Bool _e_border_cb_kill_timer(void *data);
264
265 static void      _e_border_pointer_resize_begin(E_Border *bd);
266 static void      _e_border_pointer_resize_end(E_Border *bd);
267 static void      _e_border_pointer_move_begin(E_Border *bd);
268 static void      _e_border_pointer_move_end(E_Border *bd);
269
270 static void      _e_border_hook_call(E_Border_Hook_Point hookpoint,
271                                      void               *bd);
272
273 static void _e_border_client_move_resize_send(E_Border *bd);
274
275 static void _e_border_frame_replace(E_Border *bd,
276             Eina_Bool argb);
277
278 static void _e_border_shape_input_rectangle_set(E_Border* bd);
279 static void _e_border_show(E_Border *bd);
280 static void _e_border_hide(E_Border *bd);
281
282
283 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
284 static void _e_border_latest_stacked_focus (E_Border* bd);
285 static void _e_border_check_stack (E_Border *bd);
286 static void _e_border_focus_top_stack_set (E_Border* bd);
287 #endif
288 #if _F_BORDER_CLIP_TO_ZONE_
289 static void      _e_border_shape_input_clip_to_zone(E_Border *bd);
290 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
291 /* local subsystem globals */
292 static Eina_List *handlers = NULL;
293 static Eina_List *borders = NULL;
294 static Eina_Hash *borders_hash = NULL;
295 static E_Border *focused = NULL;
296 static E_Border *focusing = NULL;
297 static Eina_List *focus_next = NULL;
298 static Ecore_X_Time focus_time = 0;
299
300 static E_Border *bdresize = NULL;
301 static E_Border *bdmove = NULL;
302 static E_Drag *drag_border = NULL;
303
304 static int grabbed = 0;
305
306 static Eina_List *focus_stack = NULL;
307 static Eina_List *raise_stack = NULL;
308
309 static Ecore_X_Randr_Screen_Size screen_size = { -1, -1 };
310 static int screen_size_index = -1;
311
312 static int focus_track_frozen = 0;
313
314 static int warp_to = 0;
315 static int warp_to_x = 0;
316 static int warp_to_y = 0;
317 static int warp_x = 0;
318 static int warp_y = 0;
319 static Ecore_X_Window warp_to_win;
320 static Ecore_Timer *warp_timer = NULL;
321
322 #ifdef _F_ZONE_WINDOW_ROTATION_
323 typedef struct _E_Border_Rotation      E_Border_Rotation;
324 typedef struct _E_Border_Rotation_Info E_Border_Rotation_Info;
325
326 struct _E_Border_Rotation
327 {
328    Eina_List     *list;
329    Eina_List     *async_list;
330
331    Eina_Bool      wait_prepare_done;
332    Ecore_Timer   *prepare_timer;
333    Ecore_Timer   *done_timer;
334    Ecore_Job     *sync_job;
335    Ecore_Job     *async_job;
336
337    Ecore_X_Window vkbd_ctrl_win;
338    E_Border      *vkbd;
339    E_Border      *vkbd_prediction;
340
341    /* vkbd show/hide preprare */
342    Eina_Bool      vkbd_show_prepare_done;
343    Ecore_Timer   *vkbd_show_prepare_timer;
344    Ecore_Timer   *vkbd_show_timer;
345
346    Eina_Bool      vkbd_hide_prepare_done;
347    Ecore_Timer   *vkbd_hide_prepare_timer;
348    Ecore_Timer   *vkbd_hide_timer;
349
350    Eina_Bool      fetch;
351    Eina_List     *msgs;
352 };
353
354 struct _E_Border_Rotation_Info
355 {
356    int            x, y, w, h;
357    int            ang;
358    E_Border      *bd;
359    Eina_Bool      win_resize;
360 };
361
362 static E_Border_Rotation rot =
363 {
364    NULL,
365    NULL,
366    EINA_FALSE,
367    NULL,
368    NULL,
369    NULL,
370    NULL,
371    0,
372    NULL,
373    NULL,
374    EINA_FALSE,
375    NULL,
376    NULL,
377    EINA_FALSE,
378    NULL,
379    NULL,
380    EINA_FALSE,
381    NULL
382 };
383 #endif
384
385 EAPI int E_EVENT_BORDER_ADD = 0;
386 EAPI int E_EVENT_BORDER_REMOVE = 0;
387 EAPI int E_EVENT_BORDER_ZONE_SET = 0;
388 EAPI int E_EVENT_BORDER_DESK_SET = 0;
389 EAPI int E_EVENT_BORDER_RESIZE = 0;
390 EAPI int E_EVENT_BORDER_MOVE = 0;
391 EAPI int E_EVENT_BORDER_SHOW = 0;
392 EAPI int E_EVENT_BORDER_HIDE = 0;
393 EAPI int E_EVENT_BORDER_ICONIFY = 0;
394 EAPI int E_EVENT_BORDER_UNICONIFY = 0;
395 EAPI int E_EVENT_BORDER_STICK = 0;
396 EAPI int E_EVENT_BORDER_UNSTICK = 0;
397 EAPI int E_EVENT_BORDER_STACK = 0;
398 EAPI int E_EVENT_BORDER_ICON_CHANGE = 0;
399 EAPI int E_EVENT_BORDER_URGENT_CHANGE = 0;
400 EAPI int E_EVENT_BORDER_FOCUS_IN = 0;
401 EAPI int E_EVENT_BORDER_FOCUS_OUT = 0;
402 EAPI int E_EVENT_BORDER_PROPERTY = 0;
403 EAPI int E_EVENT_BORDER_FULLSCREEN = 0;
404 EAPI int E_EVENT_BORDER_UNFULLSCREEN = 0;
405 #ifdef _F_ZONE_WINDOW_ROTATION_
406 EAPI int E_EVENT_BORDER_ROTATION = 0; /* deprecated */
407 EAPI int E_EVENT_BORDER_ROTATION_CHANGE_BEGIN = 0;
408 EAPI int E_EVENT_BORDER_ROTATION_CHANGE_CANCEL = 0;
409 EAPI int E_EVENT_BORDER_ROTATION_CHANGE_END = 0;
410 #endif
411
412 #define GRAV_SET(bd, grav)                                \
413   ecore_x_window_gravity_set(bd->bg_win, grav);           \
414   ecore_x_window_gravity_set(bd->client.shell_win, grav); \
415   ecore_x_window_gravity_set(bd->client.win, grav);
416
417 static Eina_List *
418 _e_border_sub_borders_new(E_Border *bd)
419 {
420    Eina_List *list = NULL, *l;
421    E_Border *child;
422    E_Border_List *bl;
423
424    EINA_LIST_FOREACH(bd->transients, l, child)
425      {
426         if (!eina_list_data_find(list, child))
427           list = eina_list_append(list, child);
428      }
429    bl = e_container_border_list_first(bd->zone->container);
430    while ((child = e_container_border_list_next(bl)))
431      {
432         if (e_object_is_del(E_OBJECT(child))) continue;
433         if (child == bd) continue;
434 /*
435         if ((bd->client.icccm.client_leader) &&
436             (child->client.icccm.client_leader ==
437                 bd->client.icccm.client_leader))
438           {
439              printf("bd %s in group with %s\n",
440                     e_border_name_get(child),
441                     e_border_name_get(bd));
442              if (!eina_list_data_find(list, child))
443                list = eina_list_append(list, child);
444           }
445  */
446      }
447    e_container_border_list_free(bl);
448    return list;
449 }
450
451 /* externally accessible functions */
452 EINTERN int
453 e_border_init(void)
454 {
455    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW_REQUEST, _e_border_cb_window_show_request, NULL));
456    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _e_border_cb_window_destroy, NULL));
457    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, _e_border_cb_window_hide, NULL));
458    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_REPARENT, _e_border_cb_window_reparent, NULL));
459    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST, _e_border_cb_window_configure_request, NULL));
460    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_RESIZE_REQUEST, _e_border_cb_window_resize_request, NULL));
461    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_GRAVITY, _e_border_cb_window_gravity, NULL));
462    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_STACK_REQUEST, _e_border_cb_window_stack_request, NULL));
463    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, _e_border_cb_window_property, NULL));
464    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_COLORMAP, _e_border_cb_window_colormap, NULL));
465    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHAPE, _e_border_cb_window_shape, NULL));
466    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, _e_border_cb_window_focus_in, NULL));
467    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, _e_border_cb_window_focus_out, NULL));
468    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _e_border_cb_client_message, NULL));
469    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, _e_border_cb_window_state_request, NULL));
470    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST, _e_border_cb_window_move_resize_request, NULL));
471    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_DESKTOP_CHANGE, _e_border_cb_desktop_change, NULL));
472    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_SYNC_ALARM, _e_border_cb_sync_alarm, NULL));
473 #ifdef _F_ZONE_WINDOW_ROTATION_
474    handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE, _e_border_cb_window_configure, NULL));
475 #endif
476
477    ecore_x_passive_grab_replay_func_set(_e_border_cb_grab_replay, NULL);
478
479    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_POINTER_WARP, _e_border_cb_pointer_warp, NULL));
480    handlers = eina_list_append(handlers, ecore_event_handler_add(EFREET_EVENT_DESKTOP_CACHE_UPDATE, _e_border_cb_efreet_cache_update, NULL));
481    handlers = eina_list_append(handlers, ecore_event_handler_add(EFREET_EVENT_ICON_CACHE_UPDATE, _e_border_cb_efreet_cache_update, NULL));
482    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_CONFIG_ICON_THEME, _e_border_cb_config_icon_theme, NULL));
483 #ifdef _F_USE_DESK_WINDOW_PROFILE_
484    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_DESK_WINDOW_PROFILE_CHANGE, _e_border_cb_desk_window_profile_change, NULL));
485 #endif
486 #ifdef _F_ZONE_WINDOW_ROTATION_
487    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_ZONE_ROTATION_CHANGE_BEGIN, _e_border_cb_zone_rotation_change_begin, NULL));
488 #endif
489
490    if (!borders_hash) borders_hash = eina_hash_string_superfast_new(NULL);
491
492    E_EVENT_BORDER_ADD = ecore_event_type_new();
493    E_EVENT_BORDER_REMOVE = ecore_event_type_new();
494    E_EVENT_BORDER_DESK_SET = ecore_event_type_new();
495    E_EVENT_BORDER_ZONE_SET = ecore_event_type_new();
496    E_EVENT_BORDER_RESIZE = ecore_event_type_new();
497    E_EVENT_BORDER_MOVE = ecore_event_type_new();
498    E_EVENT_BORDER_SHOW = ecore_event_type_new();
499    E_EVENT_BORDER_HIDE = ecore_event_type_new();
500    E_EVENT_BORDER_ICONIFY = ecore_event_type_new();
501    E_EVENT_BORDER_UNICONIFY = ecore_event_type_new();
502    E_EVENT_BORDER_STICK = ecore_event_type_new();
503    E_EVENT_BORDER_UNSTICK = ecore_event_type_new();
504    E_EVENT_BORDER_STACK = ecore_event_type_new();
505    E_EVENT_BORDER_ICON_CHANGE = ecore_event_type_new();
506    E_EVENT_BORDER_URGENT_CHANGE = ecore_event_type_new();
507    E_EVENT_BORDER_FOCUS_IN = ecore_event_type_new();
508    E_EVENT_BORDER_FOCUS_OUT = ecore_event_type_new();
509    E_EVENT_BORDER_PROPERTY = ecore_event_type_new();
510    E_EVENT_BORDER_FULLSCREEN = ecore_event_type_new();
511    E_EVENT_BORDER_UNFULLSCREEN = ecore_event_type_new();
512 #ifdef _F_ZONE_WINDOW_ROTATION_
513    E_EVENT_BORDER_ROTATION = ecore_event_type_new(); /* deprecated */
514    E_EVENT_BORDER_ROTATION_CHANGE_BEGIN = ecore_event_type_new();
515    E_EVENT_BORDER_ROTATION_CHANGE_CANCEL = ecore_event_type_new();
516    E_EVENT_BORDER_ROTATION_CHANGE_END = ecore_event_type_new();
517 #endif
518
519 //   e_init_undone();
520
521    return 1;
522 }
523
524 EINTERN int
525 e_border_shutdown(void)
526 {
527    E_FREE_LIST(handlers, ecore_event_handler_del);
528
529    if (borders_hash) eina_hash_free(borders_hash);
530    borders_hash = NULL;
531    e_int_border_menu_hooks_clear();
532
533    return 1;
534 }
535
536 EAPI E_Border *
537 e_border_new(E_Container   *con,
538              Ecore_X_Window win,
539              int            first_map,
540              int            internal)
541 {
542    E_Border *bd, *bd2;
543    Ecore_X_Window_Attributes *att;
544    unsigned int managed, desk[2];
545    int deskx, desky;
546
547    bd = E_OBJECT_ALLOC(E_Border, E_BORDER_TYPE, _e_border_free);
548    if (!bd) return NULL;
549    ecore_x_window_shadow_tree_flush();
550    e_object_del_func_set(E_OBJECT(bd), E_OBJECT_CLEANUP_FUNC(_e_border_del));
551
552    bd->w = 1;
553    bd->h = 1;
554    /* FIXME: ewww - round trip */
555    bd->client.argb = ecore_x_window_argb_get(win);
556    if (bd->client.argb)
557      bd->win = ecore_x_window_manager_argb_new(con->win, 0, 0, bd->w, bd->h);
558    else
559      {
560         bd->win = ecore_x_window_override_new(con->win, 0, 0, bd->w, bd->h);
561         ecore_x_window_shape_events_select(bd->win, 1);
562      }
563    e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
564    e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
565    e_focus_setup(bd);
566    bd->bg_ecore_evas = e_canvas_new(bd->win,
567                                     0, 0, bd->w, bd->h, 1, 0,
568                                     &(bd->bg_win));
569    ecore_evas_ignore_events_set(bd->bg_ecore_evas, EINA_TRUE);
570    e_canvas_add(bd->bg_ecore_evas);
571    bd->event_win = ecore_x_window_input_new(bd->win, 0, 0, bd->w, bd->h);
572    bd->bg_evas = ecore_evas_get(bd->bg_ecore_evas);
573    ecore_x_window_shape_events_select(bd->bg_win, 1);
574    ecore_evas_name_class_set(bd->bg_ecore_evas, "E", "Frame_Window");
575    ecore_evas_title_set(bd->bg_ecore_evas, "Enlightenment Frame");
576    if (bd->client.argb)
577      bd->client.shell_win = ecore_x_window_manager_argb_new(bd->win, 0, 0, 1, 1);
578    else
579      bd->client.shell_win = ecore_x_window_override_new(bd->win, 0, 0, 1, 1);
580    ecore_x_window_container_manage(bd->client.shell_win);
581    if (!internal) ecore_x_window_client_manage(win);
582    /* FIXME: Round trip. XCB */
583    /* fetch needed to avoid grabbing the server as window may vanish */
584    att = &bd->client.initial_attributes;
585    if ((!ecore_x_window_attributes_get(win, att)) || (att->input_only))
586      {
587         //      printf("##- ATTR FETCH FAILED/INPUT ONLY FOR 0x%x - ABORT MANAGE\n", win);
588           e_canvas_del(bd->bg_ecore_evas);
589           ecore_evas_free(bd->bg_ecore_evas);
590           ecore_x_window_free(bd->client.shell_win);
591           e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
592           e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
593           ecore_x_window_free(bd->win);
594           free(bd);
595           return NULL;
596      }
597
598    /* printf("##- ON MAP CLIENT 0x%x SIZE %ix%i %i:%i\n",
599     *     bd->client.win, bd->client.w, bd->client.h, att->x, att->y); */
600
601    /* FIXME: if first_map is 1 then we should ignore the first hide event
602     * or ensure the window is already hidden and events flushed before we
603     * create a border for it */
604    if (first_map)
605      {
606         // printf("##- FIRST MAP\n");
607           bd->x = att->x;
608           bd->y = att->y;
609           bd->changes.pos = 1;
610           bd->re_manage = 1;
611           // needed to be 1 for internal windw and on restart.
612           // bd->ignore_first_unmap = 2;
613      }
614
615    bd->client.win = win;
616    bd->zone = e_zone_current_get(con);
617
618    _e_border_hook_call(E_BORDER_HOOK_NEW_BORDER, bd);
619
620    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_X_EVENT_MOUSE_IN, _e_border_cb_mouse_in, bd));
621    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_X_EVENT_MOUSE_OUT, _e_border_cb_mouse_out, bd));
622    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_cb_mouse_down, bd));
623    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, _e_border_cb_mouse_up, bd));
624    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, _e_border_cb_mouse_move, bd));
625    bd->handlers = eina_list_append(bd->handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL, _e_border_cb_mouse_wheel, bd));
626
627    bd->client.icccm.title = NULL;
628    bd->client.icccm.name = NULL;
629    bd->client.icccm.class = NULL;
630    bd->client.icccm.icon_name = NULL;
631    bd->client.icccm.machine = NULL;
632    bd->client.icccm.min_w = 1;
633    bd->client.icccm.min_h = 1;
634    bd->client.icccm.max_w = 32767;
635    bd->client.icccm.max_h = 32767;
636    bd->client.icccm.base_w = 0;
637    bd->client.icccm.base_h = 0;
638    bd->client.icccm.step_w = -1;
639    bd->client.icccm.step_h = -1;
640    bd->client.icccm.min_aspect = 0.0;
641    bd->client.icccm.max_aspect = 0.0;
642    bd->client.icccm.accepts_focus = 1;
643
644    bd->client.netwm.pid = 0;
645    bd->client.netwm.name = NULL;
646    bd->client.netwm.icon_name = NULL;
647    bd->client.netwm.desktop = 0;
648    bd->client.netwm.state.modal = 0;
649    bd->client.netwm.state.sticky = 0;
650    bd->client.netwm.state.shaded = 0;
651    bd->client.netwm.state.hidden = 0;
652    bd->client.netwm.state.maximized_v = 0;
653    bd->client.netwm.state.maximized_h = 0;
654    bd->client.netwm.state.skip_taskbar = 0;
655    bd->client.netwm.state.skip_pager = 0;
656    bd->client.netwm.state.fullscreen = 0;
657    bd->client.netwm.state.stacking = E_STACKING_NONE;
658    bd->client.netwm.action.move = 0;
659    bd->client.netwm.action.resize = 0;
660    bd->client.netwm.action.minimize = 0;
661    bd->client.netwm.action.shade = 0;
662    bd->client.netwm.action.stick = 0;
663    bd->client.netwm.action.maximized_h = 0;
664    bd->client.netwm.action.maximized_v = 0;
665    bd->client.netwm.action.fullscreen = 0;
666    bd->client.netwm.action.change_desktop = 0;
667    bd->client.netwm.action.close = 0;
668    bd->client.netwm.type = ECORE_X_WINDOW_TYPE_UNKNOWN;
669
670    {
671       int at_num = 0, i;
672       Ecore_X_Atom *atoms;
673
674       atoms = ecore_x_window_prop_list(bd->client.win, &at_num);
675       bd->client.icccm.fetch.command = 1;
676       if (atoms)
677         {
678            Eina_Bool video_parent = EINA_FALSE;
679            Eina_Bool video_position = EINA_FALSE;
680
681            /* icccm */
682             for (i = 0; i < at_num; i++)
683               {
684                  if (atoms[i] == ECORE_X_ATOM_WM_NAME)
685                    bd->client.icccm.fetch.title = 1;
686                  else if (atoms[i] == ECORE_X_ATOM_WM_CLASS)
687                    bd->client.icccm.fetch.name_class = 1;
688                  else if (atoms[i] == ECORE_X_ATOM_WM_ICON_NAME)
689                    bd->client.icccm.fetch.icon_name = 1;
690                  else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_MACHINE)
691                    bd->client.icccm.fetch.machine = 1;
692                  else if (atoms[i] == ECORE_X_ATOM_WM_HINTS)
693                    bd->client.icccm.fetch.hints = 1;
694                  else if (atoms[i] == ECORE_X_ATOM_WM_NORMAL_HINTS)
695                    bd->client.icccm.fetch.size_pos_hints = 1;
696                  else if (atoms[i] == ECORE_X_ATOM_WM_PROTOCOLS)
697                    bd->client.icccm.fetch.protocol = 1;
698                  else if (atoms[i] == ECORE_X_ATOM_MOTIF_WM_HINTS)
699                    bd->client.mwm.fetch.hints = 1;
700                  else if (atoms[i] == ECORE_X_ATOM_WM_TRANSIENT_FOR)
701                    {
702                       bd->client.icccm.fetch.transient_for = 1;
703                       bd->client.netwm.fetch.type = 1;
704                    }
705                  else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_LEADER)
706                    bd->client.icccm.fetch.client_leader = 1;
707                  else if (atoms[i] == ECORE_X_ATOM_WM_WINDOW_ROLE)
708                    bd->client.icccm.fetch.window_role = 1;
709                  else if (atoms[i] == ECORE_X_ATOM_WM_STATE)
710                    bd->client.icccm.fetch.state = 1;
711               }
712             /* netwm, loop again, netwm will ignore some icccm, so we
713              * have to be sure that netwm is checked after */
714             for (i = 0; i < at_num; i++)
715               {
716                  if (atoms[i] == ECORE_X_ATOM_NET_WM_NAME)
717                    {
718      /* Ignore icccm */
719                        bd->client.icccm.fetch.title = 0;
720                        bd->client.netwm.fetch.name = 1;
721                    }
722                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON_NAME)
723                    {
724      /* Ignore icccm */
725                        bd->client.icccm.fetch.icon_name = 0;
726                        bd->client.netwm.fetch.icon_name = 1;
727                    }
728                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON)
729                    {
730                       bd->client.netwm.fetch.icon = 1;
731                    }
732                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_USER_TIME)
733                    {
734                       bd->client.netwm.fetch.user_time = 1;
735                    }
736                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT)
737                    {
738                       DBG("ECORE_X_ATOM_NET_WM_STRUT");
739                       bd->client.netwm.fetch.strut = 1;
740                    }
741                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
742                    {
743                       DBG("ECORE_X_ATOM_NET_WM_STRUT_PARTIAL");
744                       bd->client.netwm.fetch.strut = 1;
745                    }
746                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_WINDOW_TYPE)
747                    {
748      /* Ignore mwm
749         bd->client.mwm.fetch.hints = 0;
750       */
751                         bd->client.netwm.fetch.type = 1;
752                    }
753                  else if (atoms[i] == ECORE_X_ATOM_NET_WM_STATE)
754                    {
755                       bd->client.netwm.fetch.state = 1;
756                    }
757               }
758             /* other misc atoms */
759             for (i = 0; i < at_num; i++)
760               {
761      /* loop to check for own atoms */
762                   if (atoms[i] == E_ATOM_WINDOW_STATE)
763                     {
764                        bd->client.e.fetch.state = 1;
765                     }
766      /* loop to check for qtopia atoms */
767                   if (atoms[i] == ATM__QTOPIA_SOFT_MENU)
768                     bd->client.qtopia.fetch.soft_menu = 1;
769                   else if (atoms[i] == ATM__QTOPIA_SOFT_MENUS)
770                     bd->client.qtopia.fetch.soft_menus = 1;
771      /* loop to check for vkbd atoms */
772                   else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
773                     bd->client.vkbd.fetch.state = 1;
774                   else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
775                     bd->client.vkbd.fetch.vkbd = 1;
776      /* loop to check for illume atoms */
777                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
778                     bd->client.illume.conformant.fetch.conformant = 1;
779                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
780                     bd->client.illume.quickpanel.fetch.state = 1;
781                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
782                     bd->client.illume.quickpanel.fetch.quickpanel = 1;
783                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
784                     bd->client.illume.quickpanel.fetch.priority.major = 1;
785                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
786                     bd->client.illume.quickpanel.fetch.priority.minor = 1;
787                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
788                     bd->client.illume.quickpanel.fetch.zone = 1;
789                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
790                     bd->client.illume.drag.fetch.locked = 1;
791                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG)
792                     bd->client.illume.drag.fetch.drag = 1;
793                   else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
794                     bd->client.illume.win_state.fetch.state = 1;
795                   else if (atoms[i] == ECORE_X_ATOM_E_VIDEO_PARENT)
796                     video_parent = EINA_TRUE;
797                   else if (atoms[i] == ECORE_X_ATOM_E_VIDEO_POSITION)
798                     video_position = EINA_TRUE;
799 #ifdef _F_USE_DESK_WINDOW_PROFILE_
800      /* loop to check for window profile list atom */
801                   else if (atoms[i] == ECORE_X_ATOM_E_PROFILE_LIST)
802                     bd->client.e.fetch.profile_list = 1;
803 #endif
804 #ifdef _F_ZONE_WINDOW_ROTATION_
805                   /* loop to check for wm rotation */
806                   else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED)
807                     {
808                        if (e_config->wm_win_rotation)
809                          bd->client.e.fetch.rot.support = 1;
810                     }
811                   else if ((atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_0_GEOMETRY) ||
812                            (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_90_GEOMETRY) ||
813                            (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_180_GEOMETRY) ||
814                            (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_270_GEOMETRY))
815                     {
816                        if (e_config->wm_win_rotation)
817                          bd->client.e.fetch.rot.geom_hint = 1;
818                     }
819                   else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED)
820                     {
821                        if (e_config->wm_win_rotation)
822                          bd->client.e.fetch.rot.app_set = 1;
823                     }
824                   else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION)
825                     {
826                        if (e_config->wm_win_rotation)
827                          bd->client.e.fetch.rot.preferred_rot = 1;
828                     }
829                   else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST)
830                     {
831                        if (e_config->wm_win_rotation)
832                          bd->client.e.fetch.rot.available_rots = 1;
833                     }
834 #endif
835 #ifdef _F_DEICONIFY_APPROVE_
836                   else if (atoms[i] == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
837                     {
838                        bd->client.e.state.deiconify_approve.support = 1;
839                     }
840 #endif
841               }
842             if (video_position && video_parent)
843               {
844                  bd->client.e.state.video = 1;
845                  bd->client.e.fetch.video_parent = 1;
846                  bd->client.e.fetch.video_position = 1;
847                  ecore_x_window_lower(bd->win);
848                  ecore_x_composite_window_events_disable(bd->win);
849                  ecore_x_window_ignore_set(bd->win, EINA_TRUE);
850                  fprintf(stderr, "We found a video window \\o/ %x\n", win);
851               }
852             free(atoms);
853         }
854    }
855    bd->client.border.changed = 1;
856
857    bd->client.w = att->w;
858    bd->client.h = att->h;
859
860    bd->w = bd->client.w;
861    bd->h = bd->client.h;
862
863    bd->resize_mode = RESIZE_NONE;
864    bd->layer = 100;
865    bd->saved.layer = bd->layer;
866    bd->changes.icon = 1;
867    bd->changes.size = 1;
868    bd->changes.shape = 1;
869    bd->changes.shape_input = 1;
870
871    bd->offer_resistance = 1;
872
873    /* just to friggin make java happy - we're DELAYING the reparent until
874     * eval time...
875     */
876 /*   ecore_x_window_reparent(win, bd->client.shell_win, 0, 0); */
877    bd->need_reparent = 1;
878
879    ecore_x_window_border_width_set(win, 0);
880    ecore_x_window_show(bd->event_win);
881    ecore_x_window_show(bd->client.shell_win);
882    bd->shape = e_container_shape_add(con);
883
884    bd->take_focus = 1;
885    bd->new_client = 1;
886    bd->changed = 1;
887 #ifdef _F_ZONE_WINDOW_ROTATION_
888    bd->client.e.state.rot.preferred_rot = -1;
889    bd->client.e.state.rot.type = E_BORDER_ROTATION_TYPE_NORMAL;
890    bd->client.e.state.rot.changes = -1;
891    bd->client.e.state.rot.pending_show = 0;
892    bd->client.e.state.rot.curr = 0;
893    bd->client.e.state.rot.prev = 0;
894 #endif
895
896 //   bd->zone = e_zone_current_get(con);
897    bd->desk = e_desk_current_get(bd->zone);
898    e_container_border_add(bd);
899    borders = eina_list_append(borders, bd);
900    bd2 = eina_hash_find(borders_hash, e_util_winid_str_get(bd->client.win));
901    if (bd2)
902      {
903 #ifdef E_LOGGING
904         WRN("EEEEK! 2 borders with same client window id in them! very bad!\n"
905             "optimisations failing due to bizarre client behavior. will\n"
906             "work around.\n"
907             "bd=%p, bd->references=%i, bd->deleted=%i, bd->client.win=%x",
908                bd2, bd2->e_obj_inherit.references, bd2->e_obj_inherit.deleted,
909                bd2->client.win);
910
911         ELBF(ELBT_BD, 0, bd->client.win,
912              "ERR! 2 borders with same client win id in them! bd:%p ref:%i deleted:%i",
913              bd2, bd2->e_obj_inherit.references, bd2->e_obj_inherit.deleted);
914 #else
915         printf("EEEEK! 2 borders with same client window id in them! very bad!\n");
916         printf("optimisations failing due to bizarre client behavior. will\n");
917         printf("work around.\n");
918         printf("bd=%p, bd->references=%i, bd->deleted=%i, bd->client.win=%x\n",
919                bd2, bd2->e_obj_inherit.references, bd2->e_obj_inherit.deleted,
920                bd2->client.win);
921
922         ELBF(ELBT_BD, 0, bd->client.win,
923              "ERR! 2 borders with same client win id in them! bd:%p ref:%i deleted:%i",
924              bd2, bd2->e_obj_inherit.references, bd2->e_obj_inherit.deleted);
925 #endif
926
927 #ifdef _F_ZONE_WINDOW_ROTATION_
928         if ((rot.vkbd) && (rot.vkbd == bd2))
929           {
930              ELB(ELBT_BD, "UNSET VKBD", rot.vkbd->client.win);
931              ELBF(ELBT_BD, 1, rot.vkbd->client.win, "VKBD HIDE PREPARE_DONE:%d",
932                   rot.vkbd_hide_prepare_done);
933
934              if (rot.vkbd_hide_prepare_timer)
935                {
936                   ecore_timer_del(rot.vkbd_hide_prepare_timer);
937                   rot.vkbd_hide_prepare_timer = NULL;
938
939                   e_object_unref(E_OBJECT(bd2));
940                }
941
942              _e_border_vkbd_hide(rot.vkbd);
943
944              if (rot.vkbd_ctrl_win)
945                {
946                   ELB(ELBT_BD, "SET KBD_OFF", 0);
947                   ecore_x_e_virtual_keyboard_state_set
948                      (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
949                }
950              rot.vkbd_hide_prepare_done = EINA_FALSE;
951
952              if (rot.vkbd_hide_timer)
953                ecore_timer_del(rot.vkbd_hide_timer);
954              rot.vkbd_hide_timer = NULL;
955
956              rot.vkbd_show_prepare_done = EINA_FALSE;
957              if (rot.vkbd_show_prepare_timer)
958                ecore_timer_del(rot.vkbd_show_prepare_timer);
959              rot.vkbd_show_prepare_timer = NULL;
960              if (rot.vkbd_show_timer)
961                ecore_timer_del(rot.vkbd_show_timer);
962              rot.vkbd_show_timer = NULL;
963
964              rot.vkbd = NULL;
965           }
966 #endif
967         eina_hash_del(borders_hash, e_util_winid_str_get(bd->client.win), bd2);
968         eina_hash_del(borders_hash, e_util_winid_str_get(bd2->bg_win), bd2);
969         eina_hash_del(borders_hash, e_util_winid_str_get(bd2->win), bd2);
970      }
971    eina_hash_add(borders_hash, e_util_winid_str_get(bd->client.win), bd);
972    eina_hash_add(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
973    eina_hash_add(borders_hash, e_util_winid_str_get(bd->win), bd);
974    managed = 1;
975    ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &managed, 1);
976    ecore_x_window_prop_card32_set(win, E_ATOM_CONTAINER, &bd->zone->container->num, 1);
977    ecore_x_window_prop_card32_set(win, E_ATOM_ZONE, &bd->zone->num, 1);
978      {
979         unsigned int zgeom[4];
980         
981         zgeom[0] = bd->zone->x;
982         zgeom[1] = bd->zone->y;
983         zgeom[2] = bd->zone->w;
984         zgeom[3] = bd->zone->h;
985         ecore_x_window_prop_card32_set(win, E_ATOM_ZONE_GEOMETRY, zgeom, 4);
986      }
987    e_desk_xy_get(bd->desk, &deskx, &desky);
988    desk[0] = deskx;
989    desk[1] = desky;
990    ecore_x_window_prop_card32_set(win, E_ATOM_DESK, desk, 2);
991 #ifdef _F_USE_DESK_WINDOW_PROFILE_
992    if (strcmp(bd->desk->window_profile,
993               e_config->desktop_default_window_profile) != 0)
994      {
995         ecore_x_e_window_profile_set(bd->client.win,
996                                      bd->desk->window_profile);
997      }
998 #endif
999
1000    focus_stack = eina_list_append(focus_stack, bd);
1001
1002    bd->pointer = e_pointer_window_new(bd->win, 0);
1003    return bd;
1004 }
1005
1006 EAPI void
1007 e_border_res_change_geometry_save(E_Border *bd)
1008 {
1009    E_OBJECT_CHECK(bd);
1010    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1011
1012    if (bd->pre_res_change.valid) return;
1013    bd->pre_res_change.valid = 1;
1014    bd->pre_res_change.x = bd->x;
1015    bd->pre_res_change.y = bd->y;
1016    bd->pre_res_change.w = bd->w;
1017    bd->pre_res_change.h = bd->h;
1018    bd->pre_res_change.saved.x = bd->saved.x;
1019    bd->pre_res_change.saved.y = bd->saved.y;
1020    bd->pre_res_change.saved.w = bd->saved.w;
1021    bd->pre_res_change.saved.h = bd->saved.h;
1022 }
1023
1024 EAPI void
1025 e_border_res_change_geometry_restore(E_Border *bd)
1026 {
1027    struct
1028    {
1029       unsigned char valid : 1;
1030       int           x, y, w, h;
1031       struct
1032       {
1033          int x, y, w, h;
1034       } saved;
1035    } pre_res_change;
1036
1037    E_OBJECT_CHECK(bd);
1038    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1039    if (!bd->pre_res_change.valid) return;
1040    if (bd->new_client) return;
1041
1042    ecore_x_window_shadow_tree_flush();
1043    memcpy(&pre_res_change, &bd->pre_res_change, sizeof(pre_res_change));
1044
1045    if (bd->fullscreen)
1046      {
1047         e_border_unfullscreen(bd);
1048         e_border_fullscreen(bd, e_config->fullscreen_policy);
1049      }
1050    else if (bd->maximized != E_MAXIMIZE_NONE)
1051      {
1052         E_Maximize max;
1053
1054         max = bd->maximized;
1055         e_border_unmaximize(bd, E_MAXIMIZE_BOTH);
1056         e_border_maximize(bd, max);
1057      }
1058    else
1059      {
1060         int x, y, w, h, zx, zy, zw, zh;
1061
1062         bd->saved.x = bd->pre_res_change.saved.x;
1063         bd->saved.y = bd->pre_res_change.saved.y;
1064         bd->saved.w = bd->pre_res_change.saved.w;
1065         bd->saved.h = bd->pre_res_change.saved.h;
1066
1067         e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
1068
1069         if (bd->saved.w > zw)
1070           bd->saved.w = zw;
1071         if ((bd->saved.x + bd->saved.w) > (zx + zw))
1072           bd->saved.x = zx + zw - bd->saved.w;
1073
1074         if (bd->saved.h > zh)
1075           bd->saved.h = zh;
1076         if ((bd->saved.y + bd->saved.h) > (zy + zh))
1077           bd->saved.y = zy + zh - bd->saved.h;
1078
1079         x = bd->pre_res_change.x;
1080         y = bd->pre_res_change.y;
1081         w = bd->pre_res_change.w;
1082         h = bd->pre_res_change.h;
1083         if (w > zw)
1084           w = zw;
1085         if (h > zh)
1086           h = zh;
1087         if ((x + w) > (zx + zw))
1088           x = zx + zw - w;
1089         if ((y + h) > (zy + zh))
1090           y = zy + zh - h;
1091         e_border_move_resize(bd, x, y, w, h);
1092      }
1093    memcpy(&bd->pre_res_change, &pre_res_change, sizeof(pre_res_change));
1094 }
1095
1096 EAPI void
1097 e_border_zone_set(E_Border *bd,
1098                   E_Zone   *zone)
1099 {
1100    E_Event_Border_Zone_Set *ev;
1101
1102    E_OBJECT_CHECK(bd);
1103    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1104    E_OBJECT_CHECK(zone);
1105    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
1106    if (!zone) return;
1107    if (bd->zone == zone) return;
1108
1109    /* if the window does not lie in the new zone, move it so that it does */
1110    if (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))
1111      {
1112         int x, y;
1113         /* first guess -- get offset from old zone, and apply to new zone */
1114         x = zone->x + (bd->x - bd->zone->x);
1115         y = zone->y + (bd->y - bd->zone->y);
1116
1117         /* keep window from hanging off bottom and left */
1118         if (x + bd->w > zone->x + zone->w) x += (zone->x + zone->w) - (x + bd->w);
1119         if (y + bd->h > zone->y + zone->h) y += (zone->y + zone->h) - (y + bd->h);
1120
1121         /* make sure to and left are on screen (if the window is larger than the zone, it will hang off the bottom / right) */
1122         if (x < zone->x) x = zone->x;
1123         if (y < zone->y) y = zone->y;
1124
1125         if (!E_INTERSECTS(x, y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))
1126           {
1127              /* still not in zone at all, so just move it to closest edge */
1128               if (x < zone->x) x = zone->x;
1129               if (x >= zone->x + zone->w) x = zone->x + zone->w - bd->w;
1130               if (y < zone->y) y = zone->y;
1131               if (y >= zone->y + zone->h) y = zone->y + zone->h - bd->h;
1132           }
1133         e_border_move(bd, x, y);
1134      }
1135
1136    bd->zone = zone;
1137
1138    if (bd->desk->zone != bd->zone)
1139      e_border_desk_set(bd, e_desk_current_get(bd->zone));
1140
1141    ev = E_NEW(E_Event_Border_Zone_Set, 1);
1142    ev->border = bd;
1143    e_object_ref(E_OBJECT(bd));
1144 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_zone_set_event");
1145    ev->zone = zone;
1146    e_object_ref(E_OBJECT(zone));
1147
1148    ecore_event_add(E_EVENT_BORDER_ZONE_SET, ev, _e_border_event_border_zone_set_free, NULL);
1149
1150    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_ZONE, &bd->zone->num, 1);
1151    // XXXXXXXXXXXXXXXXXXXXXXXXX
1152    // XXX ZZZZZZZZZZZZZZZZZZZzz
1153    // need to adjust this if zone pos/size changes
1154      {
1155         unsigned int zgeom[4];
1156         
1157         zgeom[0] = bd->zone->x;
1158         zgeom[1] = bd->zone->y;
1159         zgeom[2] = bd->zone->w;
1160         zgeom[3] = bd->zone->h;
1161         ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_ZONE_GEOMETRY, zgeom, 4);
1162      }
1163    e_remember_update(bd);
1164 }
1165
1166 EAPI void
1167 e_border_desk_set(E_Border *bd,
1168                   E_Desk   *desk)
1169 {
1170    E_Event_Border_Desk_Set *ev;
1171    E_Desk *old_desk;
1172
1173    E_OBJECT_CHECK(bd);
1174    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1175    E_OBJECT_CHECK(desk);
1176    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
1177    if (bd->desk == desk) return;
1178    ecore_x_window_shadow_tree_flush();
1179    if (bd->fullscreen)
1180      {
1181         bd->desk->fullscreen_borders--;
1182         desk->fullscreen_borders++;
1183      }
1184    old_desk = bd->desk;
1185    bd->desk = desk;
1186    e_border_zone_set(bd, desk->zone);
1187
1188    _e_border_hook_call(E_BORDER_HOOK_SET_DESK, bd);
1189    e_hints_window_desktop_set(bd);
1190
1191    ev = E_NEW(E_Event_Border_Desk_Set, 1);
1192    ev->border = bd;
1193    e_object_ref(E_OBJECT(bd));
1194 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_desk_set_event");
1195    ev->desk = old_desk;
1196    e_object_ref(E_OBJECT(old_desk));
1197    ecore_event_add(E_EVENT_BORDER_DESK_SET, ev, _e_border_event_border_desk_set_free, NULL);
1198
1199    if (bd->ignore_first_unmap != 1)
1200      {
1201         if ((bd->desk->visible) || (bd->sticky))
1202           e_border_show(bd);
1203         else
1204           e_border_hide(bd, 1);
1205      }
1206
1207    if (e_config->transient.desktop)
1208      {
1209         Eina_List *l;
1210         E_Border *child;
1211         Eina_List *list = _e_border_sub_borders_new(bd);
1212
1213         EINA_LIST_FOREACH(list, l, child)
1214           {
1215              e_border_desk_set(child, bd->desk);
1216           }
1217         eina_list_free(list);
1218      }
1219    e_remember_update(bd);
1220 }
1221
1222 #ifdef _F_ZONE_WINDOW_ROTATION_
1223 static Eina_Bool
1224 _e_border_vkbd_state_check(E_Border *bd,
1225                            Eina_Bool show)
1226 {
1227    Eina_Bool res = EINA_TRUE;
1228    if (!e_config->wm_win_rotation) return EINA_FALSE;
1229    if ((rot.vkbd) && (rot.vkbd == bd))
1230      {
1231         if (show)
1232           {
1233              if ((rot.vkbd_hide_prepare_done) ||
1234                  (rot.vkbd_hide_prepare_timer))
1235                res = EINA_FALSE;
1236           }
1237         else
1238           {
1239              if ((rot.vkbd_show_prepare_done) ||
1240                  (rot.vkbd_show_prepare_timer))
1241                res = EINA_FALSE;
1242           }
1243      }
1244    return res;
1245 }
1246
1247 static Eina_Bool
1248 _e_border_vkbd_show_timeout(void *data)
1249 {
1250    E_Border *bd = data;
1251    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
1252    if ((bd) && ((E_OBJECT(bd)->type) == (E_BORDER_TYPE)))
1253      {
1254         if (_e_border_vkbd_state_check(bd, EINA_TRUE))
1255           {
1256              if (rot.vkbd_ctrl_win)
1257                {
1258                   ELB(ELBT_BD, "SET KBD_ON", 0);
1259                   ecore_x_e_virtual_keyboard_state_set
1260                     (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
1261                }
1262           }
1263      }
1264
1265    rot.vkbd_show_prepare_done = EINA_FALSE;
1266
1267    if (rot.vkbd_show_prepare_timer)
1268      ecore_timer_del(rot.vkbd_show_prepare_timer);
1269    rot.vkbd_show_prepare_timer = NULL;
1270
1271    if (rot.vkbd_show_timer)
1272      ecore_timer_del(rot.vkbd_show_timer);
1273    rot.vkbd_show_timer = NULL;
1274
1275    return ECORE_CALLBACK_CANCEL;
1276 }
1277
1278 static Eina_Bool
1279 _e_border_vkbd_hide_timeout(void *data)
1280 {
1281    E_Border *bd = data;
1282    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
1283    if ((bd) && ((E_OBJECT(bd)->type) == (E_BORDER_TYPE)))
1284      {
1285         if (_e_border_vkbd_state_check(bd, EINA_FALSE))
1286           {
1287              if (rot.vkbd_ctrl_win)
1288                {
1289                   ELB(ELBT_BD, "SET KBD_OFF", 0);
1290                   ecore_x_e_virtual_keyboard_state_set
1291                     (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
1292                }
1293           }
1294         e_object_unref(E_OBJECT(bd));
1295      }
1296
1297    rot.vkbd_hide_prepare_done = EINA_FALSE;
1298
1299    if (rot.vkbd_hide_prepare_timer)
1300      ecore_timer_del(rot.vkbd_hide_prepare_timer);
1301    rot.vkbd_hide_prepare_timer = NULL;
1302
1303    if (rot.vkbd_hide_timer)
1304      ecore_timer_del(rot.vkbd_hide_timer);
1305    rot.vkbd_hide_timer = NULL;
1306
1307    return ECORE_CALLBACK_CANCEL;
1308 }
1309
1310 static void
1311 _e_border_vkbd_show(E_Border *bd)
1312 {
1313    if (!e_config->wm_win_rotation) return;
1314    rot.vkbd_show_prepare_done = EINA_TRUE;
1315    if (rot.vkbd_show_prepare_timer)
1316      ecore_timer_del(rot.vkbd_show_prepare_timer);
1317    rot.vkbd_show_prepare_timer = NULL;
1318    if (rot.vkbd_show_timer)
1319      ecore_timer_del(rot.vkbd_show_timer);
1320    rot.vkbd_show_timer = NULL;
1321    if ((bd) && (!e_object_is_del(E_OBJECT(bd))))
1322      {
1323         e_border_show(bd);
1324         rot.vkbd_show_timer = ecore_timer_add(0.1f, _e_border_vkbd_show_timeout, bd);
1325      }
1326 }
1327
1328 static void
1329 _e_border_vkbd_hide(E_Border *bd)
1330 {
1331    if (!e_config->wm_win_rotation) return;
1332    rot.vkbd_hide_prepare_done = EINA_TRUE;
1333    if (rot.vkbd_hide_prepare_timer)
1334      ecore_timer_del(rot.vkbd_hide_prepare_timer);
1335    rot.vkbd_hide_prepare_timer = NULL;
1336    if (rot.vkbd_hide_timer)
1337      ecore_timer_del(rot.vkbd_hide_timer);
1338    rot.vkbd_hide_timer = NULL;
1339    if ((bd) && ((E_OBJECT(bd)->type) == (E_BORDER_TYPE)))
1340      {
1341         ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
1342         e_border_hide(bd, 0);
1343         if (!e_object_is_del(E_OBJECT(bd)))
1344           {
1345              ELB(ELBT_BD, "DEL VKBD", bd->client.win);
1346              e_object_del(E_OBJECT(bd));
1347           }
1348         rot.vkbd_hide_timer = ecore_timer_add(0.03f, _e_border_vkbd_hide_timeout, bd);
1349      }
1350 }
1351
1352 static Eina_Bool
1353 _e_border_vkbd_show_prepare_timeout(void *data)
1354 {
1355    E_Border *bd = data;
1356    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
1357    if ((bd) && (!e_object_is_del(E_OBJECT(bd))))
1358      {
1359         ELB(ELBT_BD, "TIMEOUT KBD_SHOW_PREPARE", bd->client.win);
1360         _e_border_vkbd_show(bd);
1361      }
1362    return ECORE_CALLBACK_CANCEL;
1363 }
1364
1365 static Eina_Bool
1366 _e_border_vkbd_hide_prepare_timeout(void *data)
1367 {
1368    E_Border *bd = data;
1369    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
1370    if ((bd) && ((E_OBJECT(bd)->type) == (E_BORDER_TYPE)))
1371      {
1372         ELB(ELBT_BD, "TIMEOUT KBD_HIDE_PREPARE", bd->client.win);
1373         _e_border_vkbd_hide(bd);
1374      }
1375    return ECORE_CALLBACK_CANCEL;
1376 }
1377 #endif
1378
1379 EAPI void
1380 e_border_show(E_Border *bd)
1381 {
1382    E_Event_Border_Show *ev;
1383    unsigned int visible;
1384
1385    E_OBJECT_CHECK(bd);
1386    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1387    if (bd->visible) return;
1388 #ifdef _F_ZONE_WINDOW_ROTATION_
1389    // newly created window that has to be rotated will be show after rotation done.
1390    // so, skip at this time. it will be called again after GETTING ROT_DONE.
1391 #if 0
1392    if ((bd->new_client) &&
1393        (bd->client.e.state.rot.changes != -1))
1394      {
1395         // if this window is in withdrawn state, show this window right now.
1396         // that's because the window in withdrawn state can't render its canvas.
1397         // eventually, this window will not send the message of rotation done,
1398         // even if e17 request to rotation this window.
1399         if (bd->client.icccm.state != ECORE_X_WINDOW_STATE_HINT_NORMAL)
1400           e_hints_window_visible_set(bd);
1401
1402         bd->client.e.state.rot.pending_show = 1;
1403         return;
1404      }
1405 #endif
1406    if ((e_config->wm_win_rotation) &&
1407        (rot.vkbd_ctrl_win) && (rot.vkbd) &&
1408        (bd == rot.vkbd) &&
1409        (!rot.vkbd_show_prepare_done))
1410      {
1411         ELB(ELBT_BD, "SEND KBD_ON_PREPARE", bd->client.win);
1412         ecore_x_e_virtual_keyboard_on_prepare_request_send(rot.vkbd_ctrl_win);
1413         if (rot.vkbd_show_prepare_timer)
1414           ecore_timer_del(rot.vkbd_show_prepare_timer);
1415         rot.vkbd_show_prepare_timer = ecore_timer_add(1.5f,
1416                                                       _e_border_vkbd_show_prepare_timeout,
1417                                                       bd);
1418         return;
1419      }
1420    ELB(ELBT_BD, "SHOW", bd->client.win);
1421 #endif
1422    ecore_x_window_shadow_tree_flush();
1423    e_container_shape_show(bd->shape);
1424    if (!bd->need_reparent)
1425      ecore_x_window_show(bd->client.win);
1426    e_hints_window_visible_set(bd);
1427    bd->hidden = 0;
1428    bd->visible = 1;
1429    bd->changes.visible = 1;
1430
1431    visible = 1;
1432    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
1433    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MANAGED, &visible, 1);
1434
1435    ev = E_NEW(E_Event_Border_Show, 1);
1436    ev->border = bd;
1437    e_object_ref(E_OBJECT(bd));
1438 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_show_event");
1439    ecore_event_add(E_EVENT_BORDER_SHOW, ev, _e_border_event_border_show_free, NULL);
1440
1441 #ifdef _F_ZONE_WINDOW_ROTATION_
1442    if ((e_config->wm_win_rotation) &&
1443        ((bd->client.e.state.rot.support) ||
1444         (bd->client.e.state.rot.app_set)))
1445      {
1446         ELB(ELBT_ROT, "CHECK", bd->client.win);
1447         int rotation = _e_border_rotation_angle_get(bd);
1448         if (rotation != -1) e_border_rotation_set(bd, rotation);
1449      }
1450 #endif
1451 }
1452
1453 EAPI void
1454 e_border_hide(E_Border *bd,
1455               int       manage)
1456 {
1457    unsigned int visible;
1458
1459    E_OBJECT_CHECK(bd);
1460    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1461
1462 #ifdef _F_ZONE_WINDOW_ROTATION_
1463    if ((e_config->wm_win_rotation) &&
1464        (rot.vkbd_ctrl_win) && (rot.vkbd) &&
1465        (bd == rot.vkbd) &&
1466        (!rot.vkbd_hide_prepare_done) &&
1467        (!bd->iconic))
1468      {
1469         Eina_Bool need_prepare = EINA_TRUE;
1470         E_Border *child = NULL;
1471         if (bd->parent)
1472           {
1473              if (e_object_is_del(E_OBJECT(bd->parent)))
1474                need_prepare = EINA_FALSE;
1475              else
1476                {
1477                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
1478                   if (bd->parent->modal == bd)
1479                     {
1480                        ecore_x_event_mask_unset(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
1481                        ecore_x_event_mask_set(bd->parent->client.win, bd->parent->saved.event_mask);
1482                        bd->parent->lock_close = 0;
1483                        bd->parent->saved.event_mask = 0;
1484                        bd->parent->modal = NULL;
1485                     }
1486                   bd->parent = NULL;
1487                }
1488           }
1489         else
1490           need_prepare = EINA_FALSE;
1491
1492         EINA_LIST_FREE(bd->transients, child)
1493           {
1494              child->parent = NULL;
1495           }
1496
1497         ELBF(ELBT_BD, 0, bd->client.win, "SEND KBD_OFF_PREPARE:%d", need_prepare);
1498
1499         if (need_prepare)
1500           {
1501              e_object_ref(E_OBJECT(bd));
1502              ecore_x_e_virtual_keyboard_off_prepare_request_send(rot.vkbd_ctrl_win);
1503              if (rot.vkbd_hide_prepare_timer)
1504                ecore_timer_del(rot.vkbd_hide_prepare_timer);
1505              rot.vkbd_hide_prepare_timer = ecore_timer_add(1.5f,
1506                                                            _e_border_vkbd_hide_prepare_timeout,
1507                                                            bd);
1508              return;
1509           }
1510         else
1511           {
1512              e_object_ref(E_OBJECT(bd));
1513
1514              /* In order to clear conformant area properly, WM should send keyboard off prepare request event */
1515              ecore_x_e_virtual_keyboard_off_prepare_request_send(rot.vkbd_ctrl_win);
1516
1517              /* cleanup code from _e_border_vkbd_hide() */
1518              rot.vkbd_hide_prepare_done = EINA_TRUE;
1519              if (rot.vkbd_hide_prepare_timer)
1520                ecore_timer_del(rot.vkbd_hide_prepare_timer);
1521              rot.vkbd_hide_prepare_timer = NULL;
1522              if (rot.vkbd_hide_timer)
1523                ecore_timer_del(rot.vkbd_hide_timer);
1524              rot.vkbd_hide_timer = ecore_timer_add(0.03f, _e_border_vkbd_hide_timeout, bd);
1525           }
1526      }
1527    ELBF(ELBT_BD, 0, bd->client.win, "HIDE visible:%d", bd->visible);
1528 #endif
1529    if (!bd->visible) goto send_event;
1530    ecore_x_window_shadow_tree_flush();
1531    if (bd->moving)
1532      _e_border_move_end(bd);
1533    if (bd->resize_mode != RESIZE_NONE)
1534      {
1535         _e_border_pointer_resize_end(bd);
1536         bd->resize_mode = RESIZE_NONE;
1537         _e_border_resize_end(bd);
1538      }
1539
1540    e_container_shape_hide(bd->shape);
1541    if (!bd->iconic) e_hints_window_hidden_set(bd);
1542
1543    bd->visible = 0;
1544    bd->changes.visible = 1;
1545
1546    if (!bd->need_reparent)
1547      {
1548         if ((bd->focused) ||
1549             (e_grabinput_last_focus_win_get() == bd->client.win))
1550           {
1551              e_border_focus_set(bd, 0, 1);
1552              if (manage != 2)
1553                {
1554                   E_Border *pbd;
1555                   E_Container *con;
1556                   E_Zone *zone;
1557                   E_Desk *desk;
1558
1559                   con = e_container_current_get(e_manager_current_get());
1560                   zone = e_zone_current_get(con);
1561                   desk = e_desk_current_get(zone);
1562
1563                   if ((bd->parent) &&
1564                       (bd->parent->desk == desk) && (bd->parent->modal == bd))
1565                     e_border_focus_set(bd->parent, 1, 1);
1566                   else if (e_config->focus_revert_on_hide_or_close)
1567                     {
1568                        /* When using pointer focus, the border under the
1569                         * pointer (if any) gets focused, in sloppy/click
1570                         * focus the last focused window on the current
1571                         * desk gets focus */
1572                        if (e_config->focus_policy == E_FOCUS_MOUSE)
1573                          {
1574                             pbd = e_border_under_pointer_get(desk, bd);
1575                             if (pbd)
1576                               e_border_focus_set(pbd, 1, 1);
1577                          }
1578 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
1579                        else if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) &&
1580                                 (e_config->focus_policy == E_FOCUS_CLICK))
1581                          _e_border_latest_stacked_focus(bd);
1582 #endif
1583
1584                        else
1585                          e_desk_last_focused_focus(desk);
1586                     }
1587                }
1588           }
1589         switch (manage)
1590           {
1591            case 2: break;
1592            case 3:
1593              bd->hidden = 1;
1594            case 1:
1595              /* Make sure that this border isn't deleted */
1596              bd->await_hide_event++;
1597            default:
1598              if (!e_manager_comp_evas_get(bd->zone->container->manager))
1599                ecore_x_window_hide(bd->client.win);
1600           }
1601      }
1602
1603    visible = 0;
1604    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
1605    if (!manage)
1606      ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MANAGED, &visible, 1);
1607
1608    bd->post_show = 0;
1609
1610 send_event:
1611    if (!stopping)
1612      {
1613 #ifdef _F_ZONE_WINDOW_ROTATION_
1614         _e_border_rotation_list_remove(bd);
1615 #endif
1616
1617         E_Event_Border_Hide *ev;
1618
1619         ev = E_NEW(E_Event_Border_Hide, 1);
1620         ev->border = bd;
1621         e_object_ref(E_OBJECT(bd));
1622 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_hide_event");
1623         ecore_event_add(E_EVENT_BORDER_HIDE, ev, _e_border_event_border_hide_free, NULL);
1624      }
1625 }
1626
1627 static void
1628 _pri_adj(int pid, int set, int adj, Eina_Bool use_adj, Eina_Bool adj_children, Eina_Bool do_children)
1629 {
1630    int newpri = set;
1631
1632    if (use_adj) newpri = getpriority(PRIO_PROCESS, pid) + adj;
1633    setpriority(PRIO_PROCESS, pid, newpri);
1634 // shouldnt need to do this as default ionice class is "none" (0), and
1635 // this inherits io priority FROM nice level
1636 //        ioprio_set(IOPRIO_WHO_PROCESS, pid,
1637 //                   IOPRIO_PRIO_VALUE(2, 5));
1638    if (do_children)
1639      {
1640         Eina_List *files;
1641         char *file, buf[PATH_MAX];
1642         FILE *f;
1643         int pid2, ppid;
1644
1645         // yes - this is /proc specific... so this may not work on some
1646         // os's - works on linux. too bad for others.
1647         files = ecore_file_ls("/proc");
1648         EINA_LIST_FREE(files, file)
1649           {
1650              if (isdigit(file[0]))
1651                {
1652                   snprintf(buf, sizeof(buf), "/proc/%s/stat", file);
1653                   f = fopen(buf, "r");
1654                   if (f)
1655                     {
1656                        pid2 = -1;
1657                        ppid = -1;
1658                        if (fscanf(f, "%i %*s %*s %i %*s", &pid2, &ppid) == 2)
1659                          {
1660                             fclose(f);
1661                             if (ppid == pid)
1662                               {
1663                                  if (adj_children)
1664                                     _pri_adj(pid2, set, adj, EINA_TRUE,
1665                                              adj_children, do_children);
1666                                  else
1667                                     _pri_adj(pid2, set, adj, use_adj,
1668                                              adj_children, do_children);
1669                               }
1670                          }
1671                        else fclose(f);
1672                     }
1673                }
1674              free(file);
1675           }
1676      }
1677 }
1678
1679 static void
1680 _e_border_pri_raise(E_Border *bd)
1681 {
1682    if (bd->client.netwm.pid <= 0) return;
1683    if (bd->client.netwm.pid == getpid()) return;
1684    _pri_adj(bd->client.netwm.pid,
1685             e_config->priority - 1, -1, EINA_FALSE,
1686 //            EINA_TRUE, EINA_TRUE);
1687             EINA_TRUE, EINA_FALSE);
1688 //   printf("WIN: pid %i, title %s (HI!!!!!!!!!!!!!!!!!!)\n",
1689 //          bd->client.netwm.pid, e_border_name_get(bd));
1690 }
1691
1692 static void
1693 _e_border_pri_norm(E_Border *bd)
1694 {
1695    if (bd->client.netwm.pid <= 0) return;
1696    if (bd->client.netwm.pid == getpid()) return;
1697    _pri_adj(bd->client.netwm.pid,
1698             e_config->priority, 1, EINA_FALSE,
1699 //            EINA_TRUE, EINA_TRUE);
1700             EINA_TRUE, EINA_FALSE);
1701 //   printf("WIN: pid %i, title %s (NORMAL)\n",
1702 //          bd->client.netwm.pid, e_border_name_get(bd));
1703 }
1704
1705 static void
1706 _e_border_frame_replace(E_Border *bd, Eina_Bool argb)
1707 {
1708    Ecore_X_Window win;
1709    Ecore_Evas *bg_ecore_evas;
1710    char buf[4096];
1711
1712    bd->argb = argb;
1713
1714    win = bd->win;
1715    bg_ecore_evas = bd->bg_ecore_evas;
1716
1717    /* unregister old frame window */
1718    eina_hash_del(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
1719    eina_hash_del(borders_hash, e_util_winid_str_get(bd->win), bd);
1720
1721    e_focus_setdown(bd);
1722    e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
1723    e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
1724
1725    if (bd->icon_object)
1726      evas_object_del(bd->icon_object);
1727
1728    evas_object_del(bd->bg_object);
1729    e_canvas_del(bg_ecore_evas);
1730    ecore_evas_free(bg_ecore_evas);
1731
1732    if (bd->pointer)
1733      e_object_del(E_OBJECT(bd->pointer));
1734
1735    /* create new frame */
1736    if (argb)
1737      bd->win = ecore_x_window_manager_argb_new(bd->zone->container->win,
1738                  bd->x, bd->y, bd->w, bd->h);
1739    else
1740      {
1741         bd->win = ecore_x_window_override_new(bd->zone->container->win,
1742                 bd->x, bd->y, bd->w, bd->h);
1743         ecore_x_window_shape_events_select(bd->win, 1);
1744      }
1745
1746    ecore_x_window_configure(bd->win,
1747           ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
1748           ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
1749           0, 0, 0, 0, 0,
1750           win, ECORE_X_WINDOW_STACK_BELOW);
1751
1752    e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
1753    e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
1754    e_focus_setup(bd);
1755
1756    bd->bg_ecore_evas = e_canvas_new(bd->win,
1757                                     0, 0, bd->w, bd->h, 1, 0,
1758                                     &(bd->bg_win));
1759
1760    e_canvas_add(bd->bg_ecore_evas);
1761    ecore_x_window_reparent(bd->event_win, bd->win, 0, 0);
1762
1763    bd->bg_evas = ecore_evas_get(bd->bg_ecore_evas);
1764    ecore_evas_name_class_set(bd->bg_ecore_evas, "E", "Frame_Window");
1765    ecore_evas_title_set(bd->bg_ecore_evas, "Enlightenment Frame");
1766
1767    ecore_x_window_shape_events_select(bd->bg_win, 1);
1768
1769    /* move client with shell win over to new frame */
1770    ecore_x_window_reparent(bd->client.shell_win, bd->win,
1771          bd->client_inset.l, bd->client_inset.t);
1772
1773    bd->pointer = e_pointer_window_new(bd->win, 0);
1774
1775    eina_hash_add(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
1776    eina_hash_add(borders_hash, e_util_winid_str_get(bd->win), bd);
1777
1778    if (bd->visible)
1779      {
1780         E_Border *tmp;
1781         Eina_List *l;
1782
1783         ecore_evas_show(bd->bg_ecore_evas);
1784         ecore_x_window_show(bd->win);
1785
1786         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
1787           ecore_x_window_show(tmp->win);
1788      }
1789
1790    bd->bg_object = edje_object_add(bd->bg_evas);
1791    snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
1792    e_theme_edje_object_set(bd->bg_object, "base/theme/borders", buf);
1793
1794    bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
1795
1796    /* cleanup old frame */
1797    ecore_x_window_free(win);
1798 }
1799
1800 static void
1801 _e_border_client_move_resize_send(E_Border *bd)
1802 {
1803    if (bd->internal_ecore_evas)
1804      ecore_evas_managed_move(bd->internal_ecore_evas,
1805                              bd->x + bd->fx.x + bd->client_inset.l,
1806                              bd->y + bd->fx.y + bd->client_inset.t);
1807
1808    ecore_x_icccm_move_resize_send(bd->client.win,
1809                                   bd->x + bd->fx.x + bd->client_inset.l,
1810                                   bd->y + bd->fx.y + bd->client_inset.t,
1811                                   bd->client.w,
1812                                   bd->client.h);
1813 }
1814
1815 static void
1816 _e_border_pending_move_resize_add(E_Border    *bd,
1817                                   int          move,
1818                                   int          resize,
1819                                   int          x,
1820                                   int          y,
1821                                   int          w,
1822                                   int          h,
1823                                   Eina_Bool    without_border,
1824                                   unsigned int serial)
1825 {
1826    E_Border_Pending_Move_Resize *pnd;
1827
1828    pnd = E_NEW(E_Border_Pending_Move_Resize, 1);
1829    if (!pnd) return;
1830    pnd->resize = resize;
1831    pnd->move = move;
1832    pnd->without_border = without_border;
1833    pnd->x = x;
1834    pnd->y = y;
1835    pnd->w = w;
1836    pnd->h = h;
1837    pnd->serial = serial;
1838    bd->pending_move_resize = eina_list_append(bd->pending_move_resize, pnd);
1839 }
1840
1841 static void
1842 _e_border_move_internal(E_Border *bd,
1843                         int       x,
1844                         int       y,
1845                         Eina_Bool without_border)
1846 {
1847    E_Event_Border_Move *ev;
1848
1849    E_OBJECT_CHECK(bd);
1850    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1851
1852    ecore_x_window_shadow_tree_flush();
1853    if (bd->new_client)
1854      {
1855         _e_border_pending_move_resize_add(bd, 1, 0, x, y, 0, 0, without_border, 0);
1856         return;
1857      }
1858
1859    if (bd->maximized)
1860      {
1861        if ((bd->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_BOTH)
1862          {
1863             if (e_config->allow_manip)
1864               bd->maximized = 0;
1865
1866             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
1867               {
1868                   x = bd->x;
1869               }
1870             else
1871             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
1872               {
1873                   y = bd->y;
1874               }
1875          }
1876        else if (e_config->allow_manip)
1877          bd->maximized = 0;
1878        else
1879          return;
1880      }
1881
1882    if (without_border)
1883      {
1884         x -= bd->client_inset.l;
1885         y -= bd->client_inset.t;
1886      }
1887    if (bd->move_intercept_cb)
1888      {
1889         int px, py;
1890         px = bd->x, py = bd->y;
1891         bd->move_intercept_cb(bd, x, y);
1892         if ((bd->x == px) && (bd->y == py)) return;
1893      }
1894    else if ((x == bd->x) && (y == bd->y)) return;
1895    bd->pre_res_change.valid = 0;
1896    bd->x = x;
1897    bd->y = y;
1898    bd->changed = 1;
1899    bd->changes.pos = 1;
1900 #if 0
1901    if (bd->client.netwm.sync.request)
1902      {
1903         bd->client.netwm.sync.wait++;
1904         ecore_x_netwm_sync_request_send(bd->client.win, bd->client.netwm.sync.serial++);
1905      }
1906 #endif
1907    _e_border_client_move_resize_send(bd);
1908    _e_border_move_update(bd);
1909    ev = E_NEW(E_Event_Border_Move, 1);
1910    ev->border = bd;
1911    e_object_ref(E_OBJECT(bd));
1912 //  e_object_breadcrumb_add(E_OBJECT(bd), "border_move_event");
1913    ecore_event_add(E_EVENT_BORDER_MOVE, ev, _e_border_event_border_move_free, NULL);
1914    _e_border_zone_update(bd);
1915 }
1916
1917 /**
1918  * Move window to coordinates that already account border decorations.
1919  *
1920  * This call will consider given position already accounts border
1921  * decorations, so it will not be considered later. This will just
1922  * work properly with borders that have being evaluated and border
1923  * decorations are known (border->client_inset).
1924  *
1925  * @parm x horizontal position to place window.
1926  * @parm y vertical position to place window.
1927  *
1928  * @see e_border_move_without_border()
1929  */
1930 EAPI void
1931 e_border_move(E_Border *bd,
1932               int       x,
1933               int       y)
1934 {
1935    if (bd->fullscreen)
1936      return;
1937
1938    _e_border_move_internal(bd, x, y, 0);
1939 }
1940
1941
1942 /**
1943  * Set a callback which will be called just prior to updating the
1944  * move coordinates for a border
1945  */
1946 EAPI void
1947 e_border_move_intercept_cb_set(E_Border *bd, E_Border_Move_Intercept_Cb cb)
1948 {
1949    bd->move_intercept_cb = cb;
1950 }
1951
1952 /**
1953  * Move window to coordinates that do not account border decorations yet.
1954  *
1955  * This call will consider given position does not account border
1956  * decoration, so these values (border->client_inset) will be
1957  * accounted automatically. This is specially useful when it is a new
1958  * client and has not be evaluated yet, in this case
1959  * border->client_inset will be zeroed and no information is known. It
1960  * will mark pending requests so border will be accounted on
1961  * evalutation phase.
1962  *
1963  * @parm x horizontal position to place window.
1964  * @parm y vertical position to place window.
1965  *
1966  * @see e_border_move()
1967  */
1968 EAPI void
1969 e_border_move_without_border(E_Border *bd,
1970                              int       x,
1971                              int       y)
1972 {
1973    if (bd->fullscreen)
1974      return;
1975
1976    _e_border_move_internal(bd, x, y, 1);
1977 }
1978
1979 EAPI void
1980 e_border_center(E_Border *bd)
1981 {
1982    int x, y, w, h;
1983    E_OBJECT_CHECK(bd);
1984    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1985
1986    e_zone_useful_geometry_get(bd->zone, &x, &y, &w, &h);
1987    e_border_move(bd, x + (w - bd->w) / 2, y + (h - bd->h) / 2);
1988 }
1989
1990 EAPI void
1991 e_border_center_pos_get(E_Border *bd,
1992                         int      *x,
1993                         int      *y)
1994 {
1995    int zx, zy, zw, zh;
1996    E_OBJECT_CHECK(bd);
1997    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
1998
1999    e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
2000    if (x) *x = zx + (zw - bd->w) / 2;
2001    if (y) *y = zy + (zh - bd->h) / 2;
2002 }
2003
2004 EAPI void
2005 e_border_fx_offset(E_Border *bd,
2006                    int       x,
2007                    int       y)
2008 {
2009    E_OBJECT_CHECK(bd);
2010    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2011
2012    if ((x == bd->fx.x) && (y == bd->fx.y)) return;
2013    bd->fx.x = x;
2014    bd->fx.y = y;
2015
2016    bd->changes.pos = 1;
2017    bd->changed = 1;
2018
2019    if (bd->moving) _e_border_move_update(bd);
2020 }
2021
2022 static void
2023 _e_border_move_resize_internal(E_Border *bd,
2024                                int       x,
2025                                int       y,
2026                                int       w,
2027                                int       h,
2028                                Eina_Bool without_border,
2029                                Eina_Bool move)
2030 {
2031    E_Event_Border_Move *mev;
2032    E_Event_Border_Resize *rev;
2033
2034    E_OBJECT_CHECK(bd);
2035    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2036
2037    ecore_x_window_shadow_tree_flush();
2038
2039    if (bd->new_client)
2040      {
2041         _e_border_pending_move_resize_add(bd, move, 1, x, y, w, h, without_border, 0);
2042         return;
2043      }
2044
2045    if (bd->maximized)
2046      {
2047        if ((bd->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_BOTH)
2048          {
2049             if (e_config->allow_manip)
2050               bd->maximized = 0;
2051
2052             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
2053               {
2054                   x = bd->x;
2055                   w = bd->w;
2056               }
2057             else
2058             if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
2059               {
2060                   y = bd->y;
2061                   h = bd->h;
2062               }
2063          }
2064        else
2065        if (e_config->allow_manip)
2066          bd->maximized = 0;
2067        else
2068          return;
2069      }
2070
2071    if (without_border)
2072      {
2073         x -= bd->client_inset.l;
2074         y -= bd->client_inset.t;
2075         w += (bd->client_inset.l + bd->client_inset.r);
2076         h += (bd->client_inset.t + bd->client_inset.b);
2077      }
2078
2079    if ((!move || ((x == bd->x) && (y == bd->y))) &&
2080        (w == bd->w) && (h == bd->h))
2081      return;
2082
2083    bd->pre_res_change.valid = 0;
2084    if (move)
2085      {
2086         bd->changes.pos = 1;
2087         bd->x = x;
2088         bd->y = y;
2089      }
2090    bd->w = w;
2091    bd->h = h;
2092    bd->client.w = bd->w - (bd->client_inset.l + bd->client_inset.r);
2093    bd->client.h = bd->h - (bd->client_inset.t + bd->client_inset.b);
2094
2095    if ((bd->shaped) || (bd->client.shaped))
2096      {
2097         bd->need_shape_merge = 1;
2098         bd->need_shape_export = 1;
2099      }
2100    if (bd->shaped_input)
2101      {
2102         bd->need_shape_merge = 1;
2103      }
2104
2105    if (bd->internal_ecore_evas)
2106      {
2107         bd->changed = 1;
2108         bd->changes.size = 1;
2109      }
2110    else
2111      {
2112         if (bdresize && bd->client.netwm.sync.request)
2113           {
2114              bd->client.netwm.sync.wait++;
2115              /* Don't use x and y as supplied to this function, as it is called with 0, 0
2116               * when no move is intended.  The border geometry is set above anyways.
2117               */
2118              _e_border_pending_move_resize_add(bd, move, 1, bd->x, bd->y, bd->w, bd->h, without_border,
2119                                                bd->client.netwm.sync.serial);
2120              ecore_x_netwm_sync_request_send(bd->client.win,
2121                                              bd->client.netwm.sync.serial++);
2122           }
2123         else
2124           {
2125              bd->changed = 1;
2126              bd->changes.size = 1;
2127           }
2128      }
2129
2130    _e_border_client_move_resize_send(bd);
2131
2132    _e_border_resize_update(bd);
2133    if (move)
2134      {
2135         mev = E_NEW(E_Event_Border_Move, 1);
2136         mev->border = bd;
2137         e_object_ref(E_OBJECT(bd));
2138         //   e_object_breadcrumb_add(E_OBJECT(bd), "border_move_event");
2139         ecore_event_add(E_EVENT_BORDER_MOVE, mev, _e_border_event_border_move_free, NULL);
2140      }
2141
2142    rev = E_NEW(E_Event_Border_Resize, 1);
2143    rev->border = bd;
2144    e_object_ref(E_OBJECT(bd));
2145 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
2146    ecore_event_add(E_EVENT_BORDER_RESIZE, rev, _e_border_event_border_resize_free, NULL);
2147    _e_border_zone_update(bd);
2148 }
2149
2150 /**
2151  * Move and resize window to values that already account border decorations.
2152  *
2153  * This call will consider given values already accounts border
2154  * decorations, so it will not be considered later. This will just
2155  * work properly with borders that have being evaluated and border
2156  * decorations are known (border->client_inset).
2157  *
2158  * @parm x horizontal position to place window.
2159  * @parm y vertical position to place window.
2160  * @parm w horizontal window size.
2161  * @parm h vertical window size.
2162  *
2163  * @see e_border_move_resize_without_border()
2164  */
2165 EAPI void
2166 e_border_move_resize(E_Border *bd,
2167                      int       x,
2168                      int       y,
2169                      int       w,
2170                      int       h)
2171 {
2172    if (bd->fullscreen)
2173      return;
2174
2175    _e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
2176 }
2177
2178 /**
2179  * Move and resize window to values that do not account border decorations yet.
2180  *
2181  * This call will consider given values already accounts border
2182  * decorations, so it will not be considered later. This will just
2183  * work properly with borders that have being evaluated and border
2184  * decorations are known (border->client_inset).
2185  *
2186  * @parm x horizontal position to place window.
2187  * @parm y vertical position to place window.
2188  * @parm w horizontal window size.
2189  * @parm h vertical window size.
2190  *
2191  * @see e_border_move_resize()
2192  */
2193 EAPI void
2194 e_border_move_resize_without_border(E_Border *bd,
2195                                     int       x,
2196                                     int       y,
2197                                     int       w,
2198                                     int       h)
2199 {
2200    if (bd->fullscreen)
2201      return;
2202
2203    _e_border_move_resize_internal(bd, x, y, w, h, 1, 1);
2204 }
2205
2206 /**
2207  * Resize window to values that already account border decorations.
2208  *
2209  * This call will consider given size already accounts border
2210  * decorations, so it will not be considered later. This will just
2211  * work properly with borders that have being evaluated and border
2212  * decorations are known (border->client_inset).
2213  *
2214  * @parm w horizontal window size.
2215  * @parm h vertical window size.
2216  *
2217  * @see e_border_resize_without_border()
2218  */
2219 EAPI void
2220 e_border_resize(E_Border *bd,
2221                 int       w,
2222                 int       h)
2223 {
2224    if (bd->fullscreen)
2225      return;
2226
2227    _e_border_move_resize_internal(bd, 0, 0, w, h, 0, 0);
2228 }
2229
2230 /**
2231  * Resize window to values that do not account border decorations yet.
2232  *
2233  * This call will consider given size does not account border
2234  * decoration, so these values (border->client_inset) will be
2235  * accounted automatically. This is specially useful when it is a new
2236  * client and has not be evaluated yet, in this case
2237  * border->client_inset will be zeroed and no information is known. It
2238  * will mark pending requests so border will be accounted on
2239  * evalutation phase.
2240  *
2241  * @parm w horizontal window size.
2242  * @parm h vertical window size.
2243  *
2244  * @see e_border_resize()
2245  */
2246 EAPI void
2247 e_border_resize_without_border(E_Border *bd,
2248                                int       w,
2249                                int       h)
2250 {
2251    if (bd->fullscreen)
2252      return;
2253
2254    _e_border_move_resize_internal(bd, 0, 0, w, h, 1, 0);
2255 }
2256
2257 EAPI void
2258 e_border_layer_set(E_Border *bd,
2259                    int       layer)
2260 {
2261    int oldraise;
2262
2263    E_OBJECT_CHECK(bd);
2264    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2265
2266    ecore_x_window_shadow_tree_flush();
2267
2268    oldraise = e_config->transient.raise;
2269
2270    if (bd->fullscreen)
2271      {
2272         bd->saved.layer = layer;
2273         return;
2274      }
2275    bd->layer = layer;
2276    if (e_config->transient.layer)
2277      {
2278         Eina_List *l;
2279         E_Border *child;
2280         Eina_List *list = _e_border_sub_borders_new(bd);
2281
2282         /* We need to set raise to one, else the child wont
2283          * follow to the new layer. It should be like this,
2284          * even if the user usually doesn't want to raise
2285          * the transients.
2286          */
2287         e_config->transient.raise = 1;
2288         EINA_LIST_FOREACH(list, l, child)
2289           {
2290              e_border_layer_set(child, layer);
2291           }
2292      }
2293    e_border_raise(bd);
2294    e_config->transient.raise = oldraise;
2295 }
2296
2297 EAPI void
2298 e_border_raise(E_Border *bd)
2299 {
2300    E_Event_Border_Stack *ev;
2301    E_Border *last = NULL, *child;
2302    Eina_List *l;
2303
2304    E_OBJECT_CHECK(bd);
2305    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2306
2307    ecore_x_window_shadow_tree_flush();
2308
2309    if (e_config->transient.raise)
2310      {
2311 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
2312         if (e_config->focus_setting != E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
2313           {
2314 #endif
2315         Eina_List *list = _e_border_sub_borders_new(bd);
2316
2317         EINA_LIST_REVERSE_FOREACH(list, l, child)
2318           {
2319              /* Don't stack iconic transients. If the user wants these shown,
2320               * thats another option.
2321               */
2322              if (!child->iconic)
2323                {
2324                   if (last)
2325                     e_border_stack_below(child, last);
2326                   else
2327                     {
2328                        E_Border *above;
2329
2330                        /* First raise the border to find out which border we will end up above */
2331                        above = e_container_border_raise(child);
2332
2333                        if (above)
2334                          {
2335                             /* We ended up above a border, now we must stack this border to
2336                              * generate the stacking event, and to check if this transient
2337                              * has other transients etc.
2338                              */
2339                             e_border_stack_above(child, above);
2340                          }
2341                        else
2342                          {
2343                             /* If we didn't end up above any border, we are on the bottom! */
2344                             e_border_lower(child);
2345                          }
2346                     }
2347                   last = child;
2348                }
2349           }
2350         eina_list_free(list);
2351 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
2352           }
2353         else
2354           {
2355              EINA_LIST_FOREACH(bd->transients, l, child)
2356                {
2357                 /* Don't stack iconic transients. If the user wants these shown,
2358                  * thats another option.
2359                  */
2360                   if (!child->iconic)
2361                     {
2362                        child->layer = bd->layer;
2363                        if (!last) last = child;
2364                        e_border_raise (child);
2365                     }
2366                }
2367           }
2368 #endif
2369      }
2370
2371    ev = E_NEW(E_Event_Border_Stack, 1);
2372    ev->border = bd;
2373    e_object_ref(E_OBJECT(bd));
2374
2375    if (last)
2376      {
2377         e_container_border_stack_below(bd, last);
2378         ev->stack = last;
2379         e_object_ref(E_OBJECT(last));
2380         ev->type = E_STACKING_BELOW;
2381      }
2382    else
2383      {
2384         E_Border *above;
2385
2386         /* If we don't have any children, raise this border */
2387         above = e_container_border_raise(bd);
2388         e_border_raise_latest_set(bd);
2389         if (above)
2390           {
2391              /* We ended up above a border */
2392               ev->stack = above;
2393               e_object_ref(E_OBJECT(above));
2394               ev->type = E_STACKING_ABOVE;
2395           }
2396         else
2397           {
2398              /* No border to raise above, same as a lower! */
2399               ev->stack = NULL;
2400               ev->type = E_STACKING_ABOVE;
2401           }
2402      }
2403
2404    ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
2405    e_remember_update(bd);
2406 }
2407
2408 EAPI void
2409 e_border_lower(E_Border *bd)
2410 {
2411    E_Event_Border_Stack *ev;
2412    E_Border *last = NULL, *child;
2413    Eina_List *l;
2414
2415    E_OBJECT_CHECK(bd);
2416    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2417
2418    ecore_x_window_shadow_tree_flush();
2419
2420    if (e_config->transient.lower)
2421      {
2422 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
2423         if (e_config->focus_setting != E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
2424           {
2425 #endif
2426         Eina_List *list = _e_border_sub_borders_new(bd);
2427
2428         EINA_LIST_REVERSE_FOREACH(list, l, child)
2429           {
2430              /* Don't stack iconic transients. If the user wants these shown,
2431               * thats another option.
2432               */
2433              if (!child->iconic)
2434                {
2435                   if (last)
2436                     e_border_stack_below(child, last);
2437                   else
2438                     {
2439                        E_Border *below;
2440
2441                        /* First lower the border to find out which border we will end up below */
2442                        below = e_container_border_lower(child);
2443
2444                        if (below)
2445                          {
2446                             /* We ended up below a border, now we must stack this border to
2447                              * generate the stacking event, and to check if this transient
2448                              * has other transients etc.
2449                              */
2450                             e_border_stack_below(child, below);
2451                          }
2452                        else
2453                          {
2454                             /* If we didn't end up below any border, we are on top! */
2455                             e_border_raise(child);
2456                          }
2457                     }
2458                   last = child;
2459                }
2460           }
2461         eina_list_free(list);
2462
2463 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
2464           }
2465         else
2466           {
2467              EINA_LIST_FOREACH(bd->transients, l, child)
2468                {
2469                 /* Don't stack iconic transients. If the user wants these shown,
2470                  * thats another option.
2471                  */
2472                   if (!child->iconic)
2473                     {
2474                        child->layer = bd->layer;
2475                        e_border_lower (child);
2476                        last = child;
2477                     }
2478                }
2479           }
2480 #endif
2481      }
2482
2483    ev = E_NEW(E_Event_Border_Stack, 1);
2484    ev->border = bd;
2485    e_object_ref(E_OBJECT(bd));
2486
2487    if (last)
2488      {
2489         e_container_border_stack_below(bd, last);
2490         ev->stack = last;
2491         e_object_ref(E_OBJECT(last));
2492         ev->type = E_STACKING_BELOW;
2493      }
2494    else
2495      {
2496         E_Border *below;
2497
2498         /* If we don't have any children, lower this border */
2499         below = e_container_border_lower(bd);
2500         if (below)
2501           {
2502              /* We ended up below a border */
2503               ev->stack = below;
2504               e_object_ref(E_OBJECT(below));
2505               ev->type = E_STACKING_BELOW;
2506           }
2507         else
2508           {
2509              /* No border to hide under, same as a raise! */
2510               ev->stack = NULL;
2511               ev->type = E_STACKING_BELOW;
2512           }
2513      }
2514
2515    ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
2516    e_remember_update(bd);
2517 }
2518
2519 EAPI void
2520 e_border_stack_above(E_Border *bd,
2521                      E_Border *above)
2522 {
2523    /* TODO: Should stack above allow the border to change level */
2524     E_Event_Border_Stack *ev;
2525     E_Border *last = NULL, *child;
2526     Eina_List *l;
2527
2528     E_OBJECT_CHECK(bd);
2529     E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2530
2531     ecore_x_window_shadow_tree_flush();
2532
2533     if (e_config->transient.raise)
2534       {
2535          Eina_List *list = _e_border_sub_borders_new(bd);
2536
2537          EINA_LIST_REVERSE_FOREACH(list, l, child)
2538            {
2539               /* Don't stack iconic transients. If the user wants these shown,
2540                * thats another option.
2541                */
2542               if (!child->iconic)
2543                 {
2544                    if (last)
2545                      e_border_stack_below(child, last);
2546                    else
2547                      e_border_stack_above(child, above);
2548                    last = child;
2549                 }
2550            }
2551          eina_list_free(list);
2552       }
2553
2554     ev = E_NEW(E_Event_Border_Stack, 1);
2555     ev->border = bd;
2556     e_object_ref(E_OBJECT(bd));
2557
2558     if (last)
2559       {
2560          e_container_border_stack_below(bd, last);
2561          ev->stack = last;
2562          e_object_ref(E_OBJECT(last));
2563          ev->type = E_STACKING_BELOW;
2564       }
2565     else
2566       {
2567          e_container_border_stack_above(bd, above);
2568          ev->stack = above;
2569          e_object_ref(E_OBJECT(above));
2570          ev->type = E_STACKING_ABOVE;
2571       }
2572
2573     ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
2574     e_remember_update(bd);
2575 }
2576
2577 EAPI void
2578 e_border_stack_below(E_Border *bd,
2579                      E_Border *below)
2580 {
2581    /* TODO: Should stack below allow the border to change level */
2582     E_Event_Border_Stack *ev;
2583     E_Border *last = NULL, *child;
2584     Eina_List *l;
2585
2586     E_OBJECT_CHECK(bd);
2587     E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2588
2589     ecore_x_window_shadow_tree_flush();
2590
2591     if (e_config->transient.lower)
2592       {
2593          Eina_List *list = _e_border_sub_borders_new(bd);
2594
2595          EINA_LIST_REVERSE_FOREACH(bd->transients, l, child)
2596            {
2597               /* Don't stack iconic transients. If the user wants these shown,
2598                * thats another option.
2599                */
2600               if (!child->iconic)
2601                 {
2602                    if (last)
2603                      e_border_stack_below(child, last);
2604                    else
2605                      e_border_stack_below(child, below);
2606                    last = child;
2607                 }
2608            }
2609          eina_list_free(list);
2610       }
2611
2612     ev = E_NEW(E_Event_Border_Stack, 1);
2613     ev->border = bd;
2614     e_object_ref(E_OBJECT(bd));
2615
2616     if (last)
2617       {
2618          e_container_border_stack_below(bd, last);
2619          ev->stack = last;
2620          e_object_ref(E_OBJECT(last));
2621          ev->type = E_STACKING_BELOW;
2622       }
2623     else
2624       {
2625          e_container_border_stack_below(bd, below);
2626          ev->stack = below;
2627          e_object_ref(E_OBJECT(below));
2628          ev->type = E_STACKING_BELOW;
2629       }
2630
2631     ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
2632     e_remember_update(bd);
2633 }
2634
2635 EAPI void
2636 e_border_focus_latest_set(E_Border *bd)
2637 {
2638    focus_stack = eina_list_remove(focus_stack, bd);
2639    focus_stack = eina_list_prepend(focus_stack, bd);
2640 }
2641
2642 EAPI void
2643 e_border_raise_latest_set(E_Border *bd)
2644 {
2645    raise_stack = eina_list_remove(raise_stack, bd);
2646    raise_stack = eina_list_prepend(raise_stack, bd);
2647 }
2648
2649 /*
2650  * Sets the focus to the given border if necessary
2651  * There are 3 cases of different focus_policy-configurations:
2652  *
2653  * - E_FOCUS_CLICK: just set the focus, the most simple one
2654  *
2655  * - E_FOCUS_MOUSE: focus is where the mouse is, so try to
2656  *   warp the pointer to the window. If this fails (because
2657  *   the pointer is already in the window), just set the focus.
2658  *
2659  * - E_FOCUS_SLOPPY: focus is where the mouse is or on the
2660  *   last window which was focused, if the mouse is on the
2661  *   desktop. So, we need to look if there is another window
2662  *   under the pointer and warp to pointer to the right
2663  *   one if so (also, we set the focus afterwards). In case
2664  *   there is no window under pointer, the pointer is on the
2665  *   desktop and so we just set the focus.
2666  *
2667  *
2668  * This function is to be called when setting the focus was not
2669  * explicitly triggered by the user (by moving the mouse or
2670  * clicking for example), but implicitly (by closing a window,
2671  * the last focused window should get focus).
2672  *
2673  */
2674 EAPI void
2675 e_border_focus_set_with_pointer(E_Border *bd)
2676 {
2677 #ifdef PRINT_LOTS_OF_DEBUG
2678    E_PRINT_BORDER_INFO(bd);
2679 #endif
2680    /* note: this is here as it seems there are enough apps that do not even
2681     * expect us to emulate a look of focus but not actually set x input
2682     * focus as we do - so simply abort any focuse set on such windows */
2683    /* be strict about accepting focus hint */
2684    if ((!bd->client.icccm.accepts_focus) &&
2685        (!bd->client.icccm.take_focus)) return;
2686    if (bd->lock_focus_out) return;
2687
2688    e_border_focus_set(bd, 1, 1);
2689
2690    if (e_config->focus_policy == E_FOCUS_CLICK) return;
2691    if (!bd->visible) return;
2692
2693    if (e_config->focus_policy == E_FOCUS_SLOPPY)
2694      {
2695         if (!e_border_under_pointer_get(bd->desk, bd))
2696           {
2697              e_border_pointer_warp_to_center(bd);
2698           }
2699      }
2700    else
2701      {
2702         e_border_pointer_warp_to_center(bd);
2703      }
2704 }
2705
2706 EAPI void
2707 e_border_focus_set(E_Border *bd,
2708                    int       focus,
2709                    int       set)
2710 {
2711    E_Border *bd_unfocus = NULL;
2712    Eina_Bool focus_changed = EINA_FALSE;
2713
2714    E_OBJECT_CHECK(bd);
2715    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2716    /* note: this is here as it seems there are enough apps that do not even
2717     * expect us to emulate a look of focus but not actually set x input
2718     * focus as we do - so simply abort any focuse set on such windows */
2719    /* be strict about accepting focus hint */
2720    if ((!bd->client.icccm.accepts_focus) &&
2721        (!bd->client.icccm.take_focus))
2722      return;
2723    if ((set) && (focus) && (bd->lock_focus_out)) return;
2724    
2725    /* dont focus an iconified window. that's silly! */
2726    if (focus)
2727      {
2728         if (bd->iconic)
2729           {
2730              e_border_uniconify(bd);
2731              if (!focus_track_frozen)
2732                e_border_focus_latest_set(bd);
2733              return;
2734           }
2735         else if (!bd->visible)
2736           {
2737              return;
2738           }
2739         /* FIXME: hack for deskflip animation:
2740          * dont update focus when sliding previous desk */
2741         else if ((!bd->sticky) &&
2742                  (bd->desk != e_desk_current_get(bd->desk->zone)))
2743           {
2744              return;
2745           }
2746      }
2747
2748    if ((bd->modal) && (bd->modal != bd) && (bd->modal->visible))
2749      {
2750         e_border_focus_set(bd->modal, focus, set);
2751         return;
2752      }
2753    else if ((bd->leader) && (bd->leader->modal) && (bd->leader->modal != bd))
2754      {
2755         e_border_focus_set(bd->leader->modal, focus, set);
2756         return;
2757      }
2758
2759    if (focus)
2760      {
2761         if (set)
2762           {
2763              if (bd->visible && bd->changes.visible)
2764                {
2765                   bd->want_focus = 1;
2766                   bd->changed = 1;
2767                }
2768              else if ((!bd->focused) ||
2769                       (focus_next && (bd != eina_list_data_get(focus_next))))
2770                {
2771                   Eina_List *l;
2772
2773                   if ((l = eina_list_data_find_list(focus_next, bd)))
2774                     focus_next = eina_list_promote_list(focus_next, l);
2775                   else
2776                     focus_next = eina_list_prepend(focus_next, bd);
2777                }
2778              if ((bd->client.icccm.take_focus) &&
2779                  (bd->client.icccm.accepts_focus))
2780                {
2781                   e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_LOCALLY_ACTIVE);
2782                   /* TODO what if the client didn't take focus ? */
2783                }
2784              else if (!bd->client.icccm.accepts_focus)
2785                {
2786                   e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_GLOBALLY_ACTIVE);
2787                }
2788              else if (!bd->client.icccm.take_focus)
2789                {
2790                   e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_PASSIVE);
2791                   /* e_border_focus_set(bd, 1, 0); */
2792                }
2793             return;
2794           }
2795
2796         if (!bd->focused)
2797           {
2798              Eina_List *l;
2799              E_Border *bd2;
2800              
2801              if (focused) bd_unfocus = focused;
2802              if (focusing == bd) focusing = NULL;
2803              bd->focused = 1;
2804              focused = bd;
2805              if (!bd_unfocus)
2806                {
2807                   EINA_LIST_FOREACH(e_border_client_list(), l, bd2)
2808                     {
2809                        if ((bd2->fullscreen) &&
2810                            (bd2 != bd) &&
2811                            (bd2->zone == bd->zone) &&
2812                            ((bd2->desk == bd->desk) ||
2813                                (bd2->sticky) || (bd->sticky)))
2814                          {
2815                             Eina_Bool unfocus_is_parent = EINA_FALSE;
2816                             E_Border *bd_parent;
2817                             
2818                             bd_parent = bd->parent;
2819                             while (bd_parent)
2820                               {
2821                                  if (bd_parent == bd2)
2822                                    {
2823                                       unfocus_is_parent = EINA_TRUE;
2824                                       break;
2825                                    }
2826                                  bd_parent = bd->parent;
2827                               }
2828                             if ((!unfocus_is_parent) && 
2829                                 (!e_config->allow_above_fullscreen))
2830                               {
2831                                  e_border_iconify(bd2);
2832                               }
2833                          }
2834                     }
2835                }
2836              focus_changed = EINA_TRUE;
2837           }
2838      }
2839    else
2840      {
2841         bd->want_focus = 0;
2842         focus_next = eina_list_remove(focus_next, bd);
2843         if (bd == focusing) focusing = NULL;
2844
2845         if ((bd->focused) && 
2846             ((bd->desk == e_desk_current_get(bd->zone)) || (bd->sticky)))
2847           {
2848              Eina_Bool wasfocused = EINA_FALSE;
2849              bd_unfocus = bd;
2850
2851              /* should always be the case. anyway */
2852              if (bd == focused)
2853                {
2854                   focused = NULL;
2855                   wasfocused = EINA_TRUE;
2856                }
2857
2858              if ((set) && (!focus_next) && (!focusing))
2859                {
2860                   e_grabinput_focus(bd->zone->container->bg_win,
2861                                     E_FOCUS_METHOD_PASSIVE);
2862                }
2863              if ((bd->fullscreen) && (wasfocused))
2864                {
2865                   Eina_Bool have_vis_child = EINA_FALSE;
2866                   Eina_List *l;
2867                   E_Border *bd2;
2868                   
2869                   EINA_LIST_FOREACH(e_border_client_list(), l, bd2)
2870                     {
2871                        if ((bd2 != bd) &&
2872                            (bd2->zone == bd->zone) &&
2873                            ((bd2->desk == bd->desk) ||
2874                                (bd2->sticky) || (bd->sticky)))
2875                          {
2876                             if (bd2->parent == bd)
2877                               {
2878                                  have_vis_child = EINA_TRUE;
2879                                  break;
2880                               }
2881                          }
2882                     }
2883                   if ((!have_vis_child) && 
2884                       (!e_config->allow_above_fullscreen))
2885                     e_border_iconify(bd);
2886                }
2887           }
2888      }
2889    
2890    if ((bd_unfocus) &&
2891        (!e_object_is_del(E_OBJECT(bd_unfocus)) &&
2892         (e_object_ref_get(E_OBJECT(bd_unfocus)) > 0)))
2893      {
2894         E_Event_Border_Focus_Out *ev;
2895
2896         bd_unfocus->focused = 0;
2897         e_focus_event_focus_out(bd_unfocus);
2898
2899         if (bd_unfocus->raise_timer)
2900           ecore_timer_del(bd_unfocus->raise_timer);
2901         bd_unfocus->raise_timer = NULL;
2902
2903         edje_object_signal_emit(bd_unfocus->bg_object, "e,state,unfocused", "e");
2904         if (bd_unfocus->icon_object)
2905           edje_object_signal_emit(bd_unfocus->icon_object, "e,state,unfocused", "e");
2906
2907         ev = E_NEW(E_Event_Border_Focus_Out, 1);
2908         ev->border = bd_unfocus;
2909         e_object_ref(E_OBJECT(bd_unfocus));
2910
2911         ecore_event_add(E_EVENT_BORDER_FOCUS_OUT, ev,
2912                         _e_border_event_border_focus_out_free, NULL);
2913         if ((bd_unfocus->fullscreen) &&
2914             (bd != bd_unfocus) &&
2915             (bd->zone == bd_unfocus->zone) &&
2916             ((bd->desk == bd_unfocus->desk) ||
2917              (bd->sticky) || (bd_unfocus->sticky)))
2918           {
2919              Eina_Bool unfocus_is_parent = EINA_FALSE;
2920              E_Border *bd_parent;
2921
2922              bd_parent = bd->parent;
2923              while (bd_parent)
2924                {
2925                   if (bd_parent == bd_unfocus)
2926                     {
2927                        unfocus_is_parent = EINA_TRUE;
2928                        break;
2929                     }
2930                   bd_parent = bd->parent;
2931                }
2932              if ((!unfocus_is_parent) && (!e_config->allow_above_fullscreen))
2933                {
2934                   e_border_iconify(bd_unfocus);
2935                }
2936           }
2937      }
2938
2939    if (focus_changed)
2940      {
2941         E_Event_Border_Focus_In *ev;
2942
2943         e_focus_event_focus_in(bd);
2944
2945         if (!focus_track_frozen)
2946           e_border_focus_latest_set(bd);
2947
2948         e_hints_active_window_set(bd->zone->container->manager, bd);
2949
2950         edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
2951         if (bd->icon_object)
2952           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
2953
2954         ev = E_NEW(E_Event_Border_Focus_In, 1);
2955         ev->border = bd;
2956         e_object_ref(E_OBJECT(bd));
2957
2958         ecore_event_add(E_EVENT_BORDER_FOCUS_IN, ev,
2959                         _e_border_event_border_focus_in_free, NULL);
2960      }
2961 }
2962
2963 EAPI void
2964 e_border_shade(E_Border   *bd,
2965                E_Direction dir)
2966 {
2967    E_Event_Border_Resize *ev;
2968    Eina_List *l;
2969    E_Border *tmp;
2970
2971    E_OBJECT_CHECK(bd);
2972    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
2973    if ((bd->shaded) || (bd->shading) || (bd->fullscreen) ||
2974        ((bd->maximized) && (!e_config->allow_manip))) return;
2975    if ((bd->client.border.name) &&
2976        (!strcmp("borderless", bd->client.border.name))) return;
2977
2978    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
2979      ecore_x_window_hide(tmp->win);
2980
2981    ecore_x_window_shadow_tree_flush();
2982
2983    bd->shade.x = bd->x;
2984    bd->shade.y = bd->y;
2985    bd->shade.dir = dir;
2986
2987    e_hints_window_shaded_set(bd, 1);
2988    e_hints_window_shade_direction_set(bd, dir);
2989
2990    if (e_config->border_shade_animate)
2991      {
2992         bd->shade.start = ecore_loop_time_get();
2993         bd->shading = 1;
2994         bd->changes.shading = 1;
2995         bd->changed = 1;
2996
2997         if (bd->shade.dir == E_DIRECTION_UP ||
2998             bd->shade.dir == E_DIRECTION_LEFT)
2999           ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_SW);
3000         else
3001           ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NE);
3002
3003         bd->shade.anim = ecore_animator_add(_e_border_shade_animator, bd);
3004         edje_object_signal_emit(bd->bg_object, "e,state,shading", "e");
3005      }
3006    else
3007      {
3008         if (bd->shade.dir == E_DIRECTION_UP)
3009           {
3010              bd->h = bd->client_inset.t + bd->client_inset.b;
3011           }
3012         else if (bd->shade.dir == E_DIRECTION_DOWN)
3013           {
3014              bd->h = bd->client_inset.t + bd->client_inset.b;
3015              bd->y = bd->y + bd->client.h;
3016              bd->changes.pos = 1;
3017           }
3018         else if (bd->shade.dir == E_DIRECTION_LEFT)
3019           {
3020              bd->w = bd->client_inset.l + bd->client_inset.r;
3021           }
3022         else if (bd->shade.dir == E_DIRECTION_RIGHT)
3023           {
3024              bd->w = bd->client_inset.l + bd->client_inset.r;
3025              bd->x = bd->x + bd->client.w;
3026              bd->changes.pos = 1;
3027           }
3028
3029         if ((bd->shaped) || (bd->client.shaped))
3030           {
3031              bd->need_shape_merge = 1;
3032              bd->need_shape_export = 1;
3033           }
3034         if (bd->shaped_input)
3035           {
3036              bd->need_shape_merge = 1;
3037           }
3038
3039         bd->changes.size = 1;
3040         bd->shaded = 1;
3041         bd->changes.shaded = 1;
3042         bd->changed = 1;
3043         edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
3044         e_border_frame_recalc(bd);
3045         ev = E_NEW(E_Event_Border_Resize, 1);
3046         ev->border = bd;
3047         /* The resize is added in the animator when animation complete */
3048         /* For non-animated, we add it immediately with the new size */
3049         e_object_ref(E_OBJECT(bd));
3050         //           e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
3051         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
3052      }
3053
3054    e_remember_update(bd);
3055 }
3056
3057 EAPI void
3058 e_border_unshade(E_Border   *bd,
3059                  E_Direction dir)
3060 {
3061    E_Event_Border_Resize *ev;
3062    Eina_List *l;
3063    E_Border *tmp;
3064
3065    E_OBJECT_CHECK(bd);
3066    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3067    if ((!bd->shaded) || (bd->shading))
3068      return;
3069
3070    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
3071      ecore_x_window_show(tmp->win);
3072
3073    ecore_x_window_shadow_tree_flush();
3074
3075    bd->shade.dir = dir;
3076
3077    e_hints_window_shaded_set(bd, 0);
3078    e_hints_window_shade_direction_set(bd, dir);
3079
3080    if (bd->shade.dir == E_DIRECTION_UP ||
3081        bd->shade.dir == E_DIRECTION_LEFT)
3082      {
3083         bd->shade.x = bd->x;
3084         bd->shade.y = bd->y;
3085      }
3086    else
3087      {
3088         bd->shade.x = bd->x - bd->client.w;
3089         bd->shade.y = bd->y - bd->client.h;
3090      }
3091    if (e_config->border_shade_animate)
3092      {
3093         bd->shade.start = ecore_loop_time_get();
3094         bd->shading = 1;
3095         bd->changes.shading = 1;
3096         bd->changed = 1;
3097
3098         if (bd->shade.dir == E_DIRECTION_UP)
3099           {
3100              ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_SW);
3101              ecore_x_window_move_resize(bd->client.win, 0,
3102                                         bd->h - (bd->client_inset.t + bd->client_inset.b) -
3103                                         bd->client.h,
3104                                         bd->client.w, bd->client.h);
3105           }
3106         else if (bd->shade.dir == E_DIRECTION_LEFT)
3107           {
3108              ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_SW);
3109              ecore_x_window_move_resize(bd->client.win,
3110                                         bd->w - (bd->client_inset.l + bd->client_inset.r) -
3111                                         bd->client.h,
3112                                         0, bd->client.w, bd->client.h);
3113           }
3114         else
3115           ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NE);
3116
3117         bd->shade.anim = ecore_animator_add(_e_border_shade_animator, bd);
3118         edje_object_signal_emit(bd->bg_object, "e,state,unshading", "e");
3119      }
3120    else
3121      {
3122         if (bd->shade.dir == E_DIRECTION_UP)
3123           {
3124              bd->h = bd->client_inset.t + bd->client.h + bd->client_inset.b;
3125           }
3126         else if (bd->shade.dir == E_DIRECTION_DOWN)
3127           {
3128              bd->h = bd->client_inset.t + bd->client.h + bd->client_inset.b;
3129              bd->y = bd->y - bd->client.h;
3130              bd->changes.pos = 1;
3131           }
3132         else if (bd->shade.dir == E_DIRECTION_LEFT)
3133           {
3134              bd->w = bd->client_inset.l + bd->client.w + bd->client_inset.r;
3135           }
3136         else if (bd->shade.dir == E_DIRECTION_RIGHT)
3137           {
3138              bd->w = bd->client_inset.l + bd->client.w + bd->client_inset.r;
3139              bd->x = bd->x - bd->client.w;
3140              bd->changes.pos = 1;
3141           }
3142         if ((bd->shaped) || (bd->client.shaped))
3143           {
3144              bd->need_shape_merge = 1;
3145              bd->need_shape_export = 1;
3146           }
3147         if (bd->shaped_input)
3148           {
3149              bd->need_shape_merge = 1;
3150           }
3151
3152         bd->changes.size = 1;
3153         bd->shaded = 0;
3154         bd->changes.shaded = 1;
3155         bd->changed = 1;
3156         edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
3157         e_border_frame_recalc(bd);
3158         ev = E_NEW(E_Event_Border_Resize, 1);
3159         ev->border = bd;
3160         /* The resize is added in the animator when animation complete */
3161         /* For non-animated, we add it immediately with the new size */
3162         e_object_ref(E_OBJECT(bd));
3163         //           e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
3164         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
3165      }
3166
3167    e_remember_update(bd);
3168 }
3169
3170 static void
3171 _e_border_client_inset_calc(E_Border *bd)
3172 {
3173    /* int w, h; */
3174    Evas_Coord cx, cy, cw, ch;
3175
3176    if (bd->bg_object)
3177      {
3178         evas_object_resize(bd->bg_object, 1000, 1000);
3179         edje_object_message_signal_process(bd->bg_object);
3180         edje_object_calc_force(bd->bg_object);
3181         edje_object_part_geometry_get(bd->bg_object, "e.swallow.client", &cx, &cy, &cw, &ch);
3182         bd->client_inset.l = cx;
3183         bd->client_inset.r = 1000 - (cx + cw);
3184         bd->client_inset.t = cy;
3185         bd->client_inset.b = 1000 - (cy + ch);
3186      }
3187    else
3188      {
3189         bd->client_inset.l = 0;
3190         bd->client_inset.r = 0;
3191         bd->client_inset.t = 0;
3192         bd->client_inset.b = 0;
3193      }
3194
3195    ecore_x_netwm_frame_size_set(bd->client.win,
3196                                 bd->client_inset.l, bd->client_inset.r,
3197                                 bd->client_inset.t, bd->client_inset.b);
3198    ecore_x_e_frame_size_set(bd->client.win,
3199                             bd->client_inset.l, bd->client_inset.r,
3200                             bd->client_inset.t, bd->client_inset.b);
3201 }
3202
3203 static void
3204 _e_border_maximize(E_Border *bd, E_Maximize max)
3205 {
3206    int x1, yy1, x2, y2;
3207    int w, h, pw, ph;
3208    int zx, zy, zw, zh;
3209 #ifdef _F_USE_BOTTOM_TOP_MAXIMIZE
3210    int cy = 0;
3211 #endif
3212
3213    zx = zy = zw = zh = 0;
3214
3215    switch (max & E_MAXIMIZE_TYPE)
3216      {
3217       case E_MAXIMIZE_NONE:
3218          /* Ignore */
3219          break;
3220
3221       case E_MAXIMIZE_FULLSCREEN:
3222          w = bd->zone->w;
3223          h = bd->zone->h;
3224
3225          if (bd->bg_object)
3226            {
3227               edje_object_signal_emit(bd->bg_object, "e,action,maximize,fullscreen", "e");
3228               _e_border_client_inset_calc(bd);
3229            }
3230          e_border_resize_limit(bd, &w, &h);
3231          /* center x-direction */
3232          x1 = bd->zone->x + (bd->zone->w - w) / 2;
3233          /* center y-direction */
3234          yy1 = bd->zone->y + (bd->zone->h - h) / 2;
3235
3236 #ifdef _F_USE_BOTTOM_TOP_MAXIMIZE
3237          cy = bd->zone->y + (bd->zone->h / 2);
3238 #endif
3239
3240          switch (max & E_MAXIMIZE_DIRECTION)
3241            {
3242             case E_MAXIMIZE_BOTH:
3243               e_border_move_resize(bd, x1, yy1, w, h);
3244               break;
3245
3246             case E_MAXIMIZE_VERTICAL:
3247               e_border_move_resize(bd, bd->x, yy1, bd->w, h);
3248               break;
3249
3250             case E_MAXIMIZE_HORIZONTAL:
3251               e_border_move_resize(bd, x1, bd->y, w, bd->h);
3252               break;
3253
3254             case E_MAXIMIZE_LEFT:
3255               e_border_move_resize(bd, bd->zone->x, bd->zone->y, w / 2, h);
3256               break;
3257
3258             case E_MAXIMIZE_RIGHT:
3259               e_border_move_resize(bd, x1, bd->zone->y, w / 2, h);
3260               break;
3261 #ifdef _F_USE_BOTTOM_TOP_MAXIMIZE
3262             case E_MAXIMIZE_TOP:
3263               e_border_move_resize(bd, bd->zone->x, bd->zone->y, w, h / 2);
3264               break;
3265             case E_MAXIMIZE_BOTTOM:
3266               e_border_move_resize(bd, bd->zone->x, cy, w, h / 2);
3267               break;
3268 #endif
3269            }
3270          break;
3271
3272       case E_MAXIMIZE_SMART:
3273       case E_MAXIMIZE_EXPAND:
3274          if (bd->zone)
3275            e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
3276
3277          if (bd->w < zw)
3278            w = bd->w;
3279          else
3280            w = zw;
3281
3282          if (bd->h < zh)
3283            h = bd->h;
3284          else
3285            h = zh;
3286
3287          if (bd->x < zx) // window left not useful coordinates
3288            x1 = zx;
3289          else if (bd->x + bd->w > zx + zw) // window right not useful coordinates
3290            x1 = zx + zw - bd->w;
3291          else // window normal position
3292            x1 = bd->x;
3293
3294          if (bd->y < zy) // window top not useful coordinates
3295            yy1 = zy;
3296          else if (bd->y + bd->h > zy + zh) // window bottom not useful coordinates
3297            yy1 = zy + zh - bd->h;
3298          else // window normal position
3299            yy1 = bd->y;
3300
3301          switch (max & E_MAXIMIZE_DIRECTION)
3302            {
3303             case E_MAXIMIZE_BOTH:
3304               e_border_move_resize(bd, zx, zy, zw, zh);
3305               break;
3306
3307             case E_MAXIMIZE_VERTICAL:
3308               e_border_move_resize(bd, x1, zy, w, zh);
3309               break;
3310
3311             case E_MAXIMIZE_HORIZONTAL:
3312               e_border_move_resize(bd, zx, yy1, zw, h);
3313               break;
3314
3315             case E_MAXIMIZE_LEFT:
3316               e_border_move_resize(bd, zx, zy, zw / 2, zh);
3317               break;
3318
3319             case E_MAXIMIZE_RIGHT:
3320               e_border_move_resize(bd, zx + zw / 2, zy, zw / 2, zh);
3321               break;
3322            }
3323
3324          edje_object_signal_emit(bd->bg_object, "e,action,maximize", "e");
3325          break;
3326
3327       case E_MAXIMIZE_FILL:
3328          x1 = bd->zone->x;
3329          yy1 = bd->zone->y;
3330          x2 = bd->zone->x + bd->zone->w;
3331          y2 = bd->zone->y + bd->zone->h;
3332
3333          /* walk through all shelves */
3334          e_maximize_border_shelf_fill(bd, &x1, &yy1, &x2, &y2, max);
3335
3336          /* walk through all windows */
3337          e_maximize_border_border_fill(bd, &x1, &yy1, &x2, &y2, max);
3338
3339          w = x2 - x1;
3340          h = y2 - yy1;
3341          pw = w;
3342          ph = h;
3343          e_border_resize_limit(bd, &w, &h);
3344          /* center x-direction */
3345          x1 = x1 + (pw - w) / 2;
3346          /* center y-direction */
3347          yy1 = yy1 + (ph - h) / 2;
3348
3349          switch (max & E_MAXIMIZE_DIRECTION)
3350            {
3351             case E_MAXIMIZE_BOTH:
3352               e_border_move_resize(bd, x1, yy1, w, h);
3353               break;
3354
3355             case E_MAXIMIZE_VERTICAL:
3356               e_border_move_resize(bd, bd->x, yy1, bd->w, h);
3357               break;
3358
3359             case E_MAXIMIZE_HORIZONTAL:
3360               e_border_move_resize(bd, x1, bd->y, w, bd->h);
3361               break;
3362
3363             case E_MAXIMIZE_LEFT:
3364               e_border_move_resize(bd, bd->zone->x, bd->zone->y, w / 2, h);
3365               break;
3366
3367             case E_MAXIMIZE_RIGHT:
3368               e_border_move_resize(bd, x1, bd->zone->y, w / 2, h);
3369               break;
3370            }
3371          break;
3372      }
3373 }
3374
3375 EAPI void
3376 e_border_maximize(E_Border  *bd,
3377                   E_Maximize max)
3378 {
3379    E_OBJECT_CHECK(bd);
3380    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3381
3382    if (!(max & E_MAXIMIZE_DIRECTION)) max |= E_MAXIMIZE_BOTH;
3383
3384    if ((bd->shaded) || (bd->shading)) return;
3385    ecore_x_window_shadow_tree_flush();
3386    if (bd->fullscreen)
3387      e_border_unfullscreen(bd);
3388    /* Only allow changes in vertical/ horizontal maximization */
3389    if (((bd->maximized & E_MAXIMIZE_DIRECTION) == (max & E_MAXIMIZE_DIRECTION)) ||
3390        ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)) return;
3391    if (bd->new_client)
3392      {
3393         bd->need_maximize = 1;
3394         bd->maximized &= ~E_MAXIMIZE_TYPE;
3395         bd->maximized |= max;
3396         return;
3397      }
3398
3399    bd->pre_res_change.valid = 0;
3400    if (!(bd->maximized & E_MAXIMIZE_HORIZONTAL))
3401      {
3402         /* Horizontal hasn't been set */
3403         bd->saved.x = bd->x - bd->zone->x;
3404         bd->saved.w = bd->w;
3405      }
3406    if (!(bd->maximized & E_MAXIMIZE_VERTICAL))
3407      {
3408         /* Vertical hasn't been set */
3409         bd->saved.y = bd->y - bd->zone->y;
3410         bd->saved.h = bd->h;
3411      }
3412
3413    bd->saved.zone = bd->zone->num;
3414    e_hints_window_size_set(bd);
3415
3416    e_border_raise(bd);
3417
3418    _e_border_maximize(bd, max);
3419
3420
3421    /* Remove previous type */
3422    bd->maximized &= ~E_MAXIMIZE_TYPE;
3423    /* Add new maximization. It must be added, so that VERTICAL + HORIZONTAL == BOTH */
3424    bd->maximized |= max;
3425
3426    e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
3427                                 bd->maximized & E_MAXIMIZE_VERTICAL);
3428    e_remember_update(bd);
3429 }
3430
3431 EAPI void
3432 e_border_unmaximize(E_Border  *bd,
3433                     E_Maximize max)
3434 {
3435    E_OBJECT_CHECK(bd);
3436    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3437    if (!(max & E_MAXIMIZE_DIRECTION))
3438      {
3439         CRI("BUG: Unmaximize call without direction!");
3440         return;
3441      }
3442
3443    if ((bd->shaded) || (bd->shading)) return;
3444    ecore_x_window_shadow_tree_flush();
3445    /* Remove directions not used */
3446    max &= (bd->maximized & E_MAXIMIZE_DIRECTION);
3447    /* Can only remove existing maximization directions */
3448    if (!max) return;
3449    if (bd->maximized & E_MAXIMIZE_TYPE)
3450      {
3451         bd->pre_res_change.valid = 0;
3452         bd->need_maximize = 0;
3453
3454         if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN)
3455           {
3456              if (bd->bg_object)
3457                {
3458                   edje_object_signal_emit(bd->bg_object, "e,action,unmaximize,fullscreen", "e");
3459                   _e_border_client_inset_calc(bd);
3460                }
3461
3462              bd->maximized = E_MAXIMIZE_NONE;
3463              _e_border_move_resize_internal(bd,
3464                                             bd->zone->x + bd->saved.x,
3465                                             bd->zone->y + bd->saved.y,
3466                                             bd->saved.w, bd->saved.h, 0, 1);
3467              bd->saved.x = bd->saved.y = bd->saved.w = bd->saved.h = 0;
3468              e_hints_window_size_unset(bd);
3469           }
3470         else
3471           {
3472              int w, h, x, y;
3473
3474              w = bd->w;
3475              h = bd->h;
3476              x = bd->x;
3477              y = bd->y;
3478
3479              if (max & E_MAXIMIZE_VERTICAL)
3480                {
3481                   /* Remove vertical */
3482                   h = bd->saved.h;
3483                   y = bd->saved.y + bd->zone->y;
3484                   bd->saved.h = bd->saved.y = 0;
3485                   bd->maximized &= ~E_MAXIMIZE_VERTICAL;
3486                   bd->maximized &= ~E_MAXIMIZE_LEFT;
3487                   bd->maximized &= ~E_MAXIMIZE_RIGHT;
3488                }
3489              if (max & E_MAXIMIZE_HORIZONTAL)
3490                {
3491                   /* Remove horizontal */
3492                   w = bd->saved.w;
3493                   x = bd->saved.x + bd->zone->x;
3494                   bd->saved.w = bd->saved.x = 0;
3495                   bd->maximized &= ~E_MAXIMIZE_HORIZONTAL;
3496                }
3497
3498              e_border_resize_limit(bd, &w, &h);
3499
3500              if (!(bd->maximized & E_MAXIMIZE_DIRECTION))
3501                {
3502                   bd->maximized = E_MAXIMIZE_NONE;
3503                   _e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
3504                   e_hints_window_size_unset(bd);
3505                   edje_object_signal_emit(bd->bg_object, "e,action,unmaximize", "e");
3506                }
3507              else
3508                {
3509                   _e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
3510                   e_hints_window_size_set(bd);
3511                }
3512           }
3513         e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
3514                                      bd->maximized & E_MAXIMIZE_VERTICAL);
3515      }
3516    e_remember_update(bd);
3517 }
3518
3519 EAPI void
3520 e_border_fullscreen(E_Border    *bd,
3521                     E_Fullscreen policy)
3522 {
3523    E_Event_Border_Fullscreen *ev;
3524
3525    E_OBJECT_CHECK(bd);
3526    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3527
3528    if ((bd->shaded) || (bd->shading)) return;
3529    ecore_x_window_shadow_tree_flush();
3530    if (bd->new_client)
3531      {
3532         bd->need_fullscreen = 1;
3533         return;
3534      }
3535    if (!bd->fullscreen)
3536      {
3537         bd->pre_res_change.valid = 0;
3538
3539         bd->saved.x = bd->x - bd->zone->x;
3540         bd->saved.y = bd->y - bd->zone->y;
3541         bd->saved.w = bd->client.w;
3542         bd->saved.h = bd->client.h;
3543         bd->saved.maximized = bd->maximized;
3544         bd->saved.zone = bd->zone->num;
3545
3546         if (bd->maximized)
3547           e_border_unmaximize(bd, E_MAXIMIZE_BOTH);
3548         e_hints_window_size_set(bd);
3549
3550         bd->client_inset.l = 0;
3551         bd->client_inset.r = 0;
3552         bd->client_inset.t = 0;
3553         bd->client_inset.b = 0;
3554
3555         bd->desk->fullscreen_borders++;
3556
3557         /* e_zone_fullscreen_set(bd->zone, 1); */
3558         bd->saved.layer = bd->layer;
3559         if (!e_config->allow_above_fullscreen)
3560           e_border_layer_set(bd, 250);
3561
3562         if ((eina_list_count(bd->zone->container->zones) > 1) ||
3563             (policy == E_FULLSCREEN_RESIZE) || (!ecore_x_randr_query()))
3564           {
3565              e_border_move_resize(bd, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h);
3566           }
3567         else if (policy == E_FULLSCREEN_ZOOM)
3568           {
3569              Ecore_X_Randr_Screen_Size_MM *sizes;
3570              int num_sizes, i, best_size_index = 0;
3571
3572              ecore_x_randr_screen_primary_output_current_size_get(bd->zone->container->manager->root,
3573                                                                   &screen_size.width,
3574                                                                   &screen_size.height,
3575                                                                   NULL, NULL, NULL);
3576              sizes = ecore_x_randr_screen_primary_output_sizes_get(bd->zone->container->manager->root,
3577                                                                    &num_sizes);
3578              if (sizes)
3579                {
3580                   Ecore_X_Randr_Screen_Size best_size = { -1, -1 };
3581                   int best_dist = INT_MAX, dist;
3582
3583                   for (i = 0; i < num_sizes; i++)
3584                     {
3585                        if ((sizes[i].width > bd->w) && (sizes[i].height > bd->h))
3586                          {
3587                             dist = (sizes[i].width * sizes[i].height) - (bd->w * bd->h);
3588                             if (dist < best_dist)
3589                               {
3590                                  best_size.width = sizes[i].width;
3591                                  best_size.height = sizes[i].height;
3592                                  best_dist = dist;
3593                                  best_size_index = i;
3594                               }
3595                          }
3596                     }
3597                   if (((best_size.width != -1) && (best_size.height != -1)) &&
3598                       ((best_size.width != screen_size.width) ||
3599                        (best_size.height != screen_size.height)))
3600                     {
3601                        if (ecore_x_randr_screen_primary_output_size_set(bd->zone->container->manager->root,
3602                                                                         best_size_index))
3603                          screen_size_index = best_size_index;
3604                        e_border_move_resize(bd, 0, 0, best_size.width, best_size.height);
3605                     }
3606                   else
3607                     {
3608                        screen_size.width = -1;
3609                        screen_size.height = -1;
3610                        e_border_move_resize(bd, 0, 0, bd->zone->w, bd->zone->h);
3611                     }
3612                   free(sizes);
3613                }
3614              else
3615                e_border_move_resize(bd, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h);
3616           }
3617         bd->fullscreen = 1;
3618
3619         e_hints_window_fullscreen_set(bd, 1);
3620         e_hints_window_size_unset(bd);
3621         bd->client.border.changed = 1;
3622         bd->changed = 1;
3623      }
3624    bd->fullscreen_policy = policy;
3625
3626    ev = E_NEW(E_Event_Border_Fullscreen, 1);
3627    ev->border = bd;
3628    e_object_ref(E_OBJECT(bd));
3629    //   e_object_breadcrumb_add(E_OBJECT(bd), "border_fullscreen_event");
3630    ecore_event_add(E_EVENT_BORDER_FULLSCREEN, ev, _e_border_event_border_fullscreen_free, NULL);
3631
3632    e_remember_update(bd);
3633 }
3634
3635 EAPI void
3636 e_border_unfullscreen(E_Border *bd)
3637 {
3638    E_Event_Border_Unfullscreen *ev;
3639
3640    E_OBJECT_CHECK(bd);
3641    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3642    if ((bd->shaded) || (bd->shading)) return;
3643    ecore_x_window_shadow_tree_flush();
3644    if (bd->fullscreen)
3645      {
3646         bd->pre_res_change.valid = 0;
3647         bd->fullscreen = 0;
3648         bd->need_fullscreen = 0;
3649         bd->desk->fullscreen_borders--;
3650
3651         if ((screen_size.width != -1) && (screen_size.height != -1))
3652           {
3653              ecore_x_randr_screen_primary_output_size_set(bd->zone->container->manager->root,
3654                                                           screen_size_index);
3655              screen_size.width = -1;
3656              screen_size.height = -1;
3657           }
3658         e_border_move_resize(bd,
3659                              bd->saved.x + bd->zone->x,
3660                              bd->saved.y + bd->zone->y,
3661                              bd->saved.w, bd->saved.h);
3662
3663         if (bd->saved.maximized)
3664           e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) |
3665                             bd->saved.maximized);
3666
3667         e_border_layer_set(bd, bd->saved.layer);
3668
3669         e_hints_window_fullscreen_set(bd, 0);
3670         bd->client.border.changed = 1;
3671         bd->changed = 1;
3672      }
3673    bd->fullscreen_policy = 0;
3674
3675    ev = E_NEW(E_Event_Border_Unfullscreen, 1);
3676    ev->border = bd;
3677    e_object_ref(E_OBJECT(bd));
3678    //   e_object_breadcrumb_add(E_OBJECT(bd), "border_unfullscreen_event");
3679    ecore_event_add(E_EVENT_BORDER_UNFULLSCREEN, ev, _e_border_event_border_unfullscreen_free, NULL);
3680
3681    e_remember_update(bd);
3682 }
3683
3684 EAPI void
3685 e_border_iconify(E_Border *bd)
3686 {
3687    E_Event_Border_Iconify *ev;
3688    unsigned int iconic;
3689
3690    E_OBJECT_CHECK(bd);
3691    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3692    if (bd->shading) return;
3693    ecore_x_window_shadow_tree_flush();
3694    if (!bd->iconic)
3695      {
3696         bd->iconic = 1;
3697         e_border_hide(bd, 1);
3698         if (bd->fullscreen) bd->desk->fullscreen_borders--;
3699         edje_object_signal_emit(bd->bg_object, "e,action,iconify", "e");
3700      }
3701    iconic = 1;
3702    e_hints_window_iconic_set(bd);
3703    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &iconic, 1);
3704
3705    ev = E_NEW(E_Event_Border_Iconify, 1);
3706    ev->border = bd;
3707    e_object_ref(E_OBJECT(bd));
3708 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_iconify_event");
3709    ecore_event_add(E_EVENT_BORDER_ICONIFY, ev, _e_border_event_border_iconify_free, NULL);
3710
3711    if (e_config->transient.iconify)
3712      {
3713         Eina_List *l;
3714         E_Border *child;
3715         Eina_List *list = _e_border_sub_borders_new(bd);
3716
3717         EINA_LIST_FOREACH(list, l, child)
3718           {
3719              e_border_iconify(child);
3720           }
3721         eina_list_free(list);
3722      }
3723    e_remember_update(bd);
3724 }
3725
3726 #ifdef _F_DEICONIFY_APPROVE_
3727 static Eina_Bool
3728 _e_border_uniconify_timeout(void *data)
3729 {
3730    E_Border *bd;
3731    E_Border *child_bd;
3732
3733    bd = data;
3734
3735    if (!e_object_is_del(E_OBJECT(bd)))
3736      {
3737         ELB(ELBT_BD, "TIMEOUT UNICONIFY_APPROVE", bd->client.win);
3738         bd->client.e.state.deiconify_approve.render_done = 1;
3739         if (bd->client.e.state.deiconify_approve.req_list)
3740           {
3741              EINA_LIST_FREE(bd->client.e.state.deiconify_approve.req_list, child_bd)
3742                {
3743                   child_bd->client.e.state.deiconify_approve.render_done = 1;
3744                   child_bd->client.e.state.deiconify_approve.ancestor = NULL;
3745                }
3746           }
3747         bd->client.e.state.deiconify_approve.req_list = NULL;
3748         bd->client.e.state.deiconify_approve.wait_timer = NULL;
3749         e_border_uniconify(bd);
3750      }
3751
3752    return ECORE_CALLBACK_CANCEL;
3753 }
3754
3755 static void
3756 _e_border_deiconify_approve_send(E_Border *bd, E_Border *bd_ancestor)
3757 {
3758    if (!bd || !bd_ancestor) return;
3759
3760    if (e_config->deiconify_approve)
3761      {
3762         if (e_config->transient.iconify)
3763           {
3764              Eina_List *l;
3765              E_Border *child;
3766              Eina_List *list = _e_border_sub_borders_new(bd);
3767              EINA_LIST_FOREACH(list, l, child)
3768                {
3769 #ifdef _F_ZONE_WINDOW_ROTATION_
3770                   if ((e_config->wm_win_rotation) &&
3771                       ((child->client.e.state.rot.support) ||
3772                        (child->client.e.state.rot.app_set)))
3773                     {
3774                        ELB(ELBT_ROT, "CHECK_DEICONIFY CHILD", child->client.win);
3775                        int rotation = _e_border_rotation_angle_get(bd);
3776                        if (rotation != -1) e_border_rotation_set(bd, rotation);
3777                     }
3778 #endif
3779                   _e_border_deiconify_approve_send(child, bd_ancestor);
3780                   if (child->client.e.state.deiconify_approve.support)
3781                     {
3782                        ELBF(ELBT_BD, 0, child->client.win,
3783                             "SEND DEICONIFY_APPROVE. ancestor:%x", bd_ancestor->client.win);
3784
3785                        ecore_x_client_message32_send(child->client.win,
3786                                                      ECORE_X_ATOM_E_DEICONIFY_APPROVE,
3787                                                      ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
3788                                                      child->client.win, 0, 0, 0, 0);
3789                        child->client.e.state.deiconify_approve.ancestor = bd_ancestor;
3790                        bd_ancestor->client.e.state.deiconify_approve.req_list = eina_list_append(bd_ancestor->client.e.state.deiconify_approve.req_list, child);
3791                     }
3792                }
3793              eina_list_free(list);
3794           }
3795      }
3796 }
3797
3798 static void
3799 _e_border_deiconify_approve_send_all_transient(E_Border *bd)
3800 {
3801    E_Border *bd_ancestor;
3802    bd_ancestor = bd;
3803
3804    if (e_config->deiconify_approve)
3805      {
3806 #ifdef _F_ZONE_WINDOW_ROTATION_
3807         if ((e_config->wm_win_rotation) &&
3808             ((bd->client.e.state.rot.support) ||
3809              (bd->client.e.state.rot.app_set)))
3810           {
3811              ELB(ELBT_ROT, "CHECK_DEICONIFY", bd->client.win);
3812              int rotation = _e_border_rotation_angle_get(bd);
3813              if (rotation != -1) e_border_rotation_set(bd, rotation);
3814           }
3815 #endif
3816
3817         if (e_config->transient.iconify)
3818           {
3819              _e_border_deiconify_approve_send(bd, bd_ancestor);
3820           }
3821
3822         if (bd->client.e.state.deiconify_approve.support)
3823           {
3824              ELBF(ELBT_BD, 0, bd->client.win,
3825                   "SEND DEICONIFY_APPROVE.. ancestor:%x", bd_ancestor->client.win);
3826
3827              ecore_x_client_message32_send(bd->client.win,
3828                                            ECORE_X_ATOM_E_DEICONIFY_APPROVE,
3829                                            ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
3830                                            bd->client.win, 0, 0, 0, 0);
3831              bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd);
3832           }
3833      }
3834 }
3835 #endif
3836
3837 EAPI void
3838 e_border_uniconify(E_Border *bd)
3839 {
3840    E_Desk *desk;
3841    E_Event_Border_Uniconify *ev;
3842    unsigned int iconic;
3843
3844    E_OBJECT_CHECK(bd);
3845    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3846
3847 #ifdef _F_DEICONIFY_APPROVE_
3848    if (e_config->deiconify_approve)
3849      {
3850         if (bd->client.e.state.deiconify_approve.support)
3851           {
3852              if (bd->client.e.state.deiconify_approve.wait_timer)
3853                {
3854                   ELB(ELBT_BD, "DEICONIFY_APPROVE WAIT_TIMER is already running", bd->client.win);
3855                   return;
3856                }
3857              if (bd->client.e.state.deiconify_approve.render_done == 0)
3858                {
3859                   ELB(ELBT_BD, "DEICONIFY_APPROVE to all transient", bd->client.win);
3860                   _e_border_deiconify_approve_send_all_transient(bd);
3861                   return;
3862                }
3863           }
3864         bd->client.e.state.deiconify_approve.render_done = 0;
3865      }
3866 #endif
3867
3868 #if _F_ZONE_WINDOW_ROTATION_
3869    if (!bd->client.win)
3870      {
3871         ELB(ELBT_DFT, "ERR! obj is already deleted", bd->client.win);
3872         return;
3873      }
3874 #endif
3875
3876    if (bd->shading) return;
3877    ecore_x_window_shadow_tree_flush();
3878    e_border_show(bd);
3879    if (bd->iconic)
3880      {
3881         bd->iconic = 0;
3882         if (bd->fullscreen) bd->desk->fullscreen_borders++;
3883         desk = e_desk_current_get(bd->desk->zone);
3884 #ifdef _F_USE_EXTENDED_ICONIFY_
3885         if (e_manager_comp_evas_get(bd->zone->container->manager))
3886           {
3887              if (bd->await_hide_event > 0)
3888                bd->await_hide_event--;
3889           }
3890 #endif
3891         e_border_desk_set(bd, desk);
3892         e_border_raise(bd);
3893         edje_object_signal_emit(bd->bg_object, "e,action,uniconify", "e");
3894      }
3895    iconic = 0;
3896    ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &iconic, 1);
3897
3898    ev = E_NEW(E_Event_Border_Uniconify, 1);
3899    ev->border = bd;
3900    e_object_ref(E_OBJECT(bd));
3901 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_uniconify_event");
3902    ecore_event_add(E_EVENT_BORDER_UNICONIFY, ev, _e_border_event_border_uniconify_free, NULL);
3903
3904    if (e_config->transient.iconify)
3905      {
3906         Eina_List *l;
3907         E_Border *child;
3908         Eina_List *list = _e_border_sub_borders_new(bd);
3909
3910         EINA_LIST_FOREACH(list, l, child)
3911           {
3912              e_border_uniconify(child);
3913           }
3914         eina_list_free(list);
3915      }
3916    e_remember_update(bd);
3917 }
3918
3919 EAPI void
3920 e_border_stick(E_Border *bd)
3921 {
3922    E_Event_Border_Stick *ev;
3923
3924    E_OBJECT_CHECK(bd);
3925    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3926    if (bd->sticky) return;
3927    bd->sticky = 1;
3928    e_hints_window_sticky_set(bd, 1);
3929    e_border_show(bd);
3930
3931    if (e_config->transient.desktop)
3932      {
3933         Eina_List *l;
3934         E_Border *child;
3935         Eina_List *list = _e_border_sub_borders_new(bd);
3936
3937         EINA_LIST_FOREACH(list, l, child)
3938           {
3939              child->sticky = 1;
3940              e_hints_window_sticky_set(child, 1);
3941              e_border_show(child);
3942           }
3943         eina_list_free(list);
3944      }
3945
3946    edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
3947    ev = E_NEW(E_Event_Border_Stick, 1);
3948    ev->border = bd;
3949    e_object_ref(E_OBJECT(bd));
3950 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_stick_event");
3951    ecore_event_add(E_EVENT_BORDER_STICK, ev, _e_border_event_border_stick_free, NULL);
3952    e_remember_update(bd);
3953 }
3954
3955 EAPI void
3956 e_border_unstick(E_Border *bd)
3957 {
3958    E_Event_Border_Unstick *ev;
3959
3960    E_OBJECT_CHECK(bd);
3961    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
3962    /* Set the desk before we unstick the border */
3963    if (!bd->sticky) return;
3964    bd->sticky = 0;
3965    e_hints_window_sticky_set(bd, 0);
3966
3967    if (e_config->transient.desktop)
3968      {
3969         Eina_List *l;
3970         E_Border *child;
3971         Eina_List *list = _e_border_sub_borders_new(bd);
3972
3973         EINA_LIST_FOREACH(list, l, child)
3974           {
3975              child->sticky = 0;
3976              e_hints_window_sticky_set(child, 0);
3977           }
3978         eina_list_free(list);
3979      }
3980
3981    edje_object_signal_emit(bd->bg_object, "e,state,unsticky", "e");
3982    ev = E_NEW(E_Event_Border_Unstick, 1);
3983    ev->border = bd;
3984    e_object_ref(E_OBJECT(bd));
3985 //   e_object_breadcrumb_add(E_OBJECT(bd), "border_unstick_event");
3986    ecore_event_add(E_EVENT_BORDER_UNSTICK, ev, _e_border_event_border_unstick_free, NULL);
3987
3988    e_border_desk_set(bd, e_desk_current_get(bd->zone));
3989    e_remember_update(bd);
3990 }
3991
3992 EAPI void
3993 e_border_pinned_set(E_Border *bd,
3994                     int       set)
3995 {
3996    int layer;
3997    int stacking;
3998
3999    if (bd)
4000      {
4001         bd->borderless = set;
4002         bd->user_skip_winlist = set;
4003         if (set)
4004           {
4005              layer = 50;
4006              stacking = E_STACKING_BELOW;
4007           }
4008         else
4009           {
4010              layer = 100;
4011              stacking = E_STACKING_NONE;
4012           }
4013
4014         e_border_layer_set(bd, layer);
4015         e_hints_window_stacking_set(bd, stacking);
4016
4017         bd->client.border.changed = 1;
4018         bd->changed = 1;
4019      }
4020 }
4021
4022 EAPI E_Border *
4023 e_border_find_by_client_window(Ecore_X_Window win)
4024 {
4025    E_Border *bd;
4026
4027    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4028    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4029        (bd->client.win == win))
4030      return bd;
4031    return NULL;
4032 }
4033
4034 EAPI E_Border *
4035 e_border_find_all_by_client_window(Ecore_X_Window win)
4036 {
4037    E_Border *bd;
4038
4039    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4040    if ((bd) && (bd->client.win == win))
4041      return bd;
4042    return NULL;
4043 }
4044
4045 EAPI E_Border *
4046 e_border_find_by_frame_window(Ecore_X_Window win)
4047 {
4048    E_Border *bd;
4049
4050    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4051    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4052        (bd->bg_win == win))
4053      return bd;
4054    return NULL;
4055 }
4056
4057 EAPI E_Border *
4058 e_border_find_by_window(Ecore_X_Window win)
4059 {
4060    E_Border *bd;
4061
4062    bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
4063    if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4064        (bd->win == win))
4065      return bd;
4066    return NULL;
4067 }
4068
4069 EAPI E_Border *
4070 e_border_find_by_alarm(Ecore_X_Sync_Alarm al)
4071 {
4072    Eina_List *l;
4073    E_Border *bd;
4074
4075    EINA_LIST_FOREACH(borders, l, bd)
4076      {
4077         if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
4078             (bd->client.netwm.sync.alarm == al))
4079           return bd;
4080      }
4081    return NULL;
4082 }
4083
4084 EAPI E_Border *
4085 e_border_focused_get(void)
4086 {
4087    return focused;
4088 }
4089
4090 static void
4091 _e_border_shape_input_rectangle_set(E_Border* bd)
4092 {
4093    if (!bd) return;
4094
4095    if ((bd->visible) && (bd->shaped_input))
4096      {
4097         Ecore_X_Rectangle rects[4];
4098         Ecore_X_Window twin, twin2;
4099         int x, y;
4100
4101         twin = ecore_x_window_override_new(bd->zone->container->scratch_win,
4102                                            0, 0, bd->w, bd->h);
4103         rects[0].x = 0;
4104         rects[0].y = 0;
4105         rects[0].width = bd->w;
4106         rects[0].height = bd->client_inset.t;
4107         rects[1].x = 0;
4108         rects[1].y = bd->client_inset.t;
4109         rects[1].width = bd->client_inset.l;
4110         rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
4111         rects[2].x = bd->w - bd->client_inset.r;
4112         rects[2].y = bd->client_inset.t;
4113         rects[2].width = bd->client_inset.r;
4114         rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
4115         rects[3].x = 0;
4116         rects[3].y = bd->h - bd->client_inset.b;
4117         rects[3].width = bd->w;
4118         rects[3].height = bd->client_inset.b;
4119         ecore_x_window_shape_input_rectangles_set(twin, rects, 4);
4120
4121         twin2 = ecore_x_window_override_new
4122            (bd->zone->container->scratch_win, 0, 0,
4123                bd->w - bd->client_inset.l - bd->client_inset.r,
4124                bd->h - bd->client_inset.t - bd->client_inset.b);
4125         x = 0;
4126         y = 0;
4127         if ((bd->shading) || (bd->shaded))
4128           {
4129              if (bd->shade.dir == E_DIRECTION_UP)
4130                 y = bd->h - bd->client_inset.t - bd->client_inset.b -
4131                 bd->client.h;
4132              else if (bd->shade.dir == E_DIRECTION_LEFT)
4133                 x = bd->w - bd->client_inset.l - bd->client_inset.r -
4134                 bd->client.w;
4135           }
4136         ecore_x_window_shape_input_window_set_xy(twin2, bd->client.win,
4137                                                  x, y);
4138         ecore_x_window_shape_input_rectangle_clip(twin2, 0, 0,
4139                                                   bd->w - bd->client_inset.l - bd->client_inset.r,
4140                                                   bd->h - bd->client_inset.t - bd->client_inset.b);
4141         ecore_x_window_shape_input_window_add_xy(twin, twin2,
4142                                                  bd->client_inset.l,
4143                                                  bd->client_inset.t);
4144         ecore_x_window_shape_input_window_set(bd->win, twin);
4145         ecore_x_window_free(twin2);
4146         ecore_x_window_free(twin);
4147      }
4148    else
4149      {
4150         if (bd->visible) // not shaped input
4151           {
4152              if (!((bd->comp_hidden) || (bd->tmp_input_hidden > 0)))
4153                 ecore_x_composite_window_events_enable(bd->win);
4154              else
4155                 ecore_x_composite_window_events_disable(bd->win);
4156           }
4157         else
4158           {
4159              if (!e_manager_comp_evas_get(bd->zone->container->manager))
4160                 ecore_x_composite_window_events_enable(bd->win);
4161              else
4162                 ecore_x_composite_window_events_disable(bd->win);
4163           }
4164      }
4165 }
4166
4167 EAPI void
4168 e_border_idler_before(void)
4169 {
4170    Eina_List *ml, *cl;
4171    E_Manager *man;
4172    E_Container *con;
4173
4174    if (!borders)
4175      return;
4176
4177    EINA_LIST_FOREACH(e_manager_list(), ml, man)
4178      {
4179         EINA_LIST_FOREACH(man->containers, cl, con)
4180           {
4181              E_Border_List *bl;
4182              E_Border *bd;
4183
4184              // pass 1 - eval0. fetch properties on new or on change and
4185              // call hooks to decide what to do - maybe move/resize
4186              bl = e_container_border_list_last(con);
4187              while ((bd = e_container_border_list_prev(bl)))
4188                {
4189                   if (bd->changed) _e_border_eval0(bd);
4190                }
4191              e_container_border_list_free(bl);
4192
4193              // layout hook - this is where a hook gets to figure out what to
4194              // do if anything.
4195              _e_border_container_layout_hook(con);
4196
4197              // pass 2 - show windows needing show
4198              bl = e_container_border_list_last(con);
4199              while ((bd = e_container_border_list_prev(bl)))
4200                {
4201                   if ((bd->changes.visible) && (bd->visible) &&
4202                       (!bd->new_client) && (!bd->changes.pos) &&
4203                       (!bd->changes.size))
4204                     {
4205                        _e_border_show(bd);
4206                        bd->changes.visible = 0;
4207                     }
4208                }
4209              e_container_border_list_free(bl);
4210
4211              // pass 3 - hide windows needing hide and eval (main eval)
4212              bl = e_container_border_list_first(con);
4213              while ((bd = e_container_border_list_next(bl)))
4214                {
4215                   if (e_object_is_del(E_OBJECT(bd))) continue;
4216
4217                   if ((bd->changes.visible) && (!bd->visible))
4218                     {
4219                        _e_border_hide(bd);
4220                        bd->changes.visible = 0;
4221                     }
4222
4223                   if (bd->changed) _e_border_eval(bd);
4224
4225                   if ((bd->changes.visible) && (bd->visible))
4226                     {
4227                        _e_border_show(bd);
4228                        bd->changes.visible = 0;
4229                     }
4230                }
4231              e_container_border_list_free(bl);
4232           }
4233      }
4234
4235    if (focus_next)
4236      {
4237         E_Border *bd = NULL, *bd2;
4238
4239         EINA_LIST_FREE(focus_next, bd2)
4240           if ((!bd) && (bd2->visible)) bd = bd2;
4241
4242         if (!bd)
4243           {
4244              /* TODO revert focus when lost here ? */
4245              return;
4246           }
4247 #if 0
4248         if (bd == focused)
4249           {
4250              /* already focused. but anyway dont be so strict, this
4251                 fcks up illume setting focus on internal windows */
4252              return;
4253           }
4254 #endif
4255         
4256         focus_time = ecore_x_current_time_get();
4257
4258         focusing = bd;
4259
4260         if ((bd->client.icccm.take_focus) &&
4261             (bd->client.icccm.accepts_focus))
4262           {
4263              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_LOCALLY_ACTIVE);
4264              /* TODO what if the client didn't take focus ? */
4265           }
4266         else if (!bd->client.icccm.accepts_focus)
4267           {
4268              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_GLOBALLY_ACTIVE);
4269           }
4270         else if (!bd->client.icccm.take_focus)
4271           {
4272              e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_PASSIVE);
4273              /* e_border_focus_set(bd, 1, 0); */
4274           }
4275      }
4276
4277 #ifdef _F_ZONE_WINDOW_ROTATION_
4278    if ((e_config->wm_win_rotation) &&
4279        (rot.fetch))
4280      {
4281         Ecore_X_Event_Client_Message *msg = NULL;
4282         Ecore_X_Atom t = 0;
4283         EINA_LIST_FREE(rot.msgs, msg)
4284           {
4285              t = msg->message_type;
4286              if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE)
4287                {
4288                   if ((rot.vkbd_ctrl_win) &&
4289                       ((Ecore_X_Window)msg->data.l[0] == rot.vkbd_ctrl_win) &&
4290                       (rot.vkbd))
4291                     {
4292                        ELB(ELBT_BD, "GET KBD_ON_PREPARE_DONE", rot.vkbd_ctrl_win);
4293                        if (rot.vkbd_show_prepare_timer)
4294                          _e_border_vkbd_show(rot.vkbd);
4295                        else
4296                          ELB(ELBT_BD, "GET KBD_ON_PREPARE_DONE but skip", rot.vkbd_ctrl_win);
4297                     }
4298                }
4299              else if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE)
4300                {
4301                   if ((rot.vkbd_ctrl_win) &&
4302                       ((Ecore_X_Window)msg->data.l[0] == rot.vkbd_ctrl_win) &&
4303                       (rot.vkbd))
4304                     {
4305                        ELB(ELBT_BD, "GET KBD_OFF_PREPARE_DONE", rot.vkbd_ctrl_win);
4306                        if (rot.vkbd_hide_prepare_timer)
4307                          {
4308                             _e_border_vkbd_hide(rot.vkbd);
4309                             rot.vkbd_hide_prepare_timer = NULL;
4310                             e_object_unref(E_OBJECT(rot.vkbd));
4311                          }
4312                        else
4313                          ELB(ELBT_BD, "GET KBD_OFF_PREPARE_DONE but skip", rot.vkbd_ctrl_win);
4314                     }
4315                }
4316              else if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW)
4317                {
4318                   rot.vkbd_ctrl_win = msg->data.l[0];
4319                   ELB(ELBT_BD, "SET KBD_CONTROL_WIN", rot.vkbd_ctrl_win);
4320                }
4321              else if (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE)
4322                {
4323                   if ((rot.vkbd_ctrl_win) &&
4324                       (rot.vkbd_ctrl_win == (Ecore_X_Window)msg->data.l[0]))
4325                     {
4326                        ELB(ELBT_ROT, "GET ROT_PREPARE_DONE", rot.vkbd_ctrl_win);
4327                        E_Manager *m = e_manager_current_get();
4328                        E_Zone *zone = NULL;
4329                        if (m) zone = e_util_zone_current_get(m);
4330                        if ((zone) && (rot.wait_prepare_done))
4331                          {
4332                             if (rot.list)
4333                               {
4334                                  _e_border_rotation_change_request(zone);
4335                                  if (rot.prepare_timer)
4336                                    ecore_timer_del(rot.prepare_timer);
4337                                  rot.prepare_timer = NULL;
4338                                  rot.wait_prepare_done = EINA_FALSE;
4339
4340                               }
4341                          }
4342                     }
4343                }
4344              E_FREE(msg);
4345           }
4346         rot.msgs = NULL;
4347         rot.fetch = EINA_FALSE;
4348      }
4349 #endif
4350 }
4351
4352 EAPI Eina_List *
4353 e_border_client_list(void)
4354 {
4355    /* FIXME: This should be a somewhat ordered list */
4356    return borders;
4357 }
4358
4359 static Ecore_X_Window action_input_win = 0;
4360 static E_Border *action_border = NULL;
4361 static Ecore_Event_Handler *action_handler_key = NULL;
4362 static Ecore_Event_Handler *action_handler_mouse = NULL;
4363 static Ecore_Timer *action_timer = NULL;
4364 static Ecore_X_Rectangle action_orig;
4365
4366 static void
4367 _e_border_show(E_Border *bd)
4368 {
4369    Eina_List *l;
4370    E_Border *tmp;
4371
4372    ecore_evas_show(bd->bg_ecore_evas);
4373
4374    if (bd->post_job)
4375      {
4376         bd->post_show = 1;
4377         return;
4378      }
4379
4380    if (!((bd->comp_hidden) || (bd->tmp_input_hidden > 0)))
4381      {
4382         _e_border_shape_input_rectangle_set(bd);
4383         // not anymore
4384         //      ecore_x_composite_window_events_enable(bd->win);
4385         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
4386      }
4387
4388    ecore_x_window_show(bd->win);
4389
4390    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
4391      ecore_x_window_show(tmp->win);
4392 }
4393
4394 static void
4395 _e_border_hide(E_Border *bd)
4396 {
4397    E_Border *tmp;
4398    Eina_List *l;
4399
4400    if (!e_manager_comp_evas_get(bd->zone->container->manager))
4401      {
4402         ecore_x_window_hide(bd->win);
4403         ecore_evas_hide(bd->bg_ecore_evas);
4404
4405         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
4406           ecore_x_window_hide(tmp->win);
4407      }
4408    else
4409      {
4410         ecore_x_composite_window_events_disable(bd->win);
4411         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
4412      }
4413 }
4414
4415 static int
4416 _e_border_action_input_win_del(void)
4417 {
4418    if (!action_input_win)
4419      return 0;
4420
4421    e_grabinput_release(action_input_win, action_input_win);
4422    ecore_x_window_free(action_input_win);
4423    action_input_win = 0;
4424    return 1;
4425 }
4426
4427 static int
4428 _e_border_action_input_win_new(E_Border *bd)
4429 {
4430    if (!action_input_win)
4431      {
4432         Ecore_X_Window parent = bd->zone->container->win;
4433         action_input_win = ecore_x_window_input_new(parent, 0, 0, 1, 1);
4434         if (!action_input_win)
4435           return 0;
4436      }
4437
4438    ecore_x_window_show(action_input_win);
4439    if (e_grabinput_get(action_input_win, 0, action_input_win))
4440      return 1;
4441
4442    _e_border_action_input_win_del();
4443    return 0;
4444 }
4445
4446 static void
4447 _e_border_action_finish(void)
4448 {
4449    _e_border_action_input_win_del();
4450
4451    if (action_timer)
4452      {
4453         ecore_timer_del(action_timer);
4454         action_timer = NULL;
4455      }
4456
4457    if (action_handler_key)
4458      {
4459         ecore_event_handler_del(action_handler_key);
4460         action_handler_key = NULL;
4461      }
4462
4463    if (action_handler_mouse)
4464      {
4465         ecore_event_handler_del(action_handler_mouse);
4466         action_handler_mouse = NULL;
4467      }
4468
4469    action_border = NULL;
4470 }
4471
4472 static void
4473 _e_border_action_init(E_Border *bd)
4474 {
4475    action_orig.x = bd->x;
4476    action_orig.y = bd->y;
4477    action_orig.width = bd->w;
4478    action_orig.height = bd->h;
4479
4480    action_border = bd;
4481 }
4482
4483 static void
4484 _e_border_action_restore_orig(E_Border *bd)
4485 {
4486    if (action_border != bd)
4487      return;
4488
4489    e_border_move_resize(bd, action_orig.x, action_orig.y, action_orig.width, action_orig.height);
4490 }
4491
4492 static int
4493 _e_border_key_down_modifier_apply(int modifier,
4494                                   int value)
4495 {
4496    if (modifier & ECORE_EVENT_MODIFIER_CTRL)
4497      return value * 2;
4498    else if (modifier & ECORE_EVENT_MODIFIER_ALT)
4499      {
4500         value /= 2;
4501         if (value)
4502           return value;
4503         else
4504           return 1;
4505      }
4506
4507    return value;
4508 }
4509
4510 static Eina_Bool
4511 _e_border_action_move_timeout(void *data __UNUSED__)
4512 {
4513    _e_border_move_end(action_border);
4514    _e_border_action_finish();
4515    return ECORE_CALLBACK_CANCEL;
4516 }
4517
4518 static void
4519 _e_border_action_move_timeout_add(void)
4520 {
4521    if (action_timer)
4522      ecore_timer_del(action_timer);
4523    action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_border_action_move_timeout, NULL);
4524 }
4525
4526 static Eina_Bool
4527 _e_border_move_key_down(void *data __UNUSED__,
4528                         int type   __UNUSED__,
4529                         void      *event)
4530 {
4531    Ecore_Event_Key *ev = event;
4532    int x, y;
4533
4534    if (ev->event_window != action_input_win)
4535      return ECORE_CALLBACK_PASS_ON;
4536    if (!action_border)
4537      {
4538         fputs("ERROR: no action_border!\n", stderr);
4539         goto stop;
4540      }
4541
4542    x = action_border->x;
4543    y = action_border->y;
4544
4545    if ((strcmp(ev->key, "Up") == 0) || (strcmp(ev->key, "k") == 0))
4546      y -= _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dy);
4547    else if ((strcmp(ev->key, "Down") == 0) || (strcmp(ev->key, "j") == 0))
4548      y += _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dy);
4549    else if ((strcmp(ev->key, "Left") == 0) || (strcmp(ev->key, "h") == 0))
4550      x -= _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dx);
4551    else if ((strcmp(ev->key, "Right") == 0) || (strcmp(ev->key, "l") == 0))
4552      x += _e_border_key_down_modifier_apply(ev->modifiers, e_config->border_keyboard.move.dx);
4553    else if (strcmp(ev->key, "Return") == 0)
4554      goto stop;
4555    else if (strcmp(ev->key, "Escape") == 0)
4556      {
4557         _e_border_action_restore_orig(action_border);
4558         goto stop;
4559      }
4560    else if ((strncmp(ev->key, "Control", sizeof("Control") - 1) != 0) &&
4561             (strncmp(ev->key, "Alt", sizeof("Alt") - 1) != 0))
4562      goto stop;
4563
4564    e_border_move(action_border, x, y);
4565    _e_border_action_move_timeout_add();
4566
4567    return ECORE_CALLBACK_PASS_ON;
4568
4569 stop:
4570    _e_border_move_end(action_border);
4571    _e_border_action_finish();
4572    return ECORE_CALLBACK_DONE;
4573 }
4574
4575 static Eina_Bool
4576 _e_border_move_mouse_down(void *data __UNUSED__,
4577                           int type   __UNUSED__,
4578                           void      *event)
4579 {
4580    Ecore_Event_Mouse_Button *ev = event;
4581
4582    if (ev->event_window != action_input_win)
4583      return ECORE_CALLBACK_PASS_ON;
4584
4585    if (!action_border)
4586      fputs("ERROR: no action_border!\n", stderr);
4587
4588    _e_border_move_end(action_border);
4589    _e_border_action_finish();
4590    return ECORE_CALLBACK_DONE;
4591 }
4592
4593 EAPI void
4594 e_border_act_move_keyboard(E_Border *bd)
4595 {
4596    if (!bd)
4597      return;
4598
4599    if (!_e_border_move_begin(bd))
4600      return;
4601
4602    if (!_e_border_action_input_win_new(bd))
4603      {
4604         _e_border_move_end(bd);
4605         return;
4606      }
4607
4608    _e_border_action_init(bd);
4609    _e_border_action_move_timeout_add();
4610    _e_border_move_update(bd);
4611
4612    if (action_handler_key)
4613      ecore_event_handler_del(action_handler_key);
4614    action_handler_key = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_border_move_key_down, NULL);
4615
4616    if (action_handler_mouse)
4617      ecore_event_handler_del(action_handler_mouse);
4618    action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_move_mouse_down, NULL);
4619 }
4620
4621 static Eina_Bool
4622 _e_border_action_resize_timeout(void *data __UNUSED__)
4623 {
4624    _e_border_resize_end(action_border);
4625    _e_border_action_finish();
4626    return ECORE_CALLBACK_CANCEL;
4627 }
4628
4629 static void
4630 _e_border_action_resize_timeout_add(void)
4631 {
4632    if (action_timer)
4633      ecore_timer_del(action_timer);
4634    action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_border_action_resize_timeout, NULL);
4635 }
4636
4637 static Eina_Bool
4638 _e_border_resize_key_down(void *data __UNUSED__,
4639                           int type   __UNUSED__,
4640                           void      *event)
4641 {
4642    Ecore_Event_Key *ev = event;
4643    int w, h, dx, dy;
4644
4645    if (ev->event_window != action_input_win)
4646      return ECORE_CALLBACK_PASS_ON;
4647    if (!action_border)
4648      {
4649         fputs("ERROR: no action_border!\n", stderr);
4650         goto stop;
4651      }
4652
4653    w = action_border->w;
4654    h = action_border->h;
4655
4656    dx = e_config->border_keyboard.resize.dx;
4657    if (dx < action_border->client.icccm.step_w)
4658      dx = action_border->client.icccm.step_w;
4659    dx = _e_border_key_down_modifier_apply(ev->modifiers, dx);
4660    if (dx < action_border->client.icccm.step_w)
4661      dx = action_border->client.icccm.step_w;
4662
4663    dy = e_config->border_keyboard.resize.dy;
4664    if (dy < action_border->client.icccm.step_h)
4665      dy = action_border->client.icccm.step_h;
4666    dy = _e_border_key_down_modifier_apply(ev->modifiers, dy);
4667    if (dy < action_border->client.icccm.step_h)
4668      dy = action_border->client.icccm.step_h;
4669
4670    if ((strcmp(ev->key, "Up") == 0) || (strcmp(ev->key, "k") == 0))
4671      h -= dy;
4672    else if ((strcmp(ev->key, "Down") == 0) || (strcmp(ev->key, "j") == 0))
4673      h += dy;
4674    else if ((strcmp(ev->key, "Left") == 0) || (strcmp(ev->key, "h") == 0))
4675      w -= dx;
4676    else if ((strcmp(ev->key, "Right") == 0) || (strcmp(ev->key, "l") == 0))
4677      w += dx;
4678    else if (strcmp(ev->key, "Return") == 0)
4679      goto stop;
4680    else if (strcmp(ev->key, "Escape") == 0)
4681      {
4682         _e_border_action_restore_orig(action_border);
4683         goto stop;
4684      }
4685    else if ((strncmp(ev->key, "Control", sizeof("Control") - 1) != 0) &&
4686             (strncmp(ev->key, "Alt", sizeof("Alt") - 1) != 0))
4687      goto stop;
4688
4689    e_border_resize_limit(action_border, &w, &h);
4690    e_border_resize(action_border, w, h);
4691    _e_border_action_resize_timeout_add();
4692
4693    return ECORE_CALLBACK_PASS_ON;
4694
4695 stop:
4696    _e_border_resize_end(action_border);
4697    _e_border_action_finish();
4698    return ECORE_CALLBACK_DONE;
4699 }
4700
4701 static Eina_Bool
4702 _e_border_resize_mouse_down(void *data __UNUSED__,
4703                             int type   __UNUSED__,
4704                             void      *event)
4705 {
4706    Ecore_Event_Mouse_Button *ev = event;
4707
4708    if (ev->event_window != action_input_win)
4709      return ECORE_CALLBACK_PASS_ON;
4710
4711    if (!action_border)
4712      fputs("ERROR: no action_border!\n", stderr);
4713
4714    _e_border_resize_end(action_border);
4715    _e_border_action_finish();
4716    return ECORE_CALLBACK_DONE;
4717 }
4718
4719 EAPI void
4720 e_border_act_resize_keyboard(E_Border *bd)
4721 {
4722    if (!bd)
4723      return;
4724
4725    if (!_e_border_resize_begin(bd))
4726      return;
4727
4728    if (!_e_border_action_input_win_new(bd))
4729      {
4730         _e_border_resize_end(bd);
4731         return;
4732      }
4733
4734    _e_border_action_init(bd);
4735    _e_border_action_resize_timeout_add();
4736    _e_border_resize_update(bd);
4737
4738    if (action_handler_key)
4739      ecore_event_handler_del(action_handler_key);
4740    action_handler_key = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_border_resize_key_down, NULL);
4741
4742    if (action_handler_mouse)
4743      ecore_event_handler_del(action_handler_mouse);
4744    action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_resize_mouse_down, NULL);
4745 }
4746
4747 EAPI void
4748 e_border_act_move_begin(E_Border                 *bd,
4749                         Ecore_Event_Mouse_Button *ev)
4750 {
4751    E_OBJECT_CHECK(bd);
4752    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4753    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
4754    if (!_e_border_move_begin(bd))
4755      return;
4756
4757    e_zone_edge_disable();
4758    bd->moving = 1;
4759    _e_border_pointer_move_begin(bd);
4760    if (ev)
4761      {
4762         char source[256];
4763
4764         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->buttons);
4765         _e_border_moveinfo_gather(bd, source);
4766      }
4767 }
4768
4769 EAPI void
4770 e_border_act_move_end(E_Border                    *bd,
4771                       Ecore_Event_Mouse_Button *ev __UNUSED__)
4772 {
4773    E_OBJECT_CHECK(bd);
4774    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4775    if (!bd->moving) return;
4776    bd->moving = 0;
4777    _e_border_pointer_move_end(bd);
4778    e_zone_edge_enable();
4779    _e_border_move_end(bd);
4780    e_zone_flip_coords_handle(bd->zone, -1, -1);
4781 }
4782
4783 EAPI void
4784 e_border_act_resize_begin(E_Border                 *bd,
4785                           Ecore_Event_Mouse_Button *ev)
4786 {
4787    E_OBJECT_CHECK(bd);
4788    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4789    if (bd->lock_user_size) return;
4790    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
4791    if (!_e_border_resize_begin(bd))
4792      return;
4793    if (bd->mouse.current.mx < (bd->x + bd->w / 2))
4794      {
4795         if (bd->mouse.current.my < (bd->y + bd->h / 2))
4796           {
4797              bd->resize_mode = RESIZE_TL;
4798              GRAV_SET(bd, ECORE_X_GRAVITY_SE);
4799           }
4800         else
4801           {
4802              bd->resize_mode = RESIZE_BL;
4803              GRAV_SET(bd, ECORE_X_GRAVITY_NE);
4804           }
4805      }
4806    else
4807      {
4808         if (bd->mouse.current.my < (bd->y + bd->h / 2))
4809           {
4810              bd->resize_mode = RESIZE_TR;
4811              GRAV_SET(bd, ECORE_X_GRAVITY_SW);
4812           }
4813         else
4814           {
4815              bd->resize_mode = RESIZE_BR;
4816              GRAV_SET(bd, ECORE_X_GRAVITY_NW);
4817           }
4818      }
4819    _e_border_pointer_resize_begin(bd);
4820    if (ev)
4821      {
4822         char source[256];
4823
4824         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->buttons);
4825         _e_border_moveinfo_gather(bd, source);
4826      }
4827 }
4828
4829 EAPI void
4830 e_border_act_resize_end(E_Border                    *bd,
4831                         Ecore_Event_Mouse_Button *ev __UNUSED__)
4832 {
4833    E_OBJECT_CHECK(bd);
4834    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4835    if (bd->resize_mode != RESIZE_NONE)
4836      {
4837         _e_border_pointer_resize_end(bd);
4838         bd->resize_mode = RESIZE_NONE;
4839         _e_border_resize_end(bd);
4840         bd->changes.reset_gravity = 1;
4841         bd->changed = 1;
4842      }
4843 }
4844
4845 EAPI void
4846 e_border_act_menu_begin(E_Border                 *bd,
4847                         Ecore_Event_Mouse_Button *ev,
4848                         int                       key)
4849 {
4850    E_OBJECT_CHECK(bd);
4851    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4852    if (ev)
4853      {
4854         e_int_border_menu_show(bd,
4855                                bd->x + bd->fx.x + ev->x - bd->zone->container->x,
4856                                bd->y + bd->fx.y + ev->y - bd->zone->container->y, key,
4857                                ev->timestamp);
4858      }
4859    else
4860      {
4861         int x, y;
4862
4863         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
4864         e_int_border_menu_show(bd, x, y, key, 0);
4865      }
4866 }
4867
4868 EAPI void
4869 e_border_act_close_begin(E_Border *bd)
4870 {
4871    E_OBJECT_CHECK(bd);
4872    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4873    if (bd->lock_close) return;
4874    if (bd->client.icccm.delete_request)
4875      {
4876         bd->delete_requested = 1;
4877         ecore_x_window_delete_request_send(bd->client.win);
4878         if (bd->client.netwm.ping)
4879           e_border_ping(bd);
4880      }
4881    else if (e_config->kill_if_close_not_possible)
4882      {
4883         e_border_act_kill_begin(bd);
4884      }
4885 }
4886
4887 EAPI void
4888 e_border_act_kill_begin(E_Border *bd)
4889 {
4890    E_OBJECT_CHECK(bd);
4891    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
4892    if (bd->internal) return;
4893    if (bd->lock_close) return;
4894    if ((bd->client.netwm.pid > 1) && (e_config->kill_process))
4895      {
4896         kill(bd->client.netwm.pid, SIGINT);
4897         bd->kill_timer = ecore_timer_add(e_config->kill_timer_wait,
4898                                          _e_border_cb_kill_timer, bd);
4899      }
4900    else
4901      {
4902         if (!bd->internal) ecore_x_kill(bd->client.win);
4903      }
4904 }
4905
4906 EAPI Evas_Object *
4907 e_border_icon_add(E_Border *bd,
4908                   Evas     *evas)
4909 {
4910    Evas_Object *o;
4911
4912    E_OBJECT_CHECK_RETURN(bd, NULL);
4913    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, NULL);
4914
4915    o = NULL;
4916    if (bd->internal)
4917      {
4918         if (!bd->internal_icon)
4919           {
4920              o = e_icon_add(evas);
4921              e_util_icon_theme_set(o, "enlightenment");
4922           }
4923         else
4924           {
4925              if (!bd->internal_icon_key)
4926                {
4927                   char *ext;
4928
4929                   ext = strrchr(bd->internal_icon, '.');
4930                   if ((ext) && ((!strcmp(ext, ".edj"))))
4931                     {
4932                        o = edje_object_add(evas);
4933                        if (!edje_object_file_set(o, bd->internal_icon, "icon"))
4934                          e_util_icon_theme_set(o, "enlightenment");
4935                     }
4936                   else if (ext)
4937                     {
4938                        o = e_icon_add(evas);
4939                        e_icon_file_set(o, bd->internal_icon);
4940                     }
4941                   else
4942                     {
4943                        o = e_icon_add(evas);
4944                        if (!e_util_icon_theme_set(o, bd->internal_icon))
4945                          e_util_icon_theme_set(o, "enlightenment");
4946                     }
4947                }
4948              else
4949                {
4950                   o = edje_object_add(evas);
4951                   edje_object_file_set(o, bd->internal_icon,
4952                                        bd->internal_icon_key);
4953                }
4954           }
4955         return o;
4956      }
4957    if ((e_config->use_app_icon) && (bd->icon_preference != E_ICON_PREF_USER))
4958      {
4959         if (bd->client.netwm.icons)
4960           {
4961              o = e_icon_add(evas);
4962              e_icon_data_set(o, bd->client.netwm.icons[0].data,
4963                              bd->client.netwm.icons[0].width,
4964                              bd->client.netwm.icons[0].height);
4965              e_icon_alpha_set(o, 1);
4966              return o;
4967           }
4968      }
4969    if (!o)
4970      {
4971         if ((bd->desktop) && (bd->icon_preference != E_ICON_PREF_NETWM))
4972           {
4973              o = e_icon_add(evas);
4974              if (o)
4975                {
4976                   e_icon_fdo_icon_set(o, bd->desktop->icon);
4977                   return o;
4978                }
4979           }
4980         else if (bd->client.netwm.icons)
4981           {
4982              o = e_icon_add(evas);
4983              e_icon_data_set(o, bd->client.netwm.icons[0].data,
4984                              bd->client.netwm.icons[0].width,
4985                              bd->client.netwm.icons[0].height);
4986              e_icon_alpha_set(o, 1);
4987              return o;
4988           }
4989      }
4990
4991    o = e_icon_add(evas);
4992    e_util_icon_theme_set(o, "unknown");
4993    return o;
4994 }
4995
4996 EAPI void
4997 e_border_button_bindings_ungrab_all(void)
4998 {
4999    Eina_List *l;
5000    E_Border *bd;
5001
5002    EINA_LIST_FOREACH(borders, l, bd)
5003      {
5004         e_focus_setdown(bd);
5005         e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5006         e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5007      }
5008 }
5009
5010 EAPI void
5011 e_border_button_bindings_grab_all(void)
5012 {
5013    Eina_List *l;
5014    E_Border *bd;
5015
5016    EINA_LIST_FOREACH(borders, l, bd)
5017      {
5018         e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
5019         e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
5020         e_focus_setup(bd);
5021      }
5022 }
5023
5024 EAPI Eina_List *
5025 e_border_focus_stack_get(void)
5026 {
5027    return focus_stack;
5028 }
5029
5030 EAPI Eina_List *
5031 e_border_raise_stack_get(void)
5032 {
5033    return raise_stack;
5034 }
5035
5036 EAPI Eina_List *
5037 e_border_lost_windows_get(E_Zone *zone)
5038 {
5039    Eina_List *list = NULL, *l;
5040    E_Border *bd;
5041    int loss_overlap = 5;
5042
5043    E_OBJECT_CHECK_RETURN(zone, NULL);
5044    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
5045    EINA_LIST_FOREACH(borders, l, bd)
5046      {
5047         if (!bd->zone)
5048           continue;
5049
5050         if ((bd->zone != zone) ||
5051             (bd->zone->container != zone->container))
5052           continue;
5053
5054         if (!E_INTERSECTS(bd->zone->x + loss_overlap,
5055                           bd->zone->y + loss_overlap,
5056                           bd->zone->w - (2 * loss_overlap),
5057                           bd->zone->h - (2 * loss_overlap),
5058                           bd->x, bd->y, bd->w, bd->h))
5059           {
5060              list = eina_list_append(list, bd);
5061           }
5062         else if ((!E_CONTAINS(bd->zone->x, bd->zone->y,
5063                               bd->zone->w, bd->zone->h,
5064                               bd->x, bd->y, bd->w, bd->h)) &&
5065                  (bd->shaped))
5066           {
5067              Ecore_X_Rectangle *rect;
5068              int i, num;
5069
5070              rect = ecore_x_window_shape_rectangles_get(bd->win, &num);
5071              if (rect)
5072                {
5073                   int ok;
5074
5075                   ok = 0;
5076                   for (i = 0; i < num; i++)
5077                     {
5078                        if (E_INTERSECTS(bd->zone->x + loss_overlap,
5079                                         bd->zone->y + loss_overlap,
5080                                         bd->zone->w - (2 * loss_overlap),
5081                                         bd->zone->h - (2 * loss_overlap),
5082                                         rect[i].x, rect[i].y,
5083                                         (int)rect[i].width, (int)rect[i].height))
5084                          {
5085                             ok = 1;
5086                             break;
5087                          }
5088                     }
5089                   free(rect);
5090                   if (!ok)
5091                     list = eina_list_append(list, bd);
5092                }
5093           }
5094      }
5095    return list;
5096 }
5097
5098 EAPI void
5099 e_border_ping(E_Border *bd)
5100 {
5101    E_OBJECT_CHECK(bd);
5102    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5103    if (!e_config->ping_clients) return;
5104    bd->ping_ok = 0;
5105    ecore_x_netwm_ping_send(bd->client.win);
5106    bd->ping = ecore_loop_time_get();
5107    if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
5108    bd->ping_poller = ecore_poller_add(ECORE_POLLER_CORE,
5109                                       e_config->ping_clients_interval,
5110                                       _e_border_cb_ping_poller, bd);
5111 }
5112
5113 EAPI void
5114 e_border_move_cancel(void)
5115 {
5116    if (bdmove)
5117      {
5118         if (bdmove->cur_mouse_action)
5119           {
5120              E_Border *bd;
5121
5122              bd = bdmove;
5123              e_object_ref(E_OBJECT(bd));
5124              if (bd->cur_mouse_action->func.end_mouse)
5125                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", NULL);
5126              else if (bd->cur_mouse_action->func.end)
5127                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
5128              e_object_unref(E_OBJECT(bd->cur_mouse_action));
5129              bd->cur_mouse_action = NULL;
5130              e_object_unref(E_OBJECT(bd));
5131           }
5132         else
5133           _e_border_move_end(bdmove);
5134      }
5135 }
5136
5137 EAPI void
5138 e_border_resize_cancel(void)
5139 {
5140    if (bdresize)
5141      {
5142         if (bdresize->cur_mouse_action)
5143           {
5144              E_Border *bd;
5145
5146              bd = bdresize;
5147              e_object_ref(E_OBJECT(bd));
5148              if (bd->cur_mouse_action->func.end_mouse)
5149                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", NULL);
5150              else if (bd->cur_mouse_action->func.end)
5151                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
5152              e_object_unref(E_OBJECT(bd->cur_mouse_action));
5153              bd->cur_mouse_action = NULL;
5154              e_object_unref(E_OBJECT(bd));
5155           }
5156         else
5157           {
5158              bdresize->resize_mode = RESIZE_NONE;
5159              _e_border_resize_end(bdresize);
5160           }
5161      }
5162 }
5163
5164 EAPI void
5165 e_border_frame_recalc(E_Border *bd)
5166 {
5167    if (!bd->bg_object) return;
5168
5169    bd->w -= (bd->client_inset.l + bd->client_inset.r);
5170    bd->h -= (bd->client_inset.t + bd->client_inset.b);
5171
5172    _e_border_client_inset_calc(bd);
5173
5174    bd->w += (bd->client_inset.l + bd->client_inset.r);
5175    bd->h += (bd->client_inset.t + bd->client_inset.b);
5176
5177    bd->changed = 1;
5178    bd->changes.size = 1;
5179    if ((bd->shaped) || (bd->client.shaped))
5180      {
5181         bd->need_shape_merge = 1;
5182         bd->need_shape_export = 1;
5183      }
5184    if (bd->shaped_input)
5185      {
5186         bd->need_shape_merge = 1;
5187      }
5188    _e_border_client_move_resize_send(bd);
5189 }
5190
5191 EAPI Eina_List *
5192 e_border_immortal_windows_get(void)
5193 {
5194    Eina_List *list = NULL, *l;
5195    E_Border *bd;
5196
5197    EINA_LIST_FOREACH(borders, l, bd)
5198      {
5199         if (bd->lock_life)
5200           list = eina_list_append(list, bd);
5201      }
5202    return list;
5203 }
5204
5205 EAPI const char *
5206 e_border_name_get(const E_Border *bd)
5207 {
5208    E_OBJECT_CHECK_RETURN(bd, "");
5209    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, "");
5210    if (bd->client.netwm.name)
5211      return bd->client.netwm.name;
5212    else if (bd->client.icccm.title)
5213      return bd->client.icccm.title;
5214    return "";
5215 }
5216
5217 EAPI void
5218 e_border_signal_move_begin(E_Border       *bd,
5219                            const char     *sig,
5220                            const char *src __UNUSED__)
5221 {
5222    E_OBJECT_CHECK(bd);
5223    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5224
5225    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
5226    if (!_e_border_move_begin(bd)) return;
5227    bd->moving = 1;
5228    _e_border_pointer_move_begin(bd);
5229    e_zone_edge_disable();
5230    _e_border_moveinfo_gather(bd, sig);
5231    if (bd->cur_mouse_action)
5232      {
5233         if ((!bd->cur_mouse_action->func.end_mouse) &&
5234             (!bd->cur_mouse_action->func.end))
5235           bd->cur_mouse_action = NULL;
5236         else
5237           e_object_unref(E_OBJECT(bd->cur_mouse_action));
5238      }
5239    bd->cur_mouse_action = e_action_find("window_move");
5240    if (bd->cur_mouse_action)
5241      e_object_ref(E_OBJECT(bd->cur_mouse_action));
5242 }
5243
5244 EAPI void
5245 e_border_signal_move_end(E_Border       *bd,
5246                          const char *sig __UNUSED__,
5247                          const char *src __UNUSED__)
5248 {
5249    E_OBJECT_CHECK(bd);
5250    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5251    if (!bd->moving) return;
5252    bd->moving = 0;
5253    _e_border_pointer_move_end(bd);
5254    e_zone_edge_enable();
5255    _e_border_move_end(bd);
5256    e_zone_flip_coords_handle(bd->zone, -1, -1);
5257 }
5258
5259 EAPI int
5260 e_border_resizing_get(E_Border *bd)
5261 {
5262    E_OBJECT_CHECK_RETURN(bd, 0);
5263    E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, 0);
5264    if (bd->resize_mode == RESIZE_NONE) return 0;
5265    return 1;
5266 }
5267
5268 EAPI void
5269 e_border_signal_resize_begin(E_Border       *bd,
5270                              const char     *dir,
5271                              const char     *sig,
5272                              const char *src __UNUSED__)
5273 {
5274    Ecore_X_Gravity grav = ECORE_X_GRAVITY_NW;
5275    int resize_mode = RESIZE_BR;
5276
5277    E_OBJECT_CHECK(bd);
5278    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5279
5280    if ((bd->resize_mode != RESIZE_NONE) || (bd->moving)) return;
5281    if (!_e_border_resize_begin(bd))
5282      return;
5283    if (!strcmp(dir, "tl"))
5284      {
5285         resize_mode = RESIZE_TL;
5286         grav = ECORE_X_GRAVITY_SE;
5287      }
5288    else if (!strcmp(dir, "t"))
5289      {
5290         resize_mode = RESIZE_T;
5291         grav = ECORE_X_GRAVITY_S;
5292      }
5293    else if (!strcmp(dir, "tr"))
5294      {
5295         resize_mode = RESIZE_TR;
5296         grav = ECORE_X_GRAVITY_SW;
5297      }
5298    else if (!strcmp(dir, "r"))
5299      {
5300         resize_mode = RESIZE_R;
5301         grav = ECORE_X_GRAVITY_W;
5302      }
5303    else if (!strcmp(dir, "br"))
5304      {
5305         resize_mode = RESIZE_BR;
5306         grav = ECORE_X_GRAVITY_NW;
5307      }
5308    else if (!strcmp(dir, "b"))
5309      {
5310         resize_mode = RESIZE_B;
5311         grav = ECORE_X_GRAVITY_N;
5312      }
5313    else if (!strcmp(dir, "bl"))
5314      {
5315         resize_mode = RESIZE_BL;
5316         grav = ECORE_X_GRAVITY_NE;
5317      }
5318    else if (!strcmp(dir, "l"))
5319      {
5320         resize_mode = RESIZE_L;
5321         grav = ECORE_X_GRAVITY_E;
5322      }
5323    bd->resize_mode = resize_mode;
5324    _e_border_pointer_resize_begin(bd);
5325    _e_border_moveinfo_gather(bd, sig);
5326    GRAV_SET(bd, grav);
5327    if (bd->cur_mouse_action)
5328      {
5329         if ((!bd->cur_mouse_action->func.end_mouse) &&
5330             (!bd->cur_mouse_action->func.end))
5331           bd->cur_mouse_action = NULL;
5332         else
5333           e_object_unref(E_OBJECT(bd->cur_mouse_action));
5334      }
5335    bd->cur_mouse_action = e_action_find("window_resize");
5336    if (bd->cur_mouse_action)
5337      e_object_ref(E_OBJECT(bd->cur_mouse_action));
5338 }
5339
5340 EAPI void
5341 e_border_signal_resize_end(E_Border       *bd,
5342                            const char *dir __UNUSED__,
5343                            const char *sig __UNUSED__,
5344                            const char *src __UNUSED__)
5345 {
5346    E_OBJECT_CHECK(bd);
5347    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5348    if (bd->resize_mode == RESIZE_NONE) return;
5349    _e_border_resize_handle(bd);
5350    _e_border_pointer_resize_end(bd);
5351    bd->resize_mode = RESIZE_NONE;
5352    _e_border_resize_end(bd);
5353    bd->changes.reset_gravity = 1;
5354    bd->changed = 1;
5355 }
5356
5357 EAPI void
5358 e_border_resize_limit(E_Border *bd,
5359                       int      *w,
5360                       int      *h)
5361 {
5362    double a;
5363
5364    E_OBJECT_CHECK(bd);
5365    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
5366    *w -= bd->client_inset.l + bd->client_inset.r;
5367    *h -= bd->client_inset.t + bd->client_inset.b;
5368    if (*h < 1) *h = 1;
5369    if (*w < 1) *w = 1;
5370    if ((bd->client.icccm.base_w >= 0) &&
5371        (bd->client.icccm.base_h >= 0))
5372      {
5373         int tw, th;
5374
5375         tw = *w - bd->client.icccm.base_w;
5376         th = *h - bd->client.icccm.base_h;
5377         if (tw < 1) tw = 1;
5378         if (th < 1) th = 1;
5379         a = (double)(tw) / (double)(th);
5380         if ((bd->client.icccm.min_aspect != 0.0) &&
5381             (a < bd->client.icccm.min_aspect))
5382           {
5383              th = tw / bd->client.icccm.max_aspect;
5384              *h = th + bd->client.icccm.base_h;
5385           }
5386         else if ((bd->client.icccm.max_aspect != 0.0) &&
5387                  (a > bd->client.icccm.max_aspect))
5388           {
5389              tw = th * bd->client.icccm.max_aspect;
5390              *w = tw + bd->client.icccm.base_w;
5391           }
5392      }
5393    else
5394      {
5395         a = (double)*w / (double)*h;
5396         if ((bd->client.icccm.min_aspect != 0.0) &&
5397             (a < bd->client.icccm.min_aspect))
5398           *h = *w / bd->client.icccm.min_aspect;
5399         else if ((bd->client.icccm.max_aspect != 0.0) &&
5400                  (a > bd->client.icccm.max_aspect))
5401           *w = *h * bd->client.icccm.max_aspect;
5402      }
5403    if (bd->client.icccm.step_w > 0)
5404      {
5405         if (bd->client.icccm.base_w >= 0)
5406           *w = bd->client.icccm.base_w +
5407             (((*w - bd->client.icccm.base_w) / bd->client.icccm.step_w) *
5408              bd->client.icccm.step_w);
5409         else
5410           *w = bd->client.icccm.min_w +
5411             (((*w - bd->client.icccm.min_w) / bd->client.icccm.step_w) *
5412              bd->client.icccm.step_w);
5413      }
5414    if (bd->client.icccm.step_h > 0)
5415      {
5416         if (bd->client.icccm.base_h >= 0)
5417           *h = bd->client.icccm.base_h +
5418             (((*h - bd->client.icccm.base_h) / bd->client.icccm.step_h) *
5419              bd->client.icccm.step_h);
5420         else
5421           *h = bd->client.icccm.min_h +
5422             (((*h - bd->client.icccm.min_h) / bd->client.icccm.step_h) *
5423              bd->client.icccm.step_h);
5424      }
5425
5426    if (*h < 1) *h = 1;
5427    if (*w < 1) *w = 1;
5428
5429    if      (*w > bd->client.icccm.max_w) *w = bd->client.icccm.max_w;
5430    else if (*w < bd->client.icccm.min_w)
5431      *w = bd->client.icccm.min_w;
5432    if      (*h > bd->client.icccm.max_h) *h = bd->client.icccm.max_h;
5433    else if (*h < bd->client.icccm.min_h)
5434      *h = bd->client.icccm.min_h;
5435
5436    *w += bd->client_inset.l + bd->client_inset.r;
5437    *h += bd->client_inset.t + bd->client_inset.b;
5438 }
5439
5440 /* local subsystem functions */
5441 static void
5442 _e_border_free(E_Border *bd)
5443 {
5444 #ifdef _F_USE_DESK_WINDOW_PROFILE_
5445    const char *str;
5446 #endif
5447    if (bd->client.e.state.video_parent && bd->client.e.state.video_parent_border)
5448      {
5449         bd->client.e.state.video_parent_border->client.e.state.video_child =
5450           eina_list_remove
5451           (bd->client.e.state.video_parent_border->client.e.state.video_child,
5452               bd);
5453      }
5454    if (bd->client.e.state.video_child)
5455      {
5456         E_Border *tmp;
5457
5458         EINA_LIST_FREE(bd->client.e.state.video_child, tmp)
5459           {
5460              tmp->client.e.state.video_parent_border = NULL;
5461           }
5462      }
5463    if (bd->desktop)
5464      {
5465         efreet_desktop_free(bd->desktop);
5466         bd->desktop = NULL;
5467      }
5468    if (bd->post_job)
5469      {
5470         ecore_idle_enterer_del(bd->post_job);
5471         bd->post_job = NULL;
5472      }
5473    if (bd->pointer)
5474      {
5475         e_object_del(E_OBJECT(bd->pointer));
5476         bd->pointer = NULL;
5477      }
5478    if (bdresize == bd)
5479      _e_border_resize_end(bd);
5480    if (bdmove == bd)
5481      _e_border_move_end(bd);
5482    /* TODO: Other states to end before dying? */
5483
5484    if (bd->cur_mouse_action)
5485      {
5486         e_object_unref(E_OBJECT(bd->cur_mouse_action));
5487         bd->cur_mouse_action = NULL;
5488      }
5489
5490    E_FREE(bd->shape_rects);
5491    bd->shape_rects_num = 0;
5492 /*
5493    if (bd->dangling_ref_check)
5494      {
5495         ecore_timer_del(bd->dangling_ref_check);
5496         bd->dangling_ref_check = NULL;
5497      }
5498  */
5499    if (bd->kill_timer)
5500      {
5501         ecore_timer_del(bd->kill_timer);
5502         bd->kill_timer = NULL;
5503      }
5504    if (bd->ping_poller)
5505      {
5506         ecore_poller_del(bd->ping_poller);
5507         bd->ping_poller = NULL;
5508      }
5509    E_FREE_LIST(bd->pending_move_resize, free);
5510
5511    if (bd->shade.anim) ecore_animator_del(bd->shade.anim);
5512    if (bd->border_menu) e_menu_deactivate(bd->border_menu);
5513
5514    if (bd->border_locks_dialog)
5515      {
5516         e_object_del(E_OBJECT(bd->border_locks_dialog));
5517         bd->border_locks_dialog = NULL;
5518      }
5519    if (bd->border_remember_dialog)
5520      {
5521         e_object_del(E_OBJECT(bd->border_remember_dialog));
5522         bd->border_remember_dialog = NULL;
5523      }
5524    if (bd->border_border_dialog)
5525      {
5526         e_object_del(E_OBJECT(bd->border_border_dialog));
5527         bd->border_border_dialog = NULL;
5528      }
5529    if (bd->border_prop_dialog)
5530      {
5531         e_object_del(E_OBJECT(bd->border_prop_dialog));
5532         bd->border_prop_dialog = NULL;
5533      }
5534
5535    e_int_border_menu_del(bd);
5536
5537    if (focusing == bd)
5538      focusing = NULL;
5539
5540    focus_next = eina_list_remove(focus_next, bd);
5541    
5542    if ((focused == bd) ||
5543        (e_grabinput_last_focus_win_get() == bd->client.win))
5544      {
5545         if ((!focus_next) && (!focusing))
5546           {
5547              e_grabinput_focus(bd->zone->container->bg_win,
5548                                E_FOCUS_METHOD_PASSIVE);
5549              e_hints_active_window_set(bd->zone->container->manager, NULL);
5550           }
5551
5552         focused = NULL;
5553      }
5554    E_FREE_LIST(bd->handlers, ecore_event_handler_del);
5555    if (bd->remember)
5556      {
5557         E_Remember *rem;
5558
5559         rem = bd->remember;
5560         bd->remember = NULL;
5561         e_remember_unuse(rem);
5562      }
5563    if (!bd->already_unparented)
5564      {
5565         ecore_x_window_reparent(bd->client.win, bd->zone->container->manager->root,
5566                                 bd->x + bd->client_inset.l, bd->y + bd->client_inset.t);
5567         ecore_x_window_save_set_del(bd->client.win);
5568         bd->already_unparented = 1;
5569      }
5570    if (bd->group) eina_list_free(bd->group);
5571    if (bd->transients) eina_list_free(bd->transients);
5572    if (bd->stick_desks) eina_list_free(bd->stick_desks);
5573    if (bd->client.netwm.icons)
5574      {
5575         int i;
5576         for (i = 0; i < bd->client.netwm.num_icons; i++)
5577           free(bd->client.netwm.icons[i].data);
5578         free(bd->client.netwm.icons);
5579      }
5580    if (bd->client.netwm.extra_types)
5581      free(bd->client.netwm.extra_types);
5582    if (bd->client.border.name)
5583      eina_stringshare_del(bd->client.border.name);
5584    if (bd->bordername)
5585      eina_stringshare_del(bd->bordername);
5586    if (bd->client.icccm.name)
5587      eina_stringshare_del(bd->client.icccm.name);
5588    if (bd->client.icccm.class)
5589      {
5590         if (!strcmp(bd->client.icccm.class, "Vmplayer"))
5591           e_bindings_mapping_change_enable(EINA_TRUE);
5592         eina_stringshare_del(bd->client.icccm.class);
5593      }
5594    if (bd->client.icccm.title)
5595      eina_stringshare_del(bd->client.icccm.title);
5596    if (bd->client.icccm.icon_name)
5597      eina_stringshare_del(bd->client.icccm.icon_name);
5598    if (bd->client.icccm.machine)
5599      eina_stringshare_del(bd->client.icccm.machine);
5600    if (bd->client.icccm.window_role)
5601      eina_stringshare_del(bd->client.icccm.window_role);
5602
5603    if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
5604      {
5605         int i;
5606
5607         for (i = 0; i < bd->client.icccm.command.argc; i++)
5608           free(bd->client.icccm.command.argv[i]);
5609         free(bd->client.icccm.command.argv);
5610      }
5611    if (bd->client.netwm.name)
5612      eina_stringshare_del(bd->client.netwm.name);
5613    if (bd->client.netwm.icon_name)
5614      eina_stringshare_del(bd->client.netwm.icon_name);
5615    e_object_del(E_OBJECT(bd->shape));
5616    if (bd->internal_icon) eina_stringshare_del(bd->internal_icon);
5617    if (bd->internal_icon_key) eina_stringshare_del(bd->internal_icon_key);
5618    if (bd->icon_object) evas_object_del(bd->icon_object);
5619 #ifdef _F_USE_DESK_WINDOW_PROFILE_
5620    EINA_LIST_FREE(bd->client.e.state.profiles, str)
5621      {
5622         if (str) eina_stringshare_del(str);
5623      }
5624    bd->client.e.state.profiles = NULL;
5625    if (bd->client.e.state.profile)
5626      eina_stringshare_del(bd->client.e.state.profile);
5627    bd->client.e.state.profile = NULL;
5628 #endif
5629 #ifdef _F_ZONE_WINDOW_ROTATION_
5630    if (e_config->wm_win_rotation)
5631      {
5632         bd->client.e.fetch.rot.app_set = 0;
5633         bd->client.e.state.rot.preferred_rot = -1;
5634
5635         if (bd->client.e.state.rot.available_rots)
5636           E_FREE(bd->client.e.state.rot.available_rots);
5637
5638         _e_border_rotation_list_remove(bd);
5639         if ((rot.vkbd) && (rot.vkbd == bd))
5640           {
5641              ELB(ELBT_BD, "UNSET VKBD", bd->client.win);
5642              rot.vkbd = NULL;
5643              if (rot.vkbd_ctrl_win)
5644                {
5645                   ELB(ELBT_BD, "SET KBD_OFF", 0);
5646                   ecore_x_e_virtual_keyboard_state_set
5647                     (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
5648                }
5649
5650              rot.vkbd_hide_prepare_done = EINA_FALSE;
5651              if (rot.vkbd_hide_prepare_timer)
5652                ecore_timer_del(rot.vkbd_hide_prepare_timer);
5653              rot.vkbd_hide_prepare_timer = NULL;
5654              if (rot.vkbd_hide_timer)
5655                ecore_timer_del(rot.vkbd_hide_timer);
5656              rot.vkbd_hide_timer = NULL;
5657
5658              rot.vkbd_show_prepare_done = EINA_FALSE;
5659              if (rot.vkbd_show_prepare_timer)
5660                ecore_timer_del(rot.vkbd_show_prepare_timer);
5661              rot.vkbd_show_prepare_timer = NULL;
5662              if (rot.vkbd_show_timer)
5663                ecore_timer_del(rot.vkbd_show_timer);
5664              rot.vkbd_show_timer = NULL;
5665           }
5666         else if ((rot.vkbd_prediction) &&
5667                  (rot.vkbd_prediction == bd))
5668           rot.vkbd_prediction = NULL;
5669      }
5670 #endif
5671    evas_object_del(bd->bg_object);
5672    e_canvas_del(bd->bg_ecore_evas);
5673    ecore_evas_free(bd->bg_ecore_evas);
5674    ecore_x_window_free(bd->client.shell_win);
5675    e_focus_setdown(bd);
5676    e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5677    e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
5678    ecore_x_window_free(bd->win);
5679
5680    eina_hash_del(borders_hash, e_util_winid_str_get(bd->client.win), bd);
5681    eina_hash_del(borders_hash, e_util_winid_str_get(bd->bg_win), bd);
5682    eina_hash_del(borders_hash, e_util_winid_str_get(bd->win), bd);
5683    borders = eina_list_remove(borders, bd);
5684    focus_stack = eina_list_remove(focus_stack, bd);
5685    raise_stack = eina_list_remove(raise_stack, bd);
5686
5687    e_container_border_remove(bd);
5688    free(bd);
5689 }
5690
5691 /*
5692    static int
5693    _e_border_del_dangling_ref_check(void *data)
5694    {
5695    E_Border *bd;
5696
5697    bd = data;
5698    printf("---\n");
5699    printf("EEK EEK border still around 1 second after being deleted!\n");
5700    printf("%p, %i, \"%s\" [\"%s\" \"%s\"]\n",
5701           bd, e_object_ref_get(E_OBJECT(bd)), bd->client.icccm.title,
5702           bd->client.icccm.name, bd->client.icccm.class);
5703    //   e_object_breadcrumb_debug(E_OBJECT(bd));
5704    printf("---\n");
5705    return 1;
5706    }
5707  */
5708
5709 static void
5710 _e_border_del(E_Border *bd)
5711 {
5712    E_Event_Border_Remove *ev;
5713    E_Border *child;
5714
5715 #ifdef _F_BORDER_HOOK_PATCH_
5716    _e_border_hook_call(E_BORDER_HOOK_DEL_BORDER, bd);
5717 #endif
5718
5719    if (bd == focused)
5720      {
5721         focused = NULL;
5722      }
5723
5724    if (bd == focusing)
5725      focusing = NULL;
5726
5727    focus_next = eina_list_remove(focus_next, bd);
5728
5729    if (bd->fullscreen) bd->desk->fullscreen_borders--;
5730
5731    if ((drag_border) && (drag_border->data == bd))
5732      {
5733         e_object_del(E_OBJECT(drag_border));
5734         drag_border = NULL;
5735      }
5736    if (bd->border_menu) e_menu_deactivate(bd->border_menu);
5737
5738    if (bd->border_locks_dialog)
5739      {
5740         e_object_del(E_OBJECT(bd->border_locks_dialog));
5741         bd->border_locks_dialog = NULL;
5742      }
5743    if (bd->border_remember_dialog)
5744      {
5745         e_object_del(E_OBJECT(bd->border_remember_dialog));
5746         bd->border_remember_dialog = NULL;
5747      }
5748    if (bd->border_border_dialog)
5749      {
5750         e_object_del(E_OBJECT(bd->border_border_dialog));
5751         bd->border_border_dialog = NULL;
5752      }
5753    if (bd->border_prop_dialog)
5754      {
5755         e_object_del(E_OBJECT(bd->border_prop_dialog));
5756         bd->border_prop_dialog = NULL;
5757      }
5758
5759    e_int_border_menu_del(bd);
5760
5761    if (bd->raise_timer)
5762      {
5763         ecore_timer_del(bd->raise_timer);
5764         bd->raise_timer = NULL;
5765      }
5766    if (!bd->already_unparented)
5767      {
5768         ecore_x_window_reparent(bd->client.win,
5769                                 bd->zone->container->manager->root,
5770                                 bd->x + bd->client_inset.l,
5771                                 bd->y + bd->client_inset.t);
5772         ecore_x_window_save_set_del(bd->client.win);
5773         bd->already_unparented = 1;
5774 //      bd->client.win = 0;
5775      }
5776    bd->already_unparented = 1;
5777
5778    if ((!bd->new_client) && (!stopping))
5779      {
5780         ev = E_NEW(E_Event_Border_Remove, 1);
5781         ev->border = bd;
5782         e_object_ref(E_OBJECT(bd));
5783         // e_object_breadcrumb_add(E_OBJECT(bd), "border_remove_event");
5784         ecore_event_add(E_EVENT_BORDER_REMOVE, ev, _e_border_event_border_remove_free, NULL);
5785      }
5786
5787    if (bd->parent)
5788      {
5789         bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
5790         if (bd->parent->modal == bd)
5791           {
5792              ecore_x_event_mask_unset(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
5793              ecore_x_event_mask_set(bd->parent->client.win, bd->parent->saved.event_mask);
5794              bd->parent->lock_close = 0;
5795              bd->parent->saved.event_mask = 0;
5796              bd->parent->modal = NULL;
5797           }
5798         bd->parent = NULL;
5799      }
5800    EINA_LIST_FREE(bd->transients, child)
5801      {
5802         child->parent = NULL;
5803      }
5804
5805 #ifdef _F_DEICONIFY_APPROVE_
5806    bd->client.e.state.deiconify_approve.render_done = 0;
5807
5808    E_Border *ancestor_bd;
5809    ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
5810    if ((ancestor_bd) &&
5811        (!e_object_is_del(E_OBJECT(ancestor_bd))))
5812      {
5813         ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
5814         bd->client.e.state.deiconify_approve.ancestor = NULL;
5815
5816         if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
5817             (ancestor_bd->client.e.state.deiconify_approve.render_done))
5818           {
5819              if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
5820                {
5821                   ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
5822                   ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
5823                   e_border_uniconify(ancestor_bd);
5824                }
5825           }
5826      }
5827
5828    if (bd->client.e.state.deiconify_approve.wait_timer)
5829      {
5830         ecore_timer_del(bd->client.e.state.deiconify_approve.wait_timer);
5831         bd->client.e.state.deiconify_approve.wait_timer = NULL;
5832      }
5833
5834    if (bd->client.e.state.deiconify_approve.req_list)
5835      {
5836         EINA_LIST_FREE(bd->client.e.state.deiconify_approve.req_list, child)
5837           {
5838              child->client.e.state.deiconify_approve.render_done = 0;
5839              child->client.e.state.deiconify_approve.ancestor = NULL;
5840           }
5841      }
5842 #endif
5843
5844 #ifdef _F_ZONE_WINDOW_ROTATION_
5845    if (rot.list) _e_border_rotation_list_remove(bd);
5846    if (rot.async_list)
5847      {
5848         Eina_List *l;
5849         E_Border_Rotation_Info *info = NULL;
5850
5851         EINA_LIST_FOREACH(rot.async_list, l, info)
5852            if (info->bd == bd)
5853              {
5854                 rot.async_list = eina_list_remove(rot.async_list, info);
5855                 E_FREE(info);
5856              }
5857      }
5858 #endif
5859
5860    if (bd->leader)
5861      {
5862         bd->leader->group = eina_list_remove(bd->leader->group, bd);
5863         if (bd->leader->modal == bd)
5864           bd->leader->modal = NULL;
5865         bd->leader = NULL;
5866      }
5867    EINA_LIST_FREE(bd->group, child)
5868      {
5869         child->leader = NULL;
5870      }
5871 }
5872
5873 #ifdef PRINT_LOTS_OF_DEBUG
5874 static void
5875 _e_border_print(E_Border   *bd,
5876                 const char *func)
5877 {
5878    if (!bd) return;
5879
5880    DBG("*Window Info*"
5881           "\tPointer: %p\n"
5882           "\tName: %s\n"
5883           "\tTitle: %s\n"
5884           "\tBorderless: %s\n",
5885           bd, bd->client.icccm.name, bd->client.icccm.title,
5886           bd->borderless ? "TRUE" : "FALSE");
5887 }
5888
5889 #endif
5890
5891 static Eina_Bool
5892 _e_border_cb_window_show_request(void *data  __UNUSED__,
5893                                  int ev_type __UNUSED__,
5894                                  void       *ev)
5895 {
5896    E_Border *bd;
5897    E_Container *con;
5898    Ecore_X_Event_Window_Show_Request *e;
5899
5900    e = ev;
5901    bd = e_border_find_by_client_window(e->win);
5902    if (!bd) return ECORE_CALLBACK_PASS_ON;
5903
5904    if ((e_config->wm_win_rotation) &&
5905        (rot.vkbd_ctrl_win) && (rot.vkbd) &&
5906        (bd == rot.vkbd) &&
5907        (rot.vkbd_hide_prepare_timer))
5908      {
5909         con = bd->zone->container;
5910         bd = e_border_new(con, e->win, 0, 0);
5911      }
5912
5913    if (bd->iconic)
5914      {
5915         if (!bd->lock_client_iconify)
5916           e_border_uniconify(bd);
5917      }
5918    else
5919      {
5920         /* FIXME: make border "urgent" for a bit - it wants attention */
5921 /*      e_border_show(bd); */
5922           if (!bd->lock_client_stacking)
5923             e_border_raise(bd);
5924      }
5925    return ECORE_CALLBACK_PASS_ON;
5926 }
5927
5928 static Eina_Bool
5929 _e_border_cb_window_destroy(void *data  __UNUSED__,
5930                             int ev_type __UNUSED__,
5931                             void       *ev)
5932 {
5933    E_Border *bd;
5934    Ecore_X_Event_Window_Destroy *e;
5935
5936    e = ev;
5937    bd = e_border_find_by_client_window(e->win);
5938    if (!bd) return ECORE_CALLBACK_PASS_ON;
5939    ELB(ELBT_BD, "X_WIN_DEL", bd->client.win);
5940 #ifdef _F_ZONE_WINDOW_ROTATION_
5941    if (e_config->wm_win_rotation)
5942      {
5943         if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD)
5944           {
5945              ELB(ELBT_BD, "X_DEL_NOTIFY", bd->client.win);
5946              if (!rot.vkbd_hide_prepare_timer)
5947                {
5948                   ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
5949                   e_border_hide(bd, 0);
5950                   if (!rot.vkbd_hide_prepare_timer)
5951                     {
5952                        ELB(ELBT_BD, "DEL VKBD", bd->client.win);
5953                        e_object_del(E_OBJECT(bd));
5954                     }
5955                }
5956              return ECORE_CALLBACK_PASS_ON;
5957           }
5958      }
5959 #endif
5960    e_border_hide(bd, 0);
5961    e_object_del(E_OBJECT(bd));
5962    return ECORE_CALLBACK_PASS_ON;
5963 }
5964
5965 static Eina_Bool
5966 _e_border_cb_window_hide(void *data  __UNUSED__,
5967                          int ev_type __UNUSED__,
5968                          void       *ev)
5969 {
5970    E_Border *bd = NULL;
5971    Ecore_X_Event_Window_Hide *e;
5972
5973    e = ev;
5974 //   printf("HIDE: %x, event %x send: %i\n", e->win, e->event_win, e->send_event);
5975 // not interested in hide events from windows other than the window in question
5976    if (e->win != e->event_win)
5977      {
5978         bd = e_border_find_by_client_window(e->win);
5979         if (!bd) return ECORE_CALLBACK_PASS_ON;
5980         if (!e->send_event) return ECORE_CALLBACK_PASS_ON;
5981         else
5982           {
5983              if (!((bd->zone) &&
5984                    (bd->zone->container->manager->root == e->event_win)))
5985                return ECORE_CALLBACK_PASS_ON;
5986           }
5987      }
5988    if (!bd) bd = e_border_find_by_client_window(e->win);
5989 //   printf("  bd = %p\n", bd);
5990    if (!bd)
5991      {
5992         if (ecore_x_window_visible_get(e->win))
5993           {
5994              ELB(ELBT_BD, "FORCE UNMAP client window", e->win);
5995              ecore_x_window_hide(e->win);
5996           }
5997         return ECORE_CALLBACK_PASS_ON;
5998      }
5999
6000 //   printf("  bd->ignore_first_unmap = %i\n", bd->ignore_first_unmap);
6001    if (bd->ignore_first_unmap > 0)
6002      {
6003         bd->ignore_first_unmap--;
6004         return ECORE_CALLBACK_PASS_ON;
6005      }
6006    /* Don't delete hidden or iconified windows */
6007 #ifdef _F_USE_EXTENDED_ICONIFY_
6008    if (bd->await_hide_event > 0)
6009 #else
6010    if ((bd->iconic) || (bd->await_hide_event > 0))
6011 #endif
6012      {
6013 //        printf("  Don't delete hidden or iconified windows\n");
6014 //        printf("  bd->iconic = %i, bd->visible = %i, bd->new_client = %i, bd->await_hide_event = %i\n",
6015 //               bd->iconic, bd->visible, bd->new_client, bd->await_hide_event);
6016         if (bd->await_hide_event > 0)
6017           {
6018              bd->await_hide_event--;
6019           }
6020         else
6021           {
6022 //             printf("  hide really\n");
6023              /* Only hide the border if it is visible */
6024              if (bd->visible) e_border_hide(bd, 1);
6025           }
6026      }
6027    else
6028      {
6029 //             printf("  hide2\n");
6030 #ifdef _F_USE_EXTENDED_ICONIFY_
6031         if (bd->iconic)
6032           {
6033              bd->iconic = 0;
6034              bd->visible = 1;
6035           }
6036 #endif
6037
6038 #ifdef _F_ZONE_WINDOW_ROTATION_
6039         if (e_config->wm_win_rotation)
6040           {
6041              if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD)
6042                {
6043                   ELB(ELBT_BD, "X_UNMAP_NOTIFY", bd->client.win);
6044                   if (!rot.vkbd_hide_prepare_timer)
6045                     {
6046                        ELB(ELBT_BD, "HIDE VKBD", bd->client.win);
6047                        e_border_hide(bd, 0);
6048                        if (!rot.vkbd_hide_prepare_timer)
6049                          {
6050                             ELB(ELBT_BD, "DEL VKBD", bd->client.win);
6051                             e_object_del(E_OBJECT(bd));
6052                          }
6053                     }
6054                   return ECORE_CALLBACK_PASS_ON;
6055                }
6056           }
6057 #endif
6058         e_border_hide(bd, 0);
6059         e_object_del(E_OBJECT(bd));
6060      }
6061    return ECORE_CALLBACK_PASS_ON;
6062 }
6063
6064 static Eina_Bool
6065 _e_border_cb_window_reparent(void *data  __UNUSED__,
6066                              int ev_type __UNUSED__,
6067                              void *ev    __UNUSED__)
6068 {
6069 #if 0
6070    E_Border *bd;
6071    Ecore_X_Event_Window_Reparent *e;
6072
6073    e = ev;
6074    bd = e_border_find_by_client_window(e->win);
6075    if (!bd) return 1;
6076    if (e->parent == bd->client.shell_win) return 1;
6077    if (ecore_x_window_parent_get(e->win) == bd->client.shell_win)
6078      {
6079         return 1;
6080      }
6081    e_border_hide(bd, 0);
6082    e_object_del(E_OBJECT(bd));
6083 #endif
6084    return ECORE_CALLBACK_PASS_ON;
6085 }
6086
6087 static Eina_Bool
6088 _e_border_cb_window_configure_request(void *data  __UNUSED__,
6089                                       int ev_type __UNUSED__,
6090                                       void       *ev)
6091 {
6092    E_Border *bd;
6093    Ecore_X_Event_Window_Configure_Request *e;
6094
6095    e = ev;
6096    bd = e_border_find_by_client_window(e->win);
6097    if (!bd)
6098      {
6099         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6100         if (!e_util_container_window_find(e->win))
6101           ecore_x_window_configure(e->win, e->value_mask,
6102                                    e->x, e->y, e->w, e->h, e->border,
6103                                    e->abovewin, e->detail);
6104         return ECORE_CALLBACK_PASS_ON;
6105      }
6106
6107    if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
6108        (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
6109      {
6110         int x, y;
6111
6112         x = bd->x;
6113         y = bd->y;
6114         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
6115           x = e->x;
6116         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
6117           y = e->y;
6118         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
6119             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
6120           {
6121              int w, h;
6122
6123              h = bd->h;
6124              w = bd->w;
6125              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
6126                w = e->w + bd->client_inset.l + bd->client_inset.r;
6127              if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
6128                h = e->h + bd->client_inset.t + bd->client_inset.b;
6129              if ((!bd->lock_client_location) && (!bd->lock_client_size))
6130                {
6131                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6132                     {
6133                        bd->saved.x = x - bd->zone->x;
6134                        bd->saved.y = y - bd->zone->y;
6135                        bd->saved.w = w;
6136                        bd->saved.h = h;
6137                     }
6138                   else
6139                     e_border_move_resize(bd, x, y, w, h);
6140                }
6141              else if (!bd->lock_client_location)
6142                {
6143                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6144                     {
6145                        bd->saved.x = x - bd->zone->x;
6146                        bd->saved.y = y - bd->zone->y;
6147                     }
6148                   else
6149                     e_border_move(bd, x, y);
6150                }
6151              else if (!bd->lock_client_size)
6152                {
6153                   if ((bd->shaded) || (bd->shading))
6154                     {
6155                        int pw, ph;
6156
6157                        pw = bd->client.w;
6158                        ph = bd->client.h;
6159                        if ((bd->shade.dir == E_DIRECTION_UP) ||
6160                            (bd->shade.dir == E_DIRECTION_DOWN))
6161                          {
6162                             e_border_resize(bd, w, bd->h);
6163                             bd->client.h = ph;
6164                          }
6165                        else
6166                          {
6167                             e_border_resize(bd, bd->w, h);
6168                             bd->client.w = pw;
6169                          }
6170                     }
6171                   else
6172                     {
6173                        if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6174                          {
6175                             bd->saved.w = w;
6176                             bd->saved.h = h;
6177                          }
6178                        else
6179                          e_border_resize(bd, w, h);
6180                     }
6181                }
6182           }
6183         else
6184           {
6185              if (!bd->lock_client_location)
6186                {
6187                   if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
6188                     {
6189                        bd->saved.x = x - bd->zone->x;
6190                        bd->saved.y = y - bd->zone->y;
6191                     }
6192                   else
6193                     e_border_move(bd, x, y);
6194                }
6195           }
6196      }
6197    else if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
6198             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
6199      {
6200         int w, h;
6201
6202         h = bd->h;
6203         w = bd->w;
6204         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
6205           w = e->w + bd->client_inset.l + bd->client_inset.r;
6206         if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
6207           h = e->h + bd->client_inset.t + bd->client_inset.b;
6208 #ifdef _F_ZONE_WINDOW_ROTATION_
6209         if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
6210 #endif
6211         if (!bd->lock_client_size)
6212           {
6213              if ((bd->shaded) || (bd->shading))
6214                {
6215                   int pw, ph;
6216
6217                   pw = bd->client.w;
6218                   ph = bd->client.h;
6219                   if ((bd->shade.dir == E_DIRECTION_UP) ||
6220                       (bd->shade.dir == E_DIRECTION_DOWN))
6221                     {
6222                        e_border_resize(bd, w, bd->h);
6223                        bd->client.h = ph;
6224                     }
6225                   else
6226                     {
6227                        e_border_resize(bd, bd->w, h);
6228                        bd->client.w = pw;
6229                     }
6230                }
6231              else
6232                {
6233                   if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_NONE)
6234                     {
6235                        int zx, zy, zw, zh;
6236                        int rx = bd->x;
6237                        int ry = bd->y;
6238                        zx = zy = zw = zh = 0;
6239
6240      /*
6241       * This code does resize and move a window on a
6242       * X configure request into an useful geometry.
6243       * This is really useful for size jumping file dialogs.
6244       */
6245
6246                        if (bd->zone)
6247                          {
6248                             e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
6249
6250                             if (e_config->geometry_auto_resize_limit == 1)
6251                               {
6252                                  if (w > zw)
6253                                    w = zw;
6254
6255                                  if (h > zh)
6256                                    h = zh;
6257                               }
6258                          }
6259                        e_border_resize(bd, w, h);
6260
6261                        if (e_config->geometry_auto_move == 1)
6262                          {
6263                              /* z{x,y,w,h} are only set here; FIXME! */
6264                              if (bd->zone)
6265                                {
6266                                   // move window horizontal if resize to not useful geometry
6267                                   if (bd->x + bd->w > zx + zw)
6268                                     rx = zx + zw - bd->w;
6269                                   else if (bd->x < zx)
6270                                     rx = zx;
6271
6272                                   // move window vertical if resize to not useful geometry
6273                                   if (bd->y + bd->h > zy + zh)
6274                                     ry = zy + zh - bd->h;
6275                                   else if (bd->y < zy)
6276                                     ry = zy;
6277                                }
6278                              e_border_move(bd, rx, ry);
6279                          }
6280                     }
6281                }
6282           }
6283      }
6284    if (!bd->lock_client_stacking)
6285      {
6286         if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE) &&
6287             (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING))
6288           {
6289              E_Border *obd;
6290
6291              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6292                {
6293                   obd = e_border_find_by_client_window(e->abovewin);
6294                   if (obd)
6295                     {
6296                        e_border_stack_above(bd, obd);
6297                     }
6298                   else
6299                     {
6300                        ecore_x_window_configure(bd->win,
6301                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6302                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6303                                                 0, 0, 0, 0, 0,
6304                                                 e->abovewin, ECORE_X_WINDOW_STACK_ABOVE);
6305                        /* FIXME: need to rebuiuld border list from current stacking */
6306                     }
6307                }
6308              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6309                {
6310                   obd = e_border_find_by_client_window(e->abovewin);
6311                   if (obd)
6312                     {
6313                        e_border_stack_below(bd, obd);
6314                     }
6315                   else
6316                     {
6317                        ecore_x_window_configure(bd->win,
6318                                                 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
6319                                                 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
6320                                                 0, 0, 0, 0, 0,
6321                                                 e->abovewin, ECORE_X_WINDOW_STACK_BELOW);
6322                        /* FIXME: need to rebuiuld border list from current stacking */
6323                     }
6324                }
6325              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
6326                {
6327      /* FIXME: do */
6328                }
6329              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
6330                {
6331      /* FIXME: do */
6332                }
6333              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
6334                {
6335      /* FIXME: do */
6336                }
6337           }
6338         else if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE)
6339           {
6340              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6341                {
6342                   e_border_raise(bd);
6343                }
6344              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6345                {
6346                   e_border_lower(bd);
6347                }
6348              else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
6349                {
6350      /* FIXME: do */
6351                }
6352              else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
6353                {
6354      /* FIXME: do */
6355                }
6356              else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
6357                {
6358      /* FIXME: do */
6359                }
6360           }
6361      }
6362
6363    /* FIXME: need to send synthetic stacking event too as well as move/resize */
6364    _e_border_client_move_resize_send(bd);
6365    return ECORE_CALLBACK_PASS_ON;
6366 }
6367
6368 static Eina_Bool
6369 _e_border_cb_window_resize_request(void *data  __UNUSED__,
6370                                    int ev_type __UNUSED__,
6371                                    void       *ev)
6372 {
6373    E_Border *bd;
6374    Ecore_X_Event_Window_Resize_Request *e;
6375
6376    e = ev;
6377    bd = e_border_find_by_client_window(e->win);
6378    if (!bd)
6379      {
6380         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6381         ecore_x_window_resize(e->win, e->w, e->h);
6382         return ECORE_CALLBACK_PASS_ON;
6383      }
6384    {
6385       int w, h;
6386
6387       w = e->w + bd->client_inset.l + bd->client_inset.r;
6388       h = e->h + bd->client_inset.t + bd->client_inset.b;
6389       if ((bd->shaded) || (bd->shading))
6390         {
6391            int pw, ph;
6392
6393            pw = bd->client.w;
6394            ph = bd->client.h;
6395            if ((bd->shade.dir == E_DIRECTION_UP) ||
6396                (bd->shade.dir == E_DIRECTION_DOWN))
6397              {
6398                 e_border_resize(bd, w, bd->h);
6399                 bd->client.h = ph;
6400              }
6401            else
6402              {
6403                 e_border_resize(bd, bd->w, h);
6404                 bd->client.w = pw;
6405              }
6406         }
6407       else
6408         e_border_resize(bd, w, h);
6409    }
6410
6411    _e_border_client_move_resize_send(bd);
6412    return ECORE_CALLBACK_PASS_ON;
6413 }
6414
6415 static Eina_Bool
6416 _e_border_cb_window_gravity(void *data  __UNUSED__,
6417                             int ev_type __UNUSED__,
6418                             void *ev    __UNUSED__)
6419 {
6420 //   E_Border *bd;
6421 //   Ecore_X_Event_Window_Gravity *e;
6422
6423 //   e = ev;
6424 //   bd = e_border_find_by_client_window(e->win);
6425 //   if (!bd) return 1;
6426              return 1;
6427 }
6428
6429 static Eina_Bool
6430 _e_border_cb_window_stack_request(void *data  __UNUSED__,
6431                                   int ev_type __UNUSED__,
6432                                   void       *ev)
6433 {
6434    E_Border *bd;
6435    Ecore_X_Event_Window_Stack_Request *e;
6436
6437    e = ev;
6438    bd = e_border_find_by_client_window(e->win);
6439    if (!bd)
6440      {
6441         if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
6442         if (!e_util_container_window_find(e->win))
6443           {
6444              if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6445                ecore_x_window_raise(e->win);
6446              else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6447                ecore_x_window_lower(e->win);
6448           }
6449         return ECORE_CALLBACK_PASS_ON;
6450      }
6451    if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
6452      e_border_raise(bd);
6453    else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
6454      e_border_lower(bd);
6455    return ECORE_CALLBACK_PASS_ON;
6456 }
6457
6458 static Eina_Bool
6459 _e_border_cb_window_property(void *data  __UNUSED__,
6460                              int ev_type __UNUSED__,
6461                              void       *ev)
6462 {
6463    E_Border *bd;
6464    Ecore_X_Event_Window_Property *e;
6465
6466    e = ev;
6467    bd = e_border_find_by_client_window(e->win);
6468    if (!bd) return ECORE_CALLBACK_PASS_ON;
6469    if (e->atom == ECORE_X_ATOM_WM_NAME)
6470      {
6471         if ((!bd->client.netwm.name) &&
6472             (!bd->client.netwm.fetch.name))
6473           {
6474              bd->client.icccm.fetch.title = 1;
6475              bd->changed = 1;
6476           }
6477      }
6478    else if (e->atom == ECORE_X_ATOM_NET_WM_NAME)
6479      {
6480         bd->client.netwm.fetch.name = 1;
6481         bd->changed = 1;
6482      }
6483    else if (e->atom == ECORE_X_ATOM_WM_CLASS)
6484      {
6485         bd->client.icccm.fetch.name_class = 1;
6486         bd->changed = 1;
6487      }
6488    else if (e->atom == ECORE_X_ATOM_WM_ICON_NAME)
6489      {
6490         if ((!bd->client.netwm.icon_name) &&
6491             (!bd->client.netwm.fetch.icon_name))
6492           {
6493              bd->client.icccm.fetch.icon_name = 1;
6494              bd->changed = 1;
6495           }
6496      }
6497    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON_NAME)
6498      {
6499         bd->client.netwm.fetch.icon_name = 1;
6500         bd->changed = 1;
6501      }
6502    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
6503      {
6504         bd->client.icccm.fetch.machine = 1;
6505         bd->changed = 1;
6506      }
6507    else if (e->atom == ECORE_X_ATOM_WM_PROTOCOLS)
6508      {
6509         bd->client.icccm.fetch.protocol = 1;
6510         bd->changed = 1;
6511      }
6512    else if (e->atom == ECORE_X_ATOM_WM_HINTS)
6513      {
6514         bd->client.icccm.fetch.hints = 1;
6515         bd->changed = 1;
6516      }
6517    else if (e->atom == ECORE_X_ATOM_WM_NORMAL_HINTS)
6518      {
6519         bd->client.icccm.fetch.size_pos_hints = 1;
6520         bd->changed = 1;
6521      }
6522    else if (e->atom == ECORE_X_ATOM_MOTIF_WM_HINTS)
6523      {
6524         /*
6525            if ((bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UNKNOWN) &&
6526             (!bd->client.netwm.fetch.type))
6527            {
6528          */
6529           bd->client.mwm.fetch.hints = 1;
6530           bd->changed = 1;
6531           /*
6532              }
6533            */
6534      }
6535    else if (e->atom == ECORE_X_ATOM_WM_TRANSIENT_FOR)
6536      {
6537         bd->client.icccm.fetch.transient_for = 1;
6538         bd->changed = 1;
6539      }
6540    else if (e->atom == ECORE_X_ATOM_WM_CLIENT_LEADER)
6541      {
6542         bd->client.icccm.fetch.client_leader = 1;
6543         bd->changed = 1;
6544      }
6545    else if (e->atom == ECORE_X_ATOM_WM_WINDOW_ROLE)
6546      {
6547         bd->client.icccm.fetch.window_role = 1;
6548         bd->changed = 1;
6549      }
6550    else if (e->atom == ECORE_X_ATOM_NET_WM_ICON)
6551      {
6552         bd->client.netwm.fetch.icon = 1;
6553         bd->changed = 1;
6554      }
6555    else if (e->atom == ATM__QTOPIA_SOFT_MENU)
6556      {
6557         bd->client.qtopia.fetch.soft_menu = 1;
6558         bd->changed = 1;
6559      }
6560    else if (e->atom == ATM__QTOPIA_SOFT_MENUS)
6561      {
6562         bd->client.qtopia.fetch.soft_menus = 1;
6563         bd->changed = 1;
6564      }
6565    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
6566      {
6567         bd->client.vkbd.fetch.state = 1;
6568         bd->changed = 1;
6569      }
6570    else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
6571      {
6572         bd->client.vkbd.fetch.vkbd = 1;
6573         bd->changed = 1;
6574      }
6575    else if (e->atom == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
6576      {
6577         bd->client.illume.conformant.fetch.conformant = 1;
6578         bd->changed = 1;
6579      }
6580    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
6581      {
6582         bd->client.illume.quickpanel.fetch.state = 1;
6583         bd->changed = 1;
6584      }
6585    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
6586      {
6587         bd->client.illume.quickpanel.fetch.quickpanel = 1;
6588         bd->changed = 1;
6589      }
6590    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
6591      {
6592         bd->client.illume.quickpanel.fetch.priority.major = 1;
6593         bd->changed = 1;
6594      }
6595    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
6596      {
6597         bd->client.illume.quickpanel.fetch.priority.minor = 1;
6598         bd->changed = 1;
6599      }
6600    else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
6601      {
6602         bd->client.illume.quickpanel.fetch.zone = 1;
6603         bd->changed = 1;
6604      }
6605    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
6606      {
6607         bd->client.illume.drag.fetch.locked = 1;
6608         bd->changed = 1;
6609      }
6610    else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG)
6611      {
6612         bd->client.illume.drag.fetch.drag = 1;
6613         bd->changed = 1;
6614      }
6615    else if (e->atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
6616      {
6617         bd->client.illume.win_state.fetch.state = 1;
6618         bd->changed = 1;
6619      }
6620    /*
6621       else if (e->atom == ECORE_X_ATOM_NET_WM_USER_TIME)
6622       {
6623         bd->client.netwm.fetch.user_time = 1;
6624         bd->changed = 1;
6625       }
6626       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT)
6627       {
6628         bd->client.netwm.fetch.strut = 1;
6629         bd->changed = 1;
6630       }
6631       else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
6632       {
6633         bd->client.netwm.fetch.strut = 1;
6634         bd->changed = 1;
6635       }
6636     */
6637    else if (e->atom == ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER)
6638      {
6639         //printf("ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER\n");
6640      }
6641    else if (e->atom == ECORE_X_ATOM_E_VIDEO_POSITION)
6642      {
6643         bd->client.e.fetch.video_position = 1;
6644         bd->changed = 1;
6645      }
6646    else if (e->atom == ECORE_X_ATOM_E_VIDEO_PARENT)
6647      {
6648         bd->client.e.fetch.video_parent = 1;
6649         bd->changed = 1;
6650      }
6651    else if (e->atom == ECORE_X_ATOM_NET_WM_STATE)
6652      {
6653         bd->client.netwm.fetch.state = 1;
6654         bd->changed = 1;
6655      }
6656 #ifdef _F_USE_DESK_WINDOW_PROFILE_
6657    else if (e->atom == ECORE_X_ATOM_E_PROFILE_LIST)
6658      {
6659         bd->client.e.fetch.profile_list = 1;
6660         bd->changed = 1;
6661      }
6662 #endif
6663 #ifdef _F_ZONE_WINDOW_ROTATION_
6664    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED)
6665      {
6666         if (e_config->wm_win_rotation)
6667           {
6668              bd->client.e.fetch.rot.support = 1;
6669              bd->changed = 1;
6670           }
6671      }
6672    else if ((e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_0_GEOMETRY) ||
6673             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_90_GEOMETRY) ||
6674             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_180_GEOMETRY) ||
6675             (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_270_GEOMETRY))
6676      {
6677         if (e_config->wm_win_rotation)
6678           {
6679              bd->client.e.fetch.rot.geom_hint = 1;
6680              bd->changed = 1;
6681           }
6682      }
6683    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED)
6684      {
6685         if (e_config->wm_win_rotation)
6686           {
6687              bd->client.e.fetch.rot.app_set = 1;
6688              bd->changed = 1;
6689           }
6690      }
6691    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION)
6692      {
6693         if (e_config->wm_win_rotation)
6694           {
6695              bd->client.e.fetch.rot.preferred_rot = 1;
6696              bd->changed = 1;
6697           }
6698      }
6699    else if (e->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST)
6700      {
6701         if (e_config->wm_win_rotation)
6702           {
6703              bd->client.e.fetch.rot.available_rots = 1;
6704              bd->changed = 1;
6705           }
6706      }
6707 #endif
6708
6709    return ECORE_CALLBACK_PASS_ON;
6710 }
6711
6712 static Eina_Bool
6713 _e_border_cb_window_colormap(void *data  __UNUSED__,
6714                              int ev_type __UNUSED__,
6715                              void       *ev)
6716 {
6717    E_Border *bd;
6718    Ecore_X_Event_Window_Colormap *e;
6719
6720    e = ev;
6721    bd = e_border_find_by_client_window(e->win);
6722    if (!bd) return ECORE_CALLBACK_PASS_ON;
6723    return ECORE_CALLBACK_PASS_ON;
6724 }
6725
6726 static Eina_Bool
6727 _e_border_cb_window_shape(void *data  __UNUSED__,
6728                           int ev_type __UNUSED__,
6729                           void       *ev)
6730 {
6731    E_Border *bd;
6732    Ecore_X_Event_Window_Shape *e;
6733
6734    e = ev;
6735    bd = e_border_find_by_client_window(e->win);
6736
6737    if (e->type == ECORE_X_SHAPE_INPUT)
6738      {
6739         if (bd)
6740           {
6741              bd->need_shape_merge = 1;
6742 // YYY             bd->shaped_input = 1;
6743              bd->changes.shape_input = 1;
6744              bd->changed = 1;
6745           }
6746
6747         return ECORE_CALLBACK_PASS_ON;
6748      }
6749
6750    if (bd)
6751      {
6752         bd->changes.shape = 1;
6753         bd->changed = 1;
6754         return ECORE_CALLBACK_PASS_ON;
6755      }
6756    bd = e_border_find_by_window(e->win);
6757    if (bd)
6758      {
6759         bd->need_shape_export = 1;
6760         bd->changed = 1;
6761         return ECORE_CALLBACK_PASS_ON;
6762      }
6763    bd = e_border_find_by_frame_window(e->win);
6764    if (bd)
6765      {
6766         bd->need_shape_merge = 1;
6767         bd->changed = 1;
6768         return ECORE_CALLBACK_PASS_ON;
6769      }
6770    return ECORE_CALLBACK_PASS_ON;
6771 }
6772
6773 static Eina_Bool
6774 _e_border_cb_window_focus_in(void *data  __UNUSED__,
6775                              int ev_type __UNUSED__,
6776                              void       *ev)
6777 {
6778    E_Border *bd;
6779    Ecore_X_Event_Window_Focus_In *e;
6780
6781    e = ev;
6782    bd = e_border_find_by_client_window(e->win);
6783    if (!bd) return ECORE_CALLBACK_PASS_ON;
6784 #ifdef INOUTDEBUG_FOCUS
6785    {
6786       time_t t;
6787       char *ct;
6788
6789       const char *modes[] = {
6790         "MODE_NORMAL",
6791         "MODE_WHILE_GRABBED",
6792         "MODE_GRAB",
6793         "MODE_UNGRAB"
6794       };
6795       const char *details[] = {
6796         "DETAIL_ANCESTOR",
6797         "DETAIL_VIRTUAL",
6798         "DETAIL_INFERIOR",
6799         "DETAIL_NON_LINEAR",
6800         "DETAIL_NON_LINEAR_VIRTUAL",
6801         "DETAIL_POINTER",
6802         "DETAIL_POINTER_ROOT",
6803         "DETAIL_DETAIL_NONE"
6804       };
6805       t = time(NULL);
6806       ct = ctime(&t);
6807       ct[strlen(ct) - 1] = 0;
6808       DBG("FF ->IN %i 0x%x %s md=%s dt=%s\n",
6809              e->time,
6810              e->win,
6811              ct,
6812              modes[e->mode],
6813              details[e->detail]);
6814
6815       DBG("%s cb focus in %d %d\n",
6816              e_border_name_get(bd),
6817              bd->client.icccm.accepts_focus,
6818              bd->client.icccm.take_focus);
6819    }
6820 #endif
6821    _e_border_pri_raise(bd);
6822    if (e->mode == ECORE_X_EVENT_MODE_GRAB)
6823      {
6824         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
6825      }
6826    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
6827      {
6828         if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
6829      }
6830
6831    /* ignore focus in from !take_focus windows, we just gave it em */
6832    /* if (!bd->client.icccm.take_focus)
6833     *   return ECORE_CALLBACK_PASS_ON; */
6834
6835    /* should be equal, maybe some clients dont reply with the proper timestamp ? */
6836    if (e->time >= focus_time)
6837      e_border_focus_set(bd, 1, 0);
6838    return ECORE_CALLBACK_PASS_ON;
6839 }
6840
6841 static Eina_Bool
6842 _e_border_cb_window_focus_out(void *data  __UNUSED__,
6843                               int ev_type __UNUSED__,
6844                               void       *ev)
6845 {
6846    E_Border *bd;
6847    Ecore_X_Event_Window_Focus_Out *e;
6848
6849    e = ev;
6850    bd = e_border_find_by_client_window(e->win);
6851    if (!bd) return ECORE_CALLBACK_PASS_ON;
6852 #ifdef INOUTDEBUG_FOCUS
6853    {
6854       time_t t;
6855       char *ct;
6856
6857       const char *modes[] = {
6858         "MODE_NORMAL",
6859         "MODE_WHILE_GRABBED",
6860         "MODE_GRAB",
6861         "MODE_UNGRAB"
6862       };
6863       const char *details[] = {
6864         "DETAIL_ANCESTOR",
6865         "DETAIL_VIRTUAL",
6866         "DETAIL_INFERIOR",
6867         "DETAIL_NON_LINEAR",
6868         "DETAIL_NON_LINEAR_VIRTUAL",
6869         "DETAIL_POINTER",
6870         "DETAIL_POINTER_ROOT",
6871         "DETAIL_DETAIL_NONE"
6872       };
6873       t = time(NULL);
6874       ct = ctime(&t);
6875       ct[strlen(ct) - 1] = 0;
6876       DBG("FF <-OUT %i 0x%x %s md=%s dt=%s",
6877              e->time,
6878              e->win,
6879              ct,
6880              modes[e->mode],
6881              details[e->detail]);
6882
6883       DBG("%s cb focus out %d %d",
6884              e_border_name_get(bd),
6885              bd->client.icccm.accepts_focus,
6886              bd->client.icccm.take_focus);
6887    }
6888 #endif
6889    _e_border_pri_norm(bd);
6890    if (e->mode == ECORE_X_EVENT_MODE_NORMAL)
6891      {
6892         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
6893         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
6894           return ECORE_CALLBACK_PASS_ON;
6895         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
6896           return ECORE_CALLBACK_PASS_ON;
6897      }
6898    else if (e->mode == ECORE_X_EVENT_MODE_GRAB)
6899      {
6900         if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR) return ECORE_CALLBACK_PASS_ON;
6901         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
6902           return ECORE_CALLBACK_PASS_ON;
6903         else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
6904           return ECORE_CALLBACK_PASS_ON;
6905         else if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
6906           return ECORE_CALLBACK_PASS_ON;
6907         else if (e->detail == ECORE_X_EVENT_DETAIL_VIRTUAL)
6908           return ECORE_CALLBACK_PASS_ON;
6909      }
6910    else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
6911      {
6912         /* for firefox/thunderbird (xul) menu walking */
6913         /* NB: why did i disable this before? */
6914         if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR) return ECORE_CALLBACK_PASS_ON;
6915         else if (e->detail == ECORE_X_EVENT_DETAIL_POINTER)
6916           return ECORE_CALLBACK_PASS_ON;
6917      }
6918    else if (e->mode == ECORE_X_EVENT_MODE_WHILE_GRABBED)
6919      {
6920         if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR) return ECORE_CALLBACK_PASS_ON;
6921         else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
6922           return ECORE_CALLBACK_PASS_ON;
6923      }
6924    e_border_focus_set(bd, 0, 0);
6925    return ECORE_CALLBACK_PASS_ON;
6926 }
6927
6928 #if _F_BORDER_CLIP_TO_ZONE_
6929 static void
6930 _e_border_shape_input_clip_to_zone(E_Border *bd)
6931 {
6932    /* if (!(e_config->window_out_of_vscreen_limits_partly)) return; */
6933    if (!(bd->visible))
6934      return;
6935
6936    if (!(E_CONTAINS(bd->zone->x, bd->zone->y,
6937                     bd->zone->w, bd->zone->h,
6938                     bd->x, bd->y, bd->w, bd->h)))
6939      {
6940         int x, y, w, h;
6941         x = bd->x; y = bd->y; w = bd->w; h = bd->h;
6942         E_RECTS_CLIP_TO_RECT(x, y, w, h,
6943                              bd->zone->x, bd->zone->y,
6944                              bd->zone->w, bd->zone->h);
6945         x -= bd->x;
6946         y -= bd->y;
6947         ecore_x_window_shape_input_rectangle_set(bd->bg_win, x, y, w, h);
6948         ecore_x_window_shape_input_rectangle_set(bd->win, x, y, w, h);
6949      }
6950    else
6951      {
6952         ecore_x_window_shape_input_rectangle_set(bd->bg_win, 0, 0, bd->w, bd->h);
6953         ecore_x_window_shape_input_rectangle_set(bd->win, 0, 0, bd->w, bd->h);
6954      }
6955 }
6956 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
6957
6958 static Eina_Bool
6959 _e_border_cb_client_message(void *data  __UNUSED__,
6960                             int ev_type __UNUSED__,
6961                             void       *ev)
6962 {
6963    Ecore_X_Event_Client_Message *e;
6964    E_Border *bd;
6965
6966    e = ev;
6967 #ifdef _F_DEICONIFY_APPROVE_
6968    if (e->message_type == ECORE_X_ATOM_E_DEICONIFY_APPROVE)
6969      {
6970         if (!e_config->deiconify_approve) return ECORE_CALLBACK_PASS_ON;
6971
6972         bd = e_border_find_by_client_window(e->win);
6973         if (bd)
6974           {
6975              if (bd->client.e.state.deiconify_approve.support)
6976                {
6977                   if (e->data.l[1] != 1) return ECORE_CALLBACK_PASS_ON;
6978                   bd->client.e.state.deiconify_approve.render_done = 1;
6979
6980                   E_Border *ancestor_bd;
6981                   ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
6982                   if (ancestor_bd)
6983                     {
6984                        ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
6985                        bd->client.e.state.deiconify_approve.ancestor = NULL;
6986                     }
6987                   else
6988                     {
6989                        ancestor_bd = bd;
6990                     }
6991
6992                   ELBF(ELBT_BD, 0, bd->client.win,
6993                        "RECEIVE DEICONIFY_APPROVE.. ancestor:%x", ancestor_bd->client.win);
6994
6995                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
6996                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
6997                     {
6998                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
6999                          {
7000                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
7001                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
7002                             e_border_uniconify(ancestor_bd);
7003                          }
7004                        else
7005                          {
7006                             ELB(ELBT_BD, "Unset DEICONIFY_APPROVE render_done", ancestor_bd->client.win);
7007                             ancestor_bd->client.e.state.deiconify_approve.render_done = 0;
7008                          }
7009                     }
7010                }
7011           }
7012         return ECORE_CALLBACK_PASS_ON;
7013      }
7014 #endif
7015
7016 #ifdef _F_ZONE_WINDOW_ROTATION_
7017    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
7018
7019    bd = e_border_find_by_client_window(e->win);
7020    if (!bd)
7021      {
7022         if (e_config->wm_win_rotation)
7023           {
7024              Ecore_X_Event_Client_Message *msg = NULL;
7025              Ecore_X_Atom t = e->message_type;
7026              if ((t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE)  ||
7027                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE) ||
7028                  (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW)   ||
7029                  (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE))
7030                {
7031                   msg = E_NEW(Ecore_X_Event_Client_Message, 1);
7032                   if (!msg) return ECORE_CALLBACK_PASS_ON;
7033
7034                   msg->win = e->win;
7035                   msg->message_type = e->message_type;
7036                   msg->data.l[0] = e->data.l[0];
7037                   msg->data.l[1] = e->data.l[1];
7038                   msg->data.l[2] = e->data.l[2];
7039                   msg->data.l[3] = e->data.l[3];
7040                   msg->data.l[4] = e->data.l[4];
7041                   rot.msgs = eina_list_append(rot.msgs, msg);
7042
7043                   rot.fetch = EINA_TRUE;
7044                }
7045           }
7046         return ECORE_CALLBACK_PASS_ON;
7047      }
7048
7049    if (e->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_DONE)
7050      {
7051         ELBF(ELBT_ROT, 0, e->data.l[0], "GET ROT_DONE a%d %dx%d zone_a:%d",
7052              e->data.l[1], e->data.l[2], e->data.l[3], bd->zone->rot.curr);
7053
7054         if (e_config->wm_win_rotation)
7055           {
7056              if ((int)e->data.l[1] == bd->client.e.state.rot.curr)
7057                {
7058                   _e_border_rotation_list_remove(bd);
7059 #if 0
7060                   if (bd->client.e.state.rot.pending_show)
7061                     {
7062                        ELB(ELBT_BD, "SHOW_BD (PEND)", bd->client.win);
7063                        e_border_show(bd);
7064                        bd->client.e.state.rot.pending_show = 0;
7065                     }
7066 #endif
7067                }
7068           }
7069      }
7070 #endif
7071    return ECORE_CALLBACK_PASS_ON;
7072 }
7073
7074 static Eina_Bool
7075 _e_border_cb_window_state_request(void *data  __UNUSED__,
7076                                   int ev_type __UNUSED__,
7077                                   void       *ev)
7078 {
7079    E_Border *bd;
7080    Ecore_X_Event_Window_State_Request *e;
7081    int i;
7082
7083    e = ev;
7084    bd = e_border_find_by_client_window(e->win);
7085    if (!bd) return ECORE_CALLBACK_PASS_ON;
7086
7087    for (i = 0; i < 2; i++)
7088      e_hints_window_state_update(bd, e->state[i], e->action);
7089
7090    return ECORE_CALLBACK_PASS_ON;
7091 }
7092
7093 static Eina_Bool
7094 _e_border_cb_window_move_resize_request(void *data  __UNUSED__,
7095                                         int ev_type __UNUSED__,
7096                                         void       *ev)
7097 {
7098    E_Border *bd;
7099    Ecore_X_Event_Window_Move_Resize_Request *e;
7100
7101    e = ev;
7102    bd = e_border_find_by_client_window(e->win);
7103    if (!bd) return ECORE_CALLBACK_PASS_ON;
7104
7105    if ((bd->shaded) || (bd->shading) ||
7106        (bd->fullscreen) || (bd->moving) ||
7107        (bd->resize_mode != RESIZE_NONE))
7108      return ECORE_CALLBACK_PASS_ON;
7109
7110    if ((e->button >= 1) && (e->button <= 3))
7111      {
7112         bd->mouse.last_down[e->button - 1].mx = e->x;
7113         bd->mouse.last_down[e->button - 1].my = e->y;
7114         bd->mouse.last_down[e->button - 1].x = bd->x;
7115         bd->mouse.last_down[e->button - 1].y = bd->y;
7116         bd->mouse.last_down[e->button - 1].w = bd->w;
7117         bd->mouse.last_down[e->button - 1].h = bd->h;
7118      }
7119    else
7120      {
7121         bd->moveinfo.down.x = bd->x;
7122         bd->moveinfo.down.y = bd->y;
7123         bd->moveinfo.down.w = bd->w;
7124         bd->moveinfo.down.h = bd->h;
7125      }
7126    bd->mouse.current.mx = e->x;
7127    bd->mouse.current.my = e->y;
7128    bd->moveinfo.down.button = e->button;
7129    bd->moveinfo.down.mx = e->x;
7130    bd->moveinfo.down.my = e->y;
7131    grabbed = 1;
7132
7133    if (!bd->lock_user_stacking)
7134      e_border_raise(bd);
7135
7136    if (e->direction == MOVE)
7137      {
7138         bd->cur_mouse_action = e_action_find("window_move");
7139         if (bd->cur_mouse_action)
7140           {
7141              if ((!bd->cur_mouse_action->func.end_mouse) &&
7142                  (!bd->cur_mouse_action->func.end))
7143                bd->cur_mouse_action = NULL;
7144              if (bd->cur_mouse_action)
7145                {
7146                   e_object_ref(E_OBJECT(bd->cur_mouse_action));
7147                   bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
7148                }
7149           }
7150         return ECORE_CALLBACK_PASS_ON;
7151      }
7152
7153    if (!_e_border_resize_begin(bd))
7154      return ECORE_CALLBACK_PASS_ON;
7155
7156    switch (e->direction)
7157      {
7158       case RESIZE_TL:
7159         bd->resize_mode = RESIZE_TL;
7160         GRAV_SET(bd, ECORE_X_GRAVITY_SE);
7161         break;
7162
7163       case RESIZE_T:
7164         bd->resize_mode = RESIZE_T;
7165         GRAV_SET(bd, ECORE_X_GRAVITY_S);
7166         break;
7167
7168       case RESIZE_TR:
7169         bd->resize_mode = RESIZE_TR;
7170         GRAV_SET(bd, ECORE_X_GRAVITY_SW);
7171         break;
7172
7173       case RESIZE_R:
7174         bd->resize_mode = RESIZE_R;
7175         GRAV_SET(bd, ECORE_X_GRAVITY_W);
7176         break;
7177
7178       case RESIZE_BR:
7179         bd->resize_mode = RESIZE_BR;
7180         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
7181         break;
7182
7183       case RESIZE_B:
7184         bd->resize_mode = RESIZE_B;
7185         GRAV_SET(bd, ECORE_X_GRAVITY_N);
7186         break;
7187
7188       case RESIZE_BL:
7189         bd->resize_mode = RESIZE_BL;
7190         GRAV_SET(bd, ECORE_X_GRAVITY_NE);
7191         break;
7192
7193       case RESIZE_L:
7194         bd->resize_mode = RESIZE_L;
7195         GRAV_SET(bd, ECORE_X_GRAVITY_E);
7196         break;
7197
7198       default:
7199         return ECORE_CALLBACK_PASS_ON;
7200      }
7201
7202    bd->cur_mouse_action = e_action_find("window_resize");
7203    if (bd->cur_mouse_action)
7204      {
7205         if ((!bd->cur_mouse_action->func.end_mouse) &&
7206             (!bd->cur_mouse_action->func.end))
7207           bd->cur_mouse_action = NULL;
7208      }
7209    if (bd->cur_mouse_action)
7210      e_object_ref(E_OBJECT(bd->cur_mouse_action));
7211
7212    return ECORE_CALLBACK_PASS_ON;
7213 }
7214
7215 static Eina_Bool
7216 _e_border_cb_desktop_change(void *data  __UNUSED__,
7217                             int ev_type __UNUSED__,
7218                             void       *ev)
7219 {
7220    E_Border *bd;
7221    Ecore_X_Event_Desktop_Change *e;
7222
7223    e = ev;
7224    bd = e_border_find_by_client_window(e->win);
7225    if (bd)
7226      {
7227         if (e->desk == 0xffffffff)
7228           e_border_stick(bd);
7229         else if ((int)e->desk < (bd->zone->desk_x_count * bd->zone->desk_y_count))
7230           {
7231              E_Desk *desk;
7232
7233              desk = e_desk_at_pos_get(bd->zone, e->desk);
7234              if (desk)
7235                e_border_desk_set(bd, desk);
7236           }
7237      }
7238    else
7239      {
7240         ecore_x_netwm_desktop_set(e->win, e->desk);
7241      }
7242    return ECORE_CALLBACK_PASS_ON;
7243 }
7244
7245 static Eina_Bool
7246 _e_border_cb_sync_alarm(void *data  __UNUSED__,
7247                         int ev_type __UNUSED__,
7248                         void       *ev)
7249 {
7250    E_Border *bd;
7251    Ecore_X_Event_Sync_Alarm *e;
7252    unsigned int serial;
7253
7254    e = ev;
7255    bd = e_border_find_by_alarm(e->alarm);
7256    if (!bd) return ECORE_CALLBACK_PASS_ON;
7257
7258    if (bd->client.netwm.sync.wait)
7259      bd->client.netwm.sync.wait--;
7260
7261    if (ecore_x_sync_counter_query(bd->client.netwm.sync.counter, &serial))
7262      {
7263         E_Border_Pending_Move_Resize *pnd = NULL;
7264
7265         /* skip pending for which we didn't get a reply */
7266         while (bd->pending_move_resize)
7267           {
7268              pnd = bd->pending_move_resize->data;
7269              bd->pending_move_resize = eina_list_remove(bd->pending_move_resize, pnd);
7270
7271              if (serial == pnd->serial)
7272                break;
7273
7274              E_FREE(pnd);
7275           }
7276
7277         if (pnd)
7278           {
7279              bd->x = pnd->x;
7280              bd->y = pnd->y;
7281              bd->w = pnd->w;
7282              bd->h = pnd->h;
7283              bd->client.w = bd->w - (bd->client_inset.l + bd->client_inset.r);
7284              bd->client.h = bd->h - (bd->client_inset.t + bd->client_inset.b);
7285              E_FREE(pnd);
7286           }
7287      }
7288
7289    bd->changes.size = 1;
7290    bd->changes.pos = 1;
7291
7292    _e_border_eval(bd);
7293    evas_render(bd->bg_evas);
7294
7295    ecore_x_pointer_xy_get(e_manager_current_get()->root,
7296                           &bd->mouse.current.mx,
7297                           &bd->mouse.current.my);
7298
7299    bd->client.netwm.sync.send_time = ecore_loop_time_get();
7300    _e_border_resize_handle(bd);
7301
7302    return ECORE_CALLBACK_PASS_ON;
7303 }
7304
7305 static Eina_Bool
7306 _e_border_cb_efreet_cache_update(void *data  __UNUSED__,
7307                                  int ev_type __UNUSED__,
7308                                  void *ev    __UNUSED__)
7309 {
7310    Eina_List *l;
7311    E_Border *bd;
7312
7313    /* mark all borders for desktop/icon updates */
7314    EINA_LIST_FOREACH(borders, l, bd)
7315      {
7316         if (bd->desktop)
7317           {
7318              efreet_desktop_free(bd->desktop);
7319              bd->desktop = NULL;
7320           }
7321         bd->changes.icon = 1;
7322         bd->changed = 1;
7323      }
7324    /*
7325       e_init_status_set(_("Desktop files scan done"));
7326       e_init_done();
7327     */
7328    return ECORE_CALLBACK_PASS_ON;
7329 }
7330
7331 static Eina_Bool
7332 _e_border_cb_config_icon_theme(void *data  __UNUSED__,
7333                                int ev_type __UNUSED__,
7334                                void *ev    __UNUSED__)
7335 {
7336    Eina_List *l;
7337    E_Border *bd;
7338
7339    /* mark all borders for desktop/icon updates */
7340    EINA_LIST_FOREACH(borders, l, bd)
7341      {
7342         bd->changes.icon = 1;
7343         bd->changed = 1;
7344      }
7345    return ECORE_CALLBACK_PASS_ON;
7346 }
7347
7348 static Eina_Bool
7349 _e_border_cb_pointer_warp(void *data  __UNUSED__,
7350                           int ev_type __UNUSED__,
7351                           void       *ev)
7352 {
7353    E_Event_Pointer_Warp *e;
7354
7355    e = ev;
7356    if (!bdmove) return ECORE_CALLBACK_PASS_ON;
7357    e_border_move(bdmove, bdmove->x + (e->curr.x - e->prev.x), bdmove->y + (e->curr.y - e->prev.y));
7358    return ECORE_CALLBACK_PASS_ON;
7359 }
7360
7361 static void
7362 _e_border_cb_signal_bind(void            *data,
7363                          Evas_Object *obj __UNUSED__,
7364                          const char      *emission,
7365                          const char      *source)
7366 {
7367    E_Border *bd;
7368
7369    bd = data;
7370    if (e_dnd_active()) return;
7371    e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd),
7372                             emission, source);
7373 }
7374
7375 static Eina_Bool
7376 _e_border_cb_mouse_in(void    *data,
7377                       int type __UNUSED__,
7378                       void    *event)
7379 {
7380    Ecore_X_Event_Mouse_In *ev;
7381    E_Border *bd;
7382
7383    ev = event;
7384    bd = data;
7385 #ifdef INOUTDEBUG_MOUSE
7386    {
7387       time_t t;
7388       char *ct;
7389
7390       const char *modes[] = {
7391          "MODE_NORMAL",
7392          "MODE_WHILE_GRABBED",
7393          "MODE_GRAB",
7394          "MODE_UNGRAB"
7395       };
7396       const char *details[] = {
7397          "DETAIL_ANCESTOR",
7398          "DETAIL_VIRTUAL",
7399          "DETAIL_INFERIOR",
7400          "DETAIL_NON_LINEAR",
7401          "DETAIL_NON_LINEAR_VIRTUAL",
7402          "DETAIL_POINTER",
7403          "DETAIL_POINTER_ROOT",
7404          "DETAIL_DETAIL_NONE"
7405       };
7406       t = time(NULL);
7407       ct = ctime(&t);
7408       ct[strlen(ct) - 1] = 0;
7409       DBG("@@ ->IN 0x%x 0x%x %s md=%s dt=%s",
7410              ev->win, ev->event_win,
7411              ct,
7412              modes[ev->mode],
7413              details[ev->detail]);
7414    }
7415 #endif
7416    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7417    if (ev->event_win == bd->win)
7418      {
7419         e_focus_event_mouse_in(bd);
7420      }
7421 #if 0
7422    if ((ev->win != bd->win) &&
7423        (ev->win != bd->event_win) &&
7424        (ev->event_win != bd->win) &&
7425        (ev->event_win != bd->event_win))
7426      return ECORE_CALLBACK_PASS_ON;
7427 #else
7428    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7429 #endif
7430    bd->mouse.current.mx = ev->root.x;
7431    bd->mouse.current.my = ev->root.y;
7432    if (!bd->bg_evas_in)
7433      {
7434         evas_event_feed_mouse_in(bd->bg_evas, ev->time, NULL);
7435         bd->bg_evas_in = EINA_TRUE;
7436      }
7437    return ECORE_CALLBACK_PASS_ON;
7438 }
7439
7440 static Eina_Bool
7441 _e_border_cb_mouse_out(void    *data,
7442                        int type __UNUSED__,
7443                        void    *event)
7444 {
7445    Ecore_X_Event_Mouse_Out *ev;
7446    E_Border *bd;
7447
7448    ev = event;
7449    bd = data;
7450 #ifdef INOUTDEBUG_MOUSE
7451    {
7452       time_t t;
7453       char *ct;
7454
7455       const char *modes[] = {
7456          "MODE_NORMAL",
7457          "MODE_WHILE_GRABBED",
7458          "MODE_GRAB",
7459          "MODE_UNGRAB"
7460       };
7461       const char *details[] = {
7462          "DETAIL_ANCESTOR",
7463          "DETAIL_VIRTUAL",
7464          "DETAIL_INFERIOR",
7465          "DETAIL_NON_LINEAR",
7466          "DETAIL_NON_LINEAR_VIRTUAL",
7467          "DETAIL_POINTER",
7468          "DETAIL_POINTER_ROOT",
7469          "DETAIL_DETAIL_NONE"
7470       };
7471       t = time(NULL);
7472       ct = ctime(&t);
7473       ct[strlen(ct) - 1] = 0;
7474       DBG("@@ <-OUT 0x%x 0x%x %s md=%s dt=%s",
7475              ev->win, ev->event_win,
7476              ct,
7477              modes[ev->mode],
7478              details[ev->detail]);
7479    }
7480 #endif
7481    if (grabbed) return ECORE_CALLBACK_PASS_ON;
7482    if (ev->event_win == bd->win)
7483      {
7484         if (bd->fullscreen)
7485           return ECORE_CALLBACK_PASS_ON;
7486         if ((ev->mode == ECORE_X_EVENT_MODE_UNGRAB) &&
7487             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7488           return ECORE_CALLBACK_PASS_ON;
7489         if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7490           return ECORE_CALLBACK_PASS_ON;
7491         if ((ev->mode == ECORE_X_EVENT_MODE_NORMAL) &&
7492             (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
7493           return ECORE_CALLBACK_PASS_ON;
7494         e_focus_event_mouse_out(bd);
7495      }
7496 #if 0
7497    if ((ev->win != bd->win) &&
7498        (ev->win != bd->event_win) &&
7499        (ev->event_win != bd->win) &&
7500        (ev->event_win != bd->event_win))
7501      return ECORE_CALLBACK_PASS_ON;
7502 #else
7503    if (ev->win != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7504 #endif
7505    bd->mouse.current.mx = ev->root.x;
7506    bd->mouse.current.my = ev->root.y;
7507    if (bd->bg_evas_in)
7508      {
7509         if (!((evas_event_down_count_get(bd->bg_evas) > 0) &&
7510               (!((ev->mode == ECORE_X_EVENT_MODE_GRAB) &&
7511                  (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)))))
7512           {
7513              if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
7514                evas_event_feed_mouse_cancel(bd->bg_evas, ev->time, NULL);
7515              evas_event_feed_mouse_out(bd->bg_evas, ev->time, NULL);
7516              bd->bg_evas_in = EINA_FALSE;
7517           }
7518      }
7519    return ECORE_CALLBACK_PASS_ON;
7520 }
7521
7522 static Eina_Bool
7523 _e_border_cb_mouse_wheel(void    *data,
7524                          int type __UNUSED__,
7525                          void    *event)
7526 {
7527    Ecore_Event_Mouse_Wheel *ev;
7528    E_Border *bd;
7529
7530    ev = event;
7531    bd = data;
7532    if ((ev->event_window == bd->win) ||
7533        (ev->event_window == bd->event_win))
7534      {
7535         bd->mouse.current.mx = ev->root.x;
7536         bd->mouse.current.my = ev->root.y;
7537         if (!bd->cur_mouse_action)
7538           e_bindings_wheel_event_handle(E_BINDING_CONTEXT_WINDOW,
7539                                         E_OBJECT(bd), ev);
7540      }
7541    evas_event_feed_mouse_wheel(bd->bg_evas, ev->direction, ev->z, ev->timestamp, NULL);
7542    return ECORE_CALLBACK_PASS_ON;
7543 }
7544
7545 static Eina_Bool
7546 _e_border_cb_mouse_down(void    *data,
7547                         int type __UNUSED__,
7548                         void    *event)
7549 {
7550    Ecore_Event_Mouse_Button *ev;
7551    E_Border *bd;
7552
7553    ev = event;
7554    bd = data;
7555    if ((ev->event_window == bd->win) ||
7556        (ev->event_window == bd->event_win))
7557      {
7558         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7559           {
7560              bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7561              bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7562              bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7563              bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7564              bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7565              bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7566           }
7567         else
7568           {
7569              bd->moveinfo.down.x = bd->x + bd->fx.x;
7570              bd->moveinfo.down.y = bd->y + bd->fx.y;
7571              bd->moveinfo.down.w = bd->w;
7572              bd->moveinfo.down.h = bd->h;
7573           }
7574         bd->mouse.current.mx = ev->root.x;
7575         bd->mouse.current.my = ev->root.y;
7576         if (!bd->cur_mouse_action)
7577           {
7578              bd->cur_mouse_action =
7579                e_bindings_mouse_down_event_handle(E_BINDING_CONTEXT_WINDOW,
7580                                                   E_OBJECT(bd), ev);
7581              if (bd->cur_mouse_action)
7582                {
7583                   if ((!bd->cur_mouse_action->func.end_mouse) &&
7584                       (!bd->cur_mouse_action->func.end))
7585                     bd->cur_mouse_action = NULL;
7586                   if (bd->cur_mouse_action)
7587                     e_object_ref(E_OBJECT(bd->cur_mouse_action));
7588                }
7589           }
7590         e_focus_event_mouse_down(bd);
7591      }
7592    if (ev->window != ev->event_window)
7593      {
7594         return 1;
7595      }
7596    if ((ev->window != bd->event_win) && (ev->event_window != bd->win))
7597      {
7598         return 1;
7599      }
7600    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7601      {
7602         bd->mouse.last_down[ev->buttons - 1].mx = ev->root.x;
7603         bd->mouse.last_down[ev->buttons - 1].my = ev->root.y;
7604         bd->mouse.last_down[ev->buttons - 1].x = bd->x + bd->fx.x;
7605         bd->mouse.last_down[ev->buttons - 1].y = bd->y + bd->fx.y;
7606         bd->mouse.last_down[ev->buttons - 1].w = bd->w;
7607         bd->mouse.last_down[ev->buttons - 1].h = bd->h;
7608      }
7609    else
7610      {
7611         bd->moveinfo.down.x = bd->x + bd->fx.x;
7612         bd->moveinfo.down.y = bd->y + bd->fx.y;
7613         bd->moveinfo.down.w = bd->w;
7614         bd->moveinfo.down.h = bd->h;
7615      }
7616    bd->mouse.current.mx = ev->root.x;
7617    bd->mouse.current.my = ev->root.y;
7618 /*
7619    if (bd->moving)
7620      {
7621      }
7622    else if (bd->resize_mode != RESIZE_NONE)
7623      {
7624      }
7625    else
7626  */
7627    {
7628       Evas_Button_Flags flags = EVAS_BUTTON_NONE;
7629
7630       if (ev->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK;
7631       if (ev->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK;
7632       evas_event_feed_mouse_down(bd->bg_evas, ev->buttons, flags, ev->timestamp, NULL);
7633    }
7634    return ECORE_CALLBACK_PASS_ON;
7635 }
7636
7637 static Eina_Bool
7638 _e_border_cb_mouse_up(void    *data,
7639                       int type __UNUSED__,
7640                       void    *event)
7641 {
7642    Ecore_Event_Mouse_Button *ev;
7643    E_Border *bd;
7644
7645    ev = event;
7646    bd = data;
7647    if ((ev->event_window == bd->win) ||
7648        (ev->event_window == bd->event_win))
7649      {
7650         if ((ev->buttons >= 1) && (ev->buttons <= 3))
7651           {
7652              bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7653              bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7654              bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7655              bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7656           }
7657         bd->mouse.current.mx = ev->root.x;
7658         bd->mouse.current.my = ev->root.y;
7659         /* also we dont pass the same params that went in - then again that */
7660         /* should be ok as we are just ending the action if it has an end */
7661         if (bd->cur_mouse_action)
7662           {
7663              if (bd->cur_mouse_action->func.end_mouse)
7664                bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", ev);
7665              else if (bd->cur_mouse_action->func.end)
7666                bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
7667              e_object_unref(E_OBJECT(bd->cur_mouse_action));
7668              bd->cur_mouse_action = NULL;
7669           }
7670         else
7671           {
7672              if (!e_bindings_mouse_up_event_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd), ev))
7673                e_focus_event_mouse_up(bd);
7674           }
7675      }
7676    if (ev->window != bd->event_win) return ECORE_CALLBACK_PASS_ON;
7677    if ((ev->buttons >= 1) && (ev->buttons <= 3))
7678      {
7679         bd->mouse.last_up[ev->buttons - 1].mx = ev->root.x;
7680         bd->mouse.last_up[ev->buttons - 1].my = ev->root.y;
7681         bd->mouse.last_up[ev->buttons - 1].x = bd->x + bd->fx.x;
7682         bd->mouse.last_up[ev->buttons - 1].y = bd->y + bd->fx.y;
7683      }
7684    bd->mouse.current.mx = ev->root.x;
7685    bd->mouse.current.my = ev->root.y;
7686
7687    bd->drag.start = 0;
7688
7689    evas_event_feed_mouse_up(bd->bg_evas, ev->buttons, EVAS_BUTTON_NONE, ev->timestamp, NULL);
7690    return ECORE_CALLBACK_PASS_ON;
7691 }
7692
7693 static void
7694 _e_border_stay_within_container(E_Border *bd, int x, int y, int *new_x, int *new_y)
7695 {
7696 #ifdef _F_BORDER_CLIP_TO_ZONE_
7697    int new_x_max, new_y_max;
7698    int new_x_min, new_y_min;
7699    int margin_x, margin_y;
7700
7701    margin_x = bd->w - 100;
7702    margin_y = bd->h - 100;
7703
7704    new_x_max = bd->zone->x + bd->zone->w - bd->w + margin_x;
7705    new_x_min = bd->zone->x - margin_x;
7706    new_y_max = bd->zone->y + bd->zone->h - bd->h + margin_y;
7707    new_y_min = bd->zone->y - margin_y;
7708
7709    if (x >= new_x_max)      *new_x = new_x_max;
7710    else if (x <= new_x_min) *new_x = new_x_min;
7711
7712    if (y >= new_y_max)      *new_y = new_y_max;
7713    else if (y <= new_y_min) *new_y = new_y_min;
7714 #endif
7715 }
7716
7717 static Eina_Bool
7718 _e_border_cb_mouse_move(void    *data,
7719                         int type __UNUSED__,
7720                         void    *event)
7721 {
7722    Ecore_Event_Mouse_Move *ev;
7723    E_Border *bd;
7724
7725    ev = event;
7726    bd = data;
7727    if ((ev->window != bd->event_win) &&
7728        (ev->event_window != bd->win)) return ECORE_CALLBACK_PASS_ON;
7729    bd->mouse.current.mx = ev->root.x;
7730    bd->mouse.current.my = ev->root.y;
7731    if (bd->moving)
7732      {
7733         int x, y, new_x, new_y;
7734         int new_w, new_h;
7735         Eina_List *skiplist = NULL;
7736 #if 0
7737         // FIXME: remove? sync what for when only moving?
7738         if ((ecore_loop_time_get() - bd->client.netwm.sync.time) > 0.5)
7739           bd->client.netwm.sync.wait = 0;
7740         if ((bd->client.netwm.sync.request) &&
7741             (bd->client.netwm.sync.alarm) &&
7742             (bd->client.netwm.sync.wait > 1)) return ECORE_CALLBACK_PASS_ON;
7743 #endif
7744         if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
7745           {
7746              x = bd->mouse.last_down[bd->moveinfo.down.button - 1].x +
7747                (bd->mouse.current.mx - bd->moveinfo.down.mx);
7748              y = bd->mouse.last_down[bd->moveinfo.down.button - 1].y +
7749                (bd->mouse.current.my - bd->moveinfo.down.my);
7750           }
7751         else
7752           {
7753              x = bd->moveinfo.down.x +
7754                (bd->mouse.current.mx - bd->moveinfo.down.mx);
7755              y = bd->moveinfo.down.y +
7756                (bd->mouse.current.my - bd->moveinfo.down.my);
7757           }
7758         new_x = x;
7759         new_y = y;
7760
7761 #ifdef _F_USE_RESIST_MAGNETIC_EFFECT_
7762         skiplist = eina_list_append(skiplist, bd);
7763         e_resist_container_border_position(bd->zone->container, skiplist,
7764                                            bd->x, bd->y, bd->w, bd->h,
7765                                            x, y, bd->w, bd->h,
7766                                            &new_x, &new_y, &new_w, &new_h);
7767         eina_list_free(skiplist);
7768
7769         _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
7770 #else
7771         /* if (e_config->window_out_of_vscreen_limits_partly) */
7772         if (1)
7773           _e_border_stay_within_container(bd, x, y, &new_x, &new_y);
7774         else
7775           {
7776              skiplist = eina_list_append(skiplist, bd);
7777              e_resist_container_border_position(bd->zone->container, skiplist,
7778                                                 bd->x, bd->y, bd->w, bd->h,
7779                                                 x, y, bd->w, bd->h,
7780                                                 &new_x, &new_y, &new_w, &new_h);
7781              eina_list_free(skiplist);
7782           }
7783 #endif
7784         bd->shelf_fix.x = 0;
7785         bd->shelf_fix.y = 0;
7786         bd->shelf_fix.modified = 0;
7787         e_border_move(bd, new_x, new_y);
7788         e_zone_flip_coords_handle(bd->zone, ev->root.x, ev->root.y);
7789      }
7790    else if (bd->resize_mode != RESIZE_NONE)
7791      {
7792         if ((bd->client.netwm.sync.request) &&
7793             (bd->client.netwm.sync.alarm))
7794           {
7795              if ((ecore_loop_time_get() - bd->client.netwm.sync.send_time) > 0.5)
7796                {
7797                   E_Border_Pending_Move_Resize *pnd;
7798
7799                   if (bd->pending_move_resize)
7800                     {
7801                        bd->changes.pos = 1;
7802                        bd->changes.size = 1;
7803                        bd->changed = 1;
7804                        _e_border_client_move_resize_send(bd);
7805                     }
7806                   EINA_LIST_FREE(bd->pending_move_resize, pnd)
7807                     E_FREE(pnd);
7808
7809                   bd->client.netwm.sync.wait = 0;
7810                }
7811              /* sync.wait is incremented when resize_handle sends
7812               * sync-request and decremented by sync-alarm cb. so
7813               * we resize here either on initial resize, timeout or
7814               * when no new resize-request was added by sync-alarm cb.
7815               */
7816              if (!bd->client.netwm.sync.wait)
7817                _e_border_resize_handle(bd);
7818           }
7819         else
7820           _e_border_resize_handle(bd);
7821      }
7822    else
7823      {
7824         if (bd->drag.start)
7825           {
7826              if ((bd->drag.x == -1) && (bd->drag.y == -1))
7827                {
7828                   bd->drag.x = ev->root.x;
7829                   bd->drag.y = ev->root.y;
7830                }
7831              else
7832                {
7833                   int dx, dy;
7834
7835                   dx = bd->drag.x - ev->root.x;
7836                   dy = bd->drag.y - ev->root.y;
7837                   if (((dx * dx) + (dy * dy)) >
7838                       (e_config->drag_resist * e_config->drag_resist))
7839                     {
7840      /* start drag! */
7841                         if (bd->icon_object)
7842                           {
7843                              Evas_Object *o = NULL;
7844                              Evas_Coord x, y, w, h;
7845                              const char *drag_types[] = { "enlightenment/border" };
7846
7847                              e_object_ref(E_OBJECT(bd));
7848                              evas_object_geometry_get(bd->icon_object,
7849                                                       &x, &y, &w, &h);
7850                              drag_border = e_drag_new(bd->zone->container,
7851                                                       bd->x + bd->fx.x + x,
7852                                                       bd->y + bd->fx.y + y,
7853                                                       drag_types, 1, bd, -1,
7854                                                       NULL,
7855                                                       _e_border_cb_drag_finished);
7856                              o = e_border_icon_add(bd, drag_border->evas);
7857                              if (!o)
7858                                {
7859      /* FIXME: fallback icon for drag */
7860                                    o = evas_object_rectangle_add(drag_border->evas);
7861                                    evas_object_color_set(o, 255, 255, 255, 255);
7862                                }
7863                              e_drag_object_set(drag_border, o);
7864
7865                              e_drag_resize(drag_border, w, h);
7866                              e_drag_start(drag_border, bd->drag.x, bd->drag.y);
7867                           }
7868                         bd->drag.start = 0;
7869                     }
7870                }
7871           }
7872         evas_event_feed_mouse_move(bd->bg_evas, ev->x, ev->y, ev->timestamp, NULL);
7873      }
7874    return ECORE_CALLBACK_PASS_ON;
7875 }
7876
7877 static Eina_Bool
7878 _e_border_cb_grab_replay(void *data __UNUSED__,
7879                          int        type,
7880                          void      *event)
7881 {
7882    Ecore_Event_Mouse_Button *ev;
7883
7884    if (type != ECORE_EVENT_MOUSE_BUTTON_DOWN) return ECORE_CALLBACK_DONE;
7885    ev = event;
7886    if ((e_config->pass_click_on)
7887        || (e_config->always_click_to_raise) // this works even if not on click-to-focus
7888        || (e_config->always_click_to_focus) // this works even if not on click-to-focus
7889       )
7890      {
7891         E_Border *bd;
7892
7893         bd = e_border_find_by_window(ev->event_window);
7894         if (bd)
7895           {
7896              if (bd->cur_mouse_action)
7897                return ECORE_CALLBACK_DONE;
7898              if (ev->event_window == bd->win)
7899                {
7900                   if (!e_bindings_mouse_down_find(E_BINDING_CONTEXT_WINDOW,
7901                                                   E_OBJECT(bd), ev, NULL))
7902                     return ECORE_CALLBACK_PASS_ON;
7903                }
7904           }
7905      }
7906    return ECORE_CALLBACK_DONE;
7907 }
7908
7909 static void
7910 _e_border_cb_drag_finished(E_Drag     *drag,
7911                            int dropped __UNUSED__)
7912 {
7913    E_Border *bd;
7914
7915    bd = drag->data;
7916    e_object_unref(E_OBJECT(bd));
7917    drag_border = NULL;
7918 }
7919
7920 #ifdef _F_USE_DESK_WINDOW_PROFILE_
7921 static Eina_Bool
7922 _e_border_cb_desk_window_profile_change(void *data  __UNUSED__,
7923                                         int ev_type __UNUSED__,
7924                                         void       *ev)
7925 {
7926    E_Event_Desk_Window_Profile_Change *e;
7927    Eina_List *l;
7928    E_Border *bd;
7929
7930    e = ev;
7931    EINA_LIST_FOREACH(borders, l, bd)
7932      {
7933         if ((bd) && (!e_object_is_del(E_OBJECT(bd))))
7934           {
7935              bd->client.e.fetch.profile_list = 1;
7936              bd->changed = 1;
7937           }
7938      }
7939    return ECORE_CALLBACK_PASS_ON;
7940 }
7941 #endif
7942
7943 #ifdef _F_ZONE_WINDOW_ROTATION_
7944 static Eina_Bool
7945 _e_border_cb_zone_rotation_change_begin(void *data  __UNUSED__,
7946                                         int ev_type __UNUSED__,
7947                                         void       *ev)
7948 {
7949    E_Event_Zone_Rotation_Change_Begin *e = ev;
7950
7951    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
7952    if ((!e) || (!e->zone)) return ECORE_CALLBACK_PASS_ON;
7953
7954    if (!_e_border_rotation_zone_set(e->zone))
7955      {
7956         /* there is no border which supports window manager rotation */
7957         e_zone_rotation_update_cancel(e->zone);
7958      }
7959    return ECORE_CALLBACK_PASS_ON;
7960 }
7961
7962 static void
7963 _e_border_cb_rotation_sync_job(void *data)
7964 {
7965    E_Zone *zone = data;
7966    Eina_List *l;
7967    E_Border_Rotation_Info *info = NULL;
7968
7969    ELB(ELBT_ROT, "DO ROTATION SYNC_JOB", zone->id);
7970
7971    if (rot.list)
7972      {
7973         EINA_LIST_FOREACH(rot.list, l, info)
7974            _e_border_hook_call(E_BORDER_HOOK_ROTATION_LIST_ADD, info->bd);
7975         if (!rot.wait_prepare_done)
7976           {
7977              _e_border_rotation_change_request(zone);
7978           }
7979      }
7980
7981    // clear job
7982    if (rot.sync_job)
7983      {
7984         ELB(ELBT_ROT, "DEL SYNC_JOB", zone->id);
7985         ecore_job_del(rot.sync_job);
7986         rot.sync_job = NULL;
7987      }
7988 }
7989
7990 static void
7991 _e_border_cb_rotation_async_job(void *data)
7992 {
7993    E_Zone *zone = data;
7994
7995    if (rot.list) goto end;
7996
7997    ELB(ELBT_ROT, "FLUSH ASYNC LIST TO ROT_CHANGE_REQ", zone->id);
7998
7999    _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
8000    rot.async_list = NULL;
8001
8002 end:
8003    // clear async job
8004    if (rot.async_job)
8005      {
8006         ELB(ELBT_ROT, "DEL ASYNC_JOB", zone->id);
8007         ecore_job_del(rot.async_job);
8008         rot.async_job = NULL;
8009      }
8010 }
8011
8012 static Eina_Bool
8013 _e_border_rotation_change_prepare_timeout(void *data)
8014 {
8015    E_Zone *zone = data;
8016    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
8017
8018    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE_PREPARE", 0);
8019
8020    if ((zone) && (rot.wait_prepare_done))
8021      {
8022         if (rot.list)
8023           {
8024              _e_border_rotation_change_request(zone);
8025              if (rot.prepare_timer)
8026                ecore_timer_del(rot.prepare_timer);
8027              rot.prepare_timer = NULL;
8028              rot.wait_prepare_done = EINA_FALSE;
8029           }
8030      }
8031    return ECORE_CALLBACK_CANCEL;
8032 }
8033
8034 static void
8035 _e_border_rotation_change_request(E_Zone *zone)
8036 {
8037    if (!e_config->wm_win_rotation) return;
8038    if (!rot.list) return;
8039    if (eina_list_count(rot.list) <= 0) return;
8040    if (zone->rot.block_count) return;
8041
8042    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8043    rot.prepare_timer = NULL;
8044    rot.wait_prepare_done = EINA_FALSE;
8045
8046    _e_border_rotation_list_flush(rot.list, EINA_FALSE);
8047
8048    if (rot.done_timer)
8049      ecore_timer_del(rot.done_timer);
8050    ELB(ELBT_ROT, "ADD TIMEOUT ROT_DONE", zone->id);
8051    rot.done_timer = ecore_timer_add(5.0f,
8052                                     _e_border_rotation_change_done_timeout,
8053                                     NULL);
8054 }
8055
8056 static void
8057 _e_border_rotation_list_flush(Eina_List *list, Eina_Bool flush)
8058 {
8059    Eina_List *l;
8060    E_Border_Rotation_Info *info =NULL;
8061    int x, y, w, h;
8062
8063    EINA_LIST_FOREACH (list, l, info)
8064      {
8065         if (!info->bd) continue;
8066         if ((info->bd->client.e.state.rot.wait_for_done) &&
8067             (info->bd->client.e.state.rot.wait_done_ang == info->ang)) continue;
8068
8069         _e_border_event_border_rotation_change_begin_send(info->bd);
8070
8071         /* resize border */
8072         info->win_resize = _e_border_rotation_pre_resize(info->bd, info->ang, &x, &y, &w, &h);
8073         info->bd->client.e.state.rot.pending_change_request = info->win_resize;
8074
8075         info->x = x; info->y = y;
8076         info->w = w; info->h = h;
8077
8078         ELBF(ELBT_ROT, 1, info->bd->client.win,
8079              "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d",
8080              info->ang, info->win_resize, info->w, info->h);
8081
8082         ecore_x_e_window_rotation_change_prepare_send
8083            (info->bd->client.win, info->ang,
8084             info->win_resize, info->w, info->h);
8085
8086         if (!info->bd->client.e.state.rot.pending_change_request)
8087           {
8088              ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST");
8089              ecore_x_e_window_rotation_change_request_send(info->bd->client.win,
8090                                                            info->ang);
8091              info->bd->client.e.state.rot.wait_for_done = 1;
8092              info->bd->client.e.state.rot.wait_done_ang = info->ang;
8093           }
8094      }
8095
8096    if (flush)
8097      {
8098         EINA_LIST_FREE(list, info)
8099            E_FREE(info);
8100      }
8101 }
8102
8103 EAPI void
8104 e_border_rotation_list_clear(E_Zone *zone, Eina_Bool send_request)
8105 {
8106    E_Border_Rotation_Info *info = NULL;
8107
8108    if (send_request) _e_border_rotation_change_request(zone);
8109    else
8110      {
8111         EINA_LIST_FREE(rot.list, info)
8112            E_FREE(info);
8113         rot.list = NULL;
8114      }
8115 }
8116
8117 static void
8118 _e_border_rotation_list_remove(E_Border *bd)
8119 {
8120    Eina_List *l = NULL;
8121    E_Border_Rotation_Info *info = NULL;
8122    E_Event_Border_Rotation_Change_End *ev = NULL;
8123    Eina_Bool found = EINA_FALSE;
8124
8125    if (!e_config->wm_win_rotation) return;
8126
8127    EINA_LIST_FOREACH(rot.list, l, info)
8128      {
8129         if (info->bd == bd)
8130           {
8131              rot.list = eina_list_remove(rot.list, info);
8132              E_FREE(info);
8133              found = EINA_TRUE;
8134           }
8135      }
8136
8137    if (bd->client.e.state.rot.wait_for_done)
8138      {
8139         bd->client.e.state.rot.wait_for_done = 0;
8140
8141         /* if we make the border event in the _e_border_free function,
8142          * then we may meet a crash problem, only work this at least e_border_hide.
8143          */
8144         if (!e_object_is_del(E_OBJECT(bd)))
8145           {
8146              ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
8147              if (ev)
8148                {
8149                   ev->border = bd;
8150                   e_object_ref(E_OBJECT(bd));
8151                   ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_END,
8152                                   ev,
8153                                   _e_border_event_border_rotation_change_end_free,
8154                                   NULL);
8155                }
8156           }
8157
8158         if ((found) &&
8159             (eina_list_count(rot.list) == 0))
8160           {
8161              _e_border_rotation_change_done();
8162           }
8163      }
8164 }
8165
8166 static Eina_Bool
8167 _e_border_rotation_change_done_timeout(void *data __UNUSED__)
8168 {
8169    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_CANCEL;
8170    ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE", 0);
8171    _e_border_rotation_change_done();
8172    return ECORE_CALLBACK_CANCEL;
8173 }
8174
8175 static void
8176 _e_border_rotation_change_done(void)
8177 {
8178    E_Manager *m = NULL;
8179    E_Border_Rotation_Info *info = NULL;
8180
8181    if (!e_config->wm_win_rotation) return;
8182
8183    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
8184    rot.prepare_timer = NULL;
8185
8186    rot.wait_prepare_done = EINA_FALSE;
8187
8188    if (rot.done_timer) ecore_timer_del(rot.done_timer);
8189    rot.done_timer = NULL;
8190
8191    EINA_LIST_FREE(rot.list, info)
8192      {
8193         if (info->bd)
8194           {
8195              ELB(ELBT_ROT, "TIMEOUT ROT_DONE", info->bd->client.win);
8196              if (info->bd->client.e.state.rot.pending_show)
8197                {
8198                   ELB(ELBT_ROT, "SHOW PEND(TIMEOUT)", info->bd->client.win);
8199                   e_border_show(info->bd);
8200                   info->bd->client.e.state.rot.pending_show = 0;
8201                }
8202              info->bd->client.e.state.rot.wait_for_done = 0;
8203           }
8204         E_FREE(info);
8205      }
8206
8207    _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
8208
8209    rot.list = NULL;
8210    rot.async_list = NULL;
8211
8212    m = e_manager_current_get();
8213    e_manager_comp_screen_unlock(m);
8214    e_zone_rotation_update_done(e_util_zone_current_get(m));
8215 }
8216
8217 static int
8218 _prev_angle_get(Ecore_X_Window win)
8219 {
8220    int ret, count = 0, ang = -1;
8221    unsigned char* data = NULL;
8222
8223    ret = ecore_x_window_prop_property_get
8224       (win, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
8225       ECORE_X_ATOM_CARDINAL, 32, &data, &count);
8226
8227    if ((ret) && (data) && (count))
8228      ang = ((int *)data)[0];
8229    if (data) free(data);
8230    return ang;
8231 }
8232
8233 /* get proper rotation value using preferred rotation and list of available rotations */
8234 static int
8235 _e_border_rotation_get(E_Border *bd,
8236                        int       base_ang)
8237 {
8238    int ang = -1;
8239    int current_ang = bd->client.e.state.rot.curr;
8240    unsigned int i;
8241    Eina_Bool found = EINA_FALSE;
8242    Eina_Bool found_curr_ang = EINA_FALSE;
8243
8244    if (!e_config->wm_win_rotation) return ang;
8245    if (!bd->client.e.state.rot.app_set) return ang;
8246
8247    if (bd->client.e.state.rot.preferred_rot != -1)
8248      {
8249         ang = bd->client.e.state.rot.preferred_rot;
8250         ELBF(ELBT_ROT, 0, bd->client.win, "ang:%d base_ang:%d", ang, base_ang);
8251      }
8252    else if ((bd->client.e.state.rot.available_rots) &&
8253             (bd->client.e.state.rot.count))
8254      {
8255         for (i = 0; i < bd->client.e.state.rot.count; i++)
8256           {
8257              if (bd->client.e.state.rot.available_rots[i] == base_ang)
8258                {
8259                   ang = base_ang;
8260                   found = EINA_TRUE;
8261                   break;
8262                }
8263              if (bd->client.e.state.rot.available_rots[i] == current_ang)
8264                found_curr_ang = EINA_TRUE;
8265           }
8266
8267         /* do nothing. this window wants to maintain current state.
8268          * for example, window's available_rots: 0, 90, 270,
8269          * current zone rotation request: 180. the WM does nothing
8270          * for this window.
8271          */
8272         if (!found)
8273           {
8274              if ((bd->client.e.state.rot.curr != -1) && (found_curr_ang))
8275                ang = bd->client.e.state.rot.curr;
8276              else
8277                ang = bd->client.e.state.rot.available_rots[0];
8278           }
8279      }
8280    else
8281      {
8282         /* In this case, border doesn't have a list of
8283          * available rotations, thus WM should request
8284          * rotation with '0' degree to the application.
8285          */
8286         ang = 0;
8287      }
8288
8289    return ang;
8290 }
8291
8292 static int
8293 _e_border_rotation_angle_get(E_Border *bd)
8294 {
8295    E_Zone *zone = bd->zone;
8296    int will_ang = 0;
8297    int _ang = 0;
8298    int ret = -1;
8299
8300    if (!e_config->wm_win_rotation) return ret;
8301    if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) return ret;
8302
8303    ELB(ELBT_ROT, "CHECK ROT", bd->client.win);
8304
8305    // the window with "ECORE_X_WINDOW_TYPE_NORMAL" type
8306    // should follow the state of rotation of zone.
8307    if ((bd->parent) &&
8308        (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL))
8309      will_ang = bd->parent->client.e.state.rot.curr;
8310    else will_ang = zone->rot.curr;
8311
8312    if (bd->client.vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE)
8313      {
8314         ELBF(ELBT_ROT, 1, bd->client.win,
8315              "%s->parent:0x%08x (support:%d app_set:%d ang:%d)",
8316              (rot.vkbd == bd) ? "vkbd" : "prediction",
8317              bd->parent ? bd->parent->client.win : 0,
8318              bd->parent ? bd->parent->client.e.state.rot.support : -1,
8319              bd->parent ? bd->parent->client.e.state.rot.app_set : -1,
8320              bd->parent ? bd->parent->client.e.state.rot.curr : -1);
8321
8322         if (bd->parent)
8323           {
8324              will_ang = bd->parent->client.e.state.rot.curr;
8325              if ((!bd->parent->client.e.state.rot.support) &&
8326                  (!bd->parent->client.e.state.rot.app_set))
8327                {
8328                   will_ang = 0;
8329                }
8330           }
8331      }
8332
8333    if ((!bd->client.e.state.rot.app_set) &&
8334        (!bd->client.e.state.rot.support))
8335      {
8336         /* hack for magnifier and keyboard popup */
8337         if ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER) ||
8338             (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP))
8339           {
8340              ELB(ELBT_BD, "MAG", bd->client.win);
8341              will_ang = 0;
8342              if ((rot.vkbd) && (rot.vkbd->visible))
8343                will_ang = rot.vkbd->client.e.state.rot.curr;
8344           }
8345      }
8346
8347    if (bd->client.e.state.rot.app_set)
8348      {
8349         /* utility type window should be rotated according to
8350          * rotation of the transient_for window.
8351          */
8352         if ((bd->parent) &&
8353             (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UTILITY))
8354           {
8355              will_ang = bd->parent->client.e.state.rot.curr;
8356              if ((!bd->parent->client.e.state.rot.support) &&
8357                  (!bd->parent->client.e.state.rot.app_set))
8358                {
8359                   /* if transient_for window doesn't support rotation feature,
8360                    * then this window should't be rotated.
8361                    * TODO: need to check whether window supports '0' degree or not.
8362                    */
8363                   will_ang = 0;
8364                   ELBF(ELBT_ROT, 0, bd->client.win,
8365                        "GET ROT ang:%d Transient_For:0x%08x Not support rot",
8366                        will_ang, bd->parent->client.win);
8367                }
8368              else
8369                {
8370                   will_ang = _e_border_rotation_get(bd->parent, will_ang);
8371                   ELBF(ELBT_ROT, 0, bd->client.win,
8372                        "GET ROT ang:%d Transient_For:0x%08x",
8373                        will_ang, bd->parent->client.win);
8374                }
8375           }
8376         else
8377           {
8378              will_ang = _e_border_rotation_get(bd, will_ang);
8379              ELBF(ELBT_ROT, 0, bd->client.win, "GET ROT ang:%d bd->parent:0x%08x type:%d",
8380                   will_ang, bd->parent ? bd->parent->client.win : 0,
8381                   bd->client.netwm.type);
8382           }
8383      }
8384
8385    if (bd->new_client)
8386      {
8387         _ang = _prev_angle_get(bd->client.win);
8388         if (_ang != -1)
8389           bd->client.e.state.rot.curr = _ang;
8390         ELBF(ELBT_ROT, 1, bd->client.win, "prev_ang:%d", _ang);
8391      }
8392
8393    if (bd->client.e.state.rot.curr != will_ang)
8394      ret = will_ang;
8395
8396    return ret;
8397 }
8398
8399
8400 static Eina_Bool
8401 _e_border_rotation_zone_set(E_Zone *zone)
8402 {
8403    E_Border_List *l = NULL;
8404    E_Border *bd = NULL;
8405    Eina_Bool ret = EINA_FALSE;
8406
8407    if (!e_config->wm_win_rotation) return EINA_FALSE;
8408
8409    l = e_container_border_list_last(zone->container);
8410    if (!l) return ret;
8411
8412    /* step 1. make the list needs to be rotated. */
8413    while ((bd = e_container_border_list_prev(l)))
8414      {
8415         if (!bd) continue;
8416
8417         // if this window has parent and window type isn't "ECORE_X_WINDOW_TYPE_NORMAL",
8418         // it will be rotated when parent do rotate itself.
8419         // so skip here.
8420         if ((bd->parent) &&
8421             (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL)) continue;
8422
8423         // default type is "E_BORDER_ROTATION_TYPE_NORMAL",
8424         // but it can be changed to "E_BORDER_ROTATION_TYPE_DEPENDENT" by illume according to its policy.
8425         // if it's not normal type window, will be rotated by illume.
8426         // so skip here.
8427         if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) continue;
8428
8429         if ((!bd->visible) ||
8430             (!E_INTERSECTS(bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h,
8431                            bd->x, bd->y, bd->w, bd->h))) continue;
8432
8433         if (_e_border_rotatable_check(bd, zone->rot.curr))
8434           {
8435              ELBF(ELBT_ROT, 0, bd->client.win, "ROT_SET(main) curr:%d != TOBE:%d",
8436                   bd->client.e.state.rot.curr, zone->rot.curr);
8437
8438              ret = e_border_rotation_set(bd, zone->rot.curr);
8439           }
8440      }
8441    if (l) e_container_border_list_free(l);
8442
8443    return ret;
8444 }
8445
8446 EAPI Eina_Bool
8447 e_border_rotation_set(E_Border *bd, int rotation)
8448 {
8449    E_Zone *zone = bd->zone;
8450    E_Border_Rotation_Info *info = NULL;
8451    Eina_List *list, *l;
8452    E_Border *child;
8453
8454    if (rotation < 0) return EINA_FALSE;
8455
8456    /* step 1. check if rotation */
8457    if (!_e_border_rotatable_check(bd, rotation)) return EINA_FALSE;
8458
8459    /* step 2. add to async/sync list */
8460    if ((!zone->rot.block_count) &&
8461        ((!bd->visible) ||
8462         (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))))
8463      {
8464         // send rotation change request later.
8465         // and no need to wait message of rotation done.
8466
8467         // async list add
8468         info = E_NEW(E_Border_Rotation_Info, 1);
8469         if (!info) return EINA_FALSE;
8470         ELB(ELBT_ROT, "ADD ASYNC LIST", 0);
8471         info->bd = bd;
8472         info->ang = rotation;
8473         rot.async_list = eina_list_append(rot.async_list, info);
8474
8475         // add job for sending event.
8476         if (!rot.async_job)
8477           {
8478              ELB(ELBT_ROT, "ADD ASYNC_JOB", bd->client.win);
8479              rot.async_job = ecore_job_add(_e_border_cb_rotation_async_job, zone);
8480           }
8481      }
8482    else
8483      {
8484         // sync list add
8485         info = E_NEW(E_Border_Rotation_Info, 1);
8486         if (!info) return EINA_FALSE;
8487         ELB(ELBT_ROT, "ADD SYNC LIST", 0);
8488         info->bd = bd;
8489         info->ang = rotation;
8490         rot.list = eina_list_append(rot.list, info);
8491
8492         // add job for sending event.
8493         if (!rot.sync_job)
8494           {
8495              ELB(ELBT_ROT, "ADD SYNC_JOB", bd->client.win);
8496              rot.sync_job = ecore_job_add(_e_border_cb_rotation_sync_job, zone);
8497           }
8498
8499         // if there is windows over 2 that has to be rotated or is existed window needs resizing,
8500         // lock the screen.
8501         // but, DO NOT lock the screen when rotation block state.
8502         if ((!zone->rot.block_count) &&
8503             ((eina_list_count(rot.list) == 2)))
8504           e_manager_comp_screen_lock(e_manager_current_get());
8505      }
8506
8507    /* step 3. search rotatable window in this window's child */
8508    list = _e_border_sub_borders_new(bd);
8509    EINA_LIST_FOREACH(list, l, child)
8510      {
8511         // the window which type is "ECORE_X_WINDOW_TYPE_NORMAL" will be rotated itself.
8512         // it shouldn't be rotated by rotation state of parent window.
8513         if (child->client.netwm.type == ECORE_X_WINDOW_TYPE_NORMAL) continue;
8514         if (_e_border_rotatable_check(child, rotation))
8515           {
8516              ELBF(ELBT_ROT, 0, child->client.win, "ROT_SET(child) curr:%d != TOBE:%d",
8517                   bd->client.e.state.rot.curr, rotation);
8518              e_border_rotation_set(child, rotation);
8519           }
8520      }
8521
8522    /* step 4. if there is vkbd window, send message to prepare rotation */
8523    if (_e_border_is_vkbd(bd))
8524      {
8525         ELB(ELBT_ROT, "PENDING ROT_REQ UNTIL GET PREP_DONE", rot.vkbd_ctrl_win);
8526         if (rot.prepare_timer)
8527           ecore_timer_del(rot.prepare_timer);
8528         rot.prepare_timer = NULL;
8529
8530         if (rot.done_timer)
8531           ecore_timer_del(rot.done_timer);
8532         rot.done_timer = NULL;
8533
8534         ELB(ELBT_ROT, "SEND ROT_CHANGE_PREPARE", rot.vkbd_ctrl_win);
8535         ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win,
8536                                                       zone->rot.curr,
8537                                                       EINA_FALSE, 1, 1);
8538         rot.prepare_timer = ecore_timer_add(4.0f,
8539                                             _e_border_rotation_change_prepare_timeout,
8540                                             NULL);
8541
8542         rot.wait_prepare_done = EINA_TRUE;
8543      }
8544
8545    bd->client.e.state.rot.prev = bd->client.e.state.rot.curr;
8546    bd->client.e.state.rot.curr = rotation;
8547
8548    return EINA_TRUE;
8549 }
8550
8551 // check if border is rotatable in ang.
8552 static Eina_Bool
8553 _e_border_rotatable_check(E_Border *bd, int ang)
8554 {
8555    Eina_Bool ret = EINA_FALSE;
8556
8557    if (!bd) return ret;
8558    if (ang < 0) return ret;
8559    if ((!bd->client.e.state.rot.support) && (!bd->client.e.state.rot.app_set)) return ret;
8560    if (e_object_is_del(E_OBJECT(bd))) return ret;
8561
8562    // same with current angle of window, then false return.
8563    if (ang == bd->client.e.state.rot.curr) return ret;
8564
8565    /* basically WM allows only fullscreen window to rotate */
8566    if (bd->client.e.state.rot.preferred_rot == -1)
8567      {
8568         unsigned int i;
8569
8570         if (bd->client.e.state.rot.app_set)
8571           {
8572              if (bd->client.e.state.rot.available_rots &&
8573                  bd->client.e.state.rot.count)
8574                {
8575                   Eina_Bool found = EINA_FALSE;
8576                   for (i = 0; i < bd->client.e.state.rot.count; i++)
8577                     {
8578                        if (bd->client.e.state.rot.available_rots[i] == ang)
8579                          {
8580                             found = EINA_TRUE;
8581                          }
8582                     }
8583                   if (found) ret = EINA_TRUE;
8584                }
8585           }
8586         else
8587           {
8588              ELB(ELBT_ROT, "DO ROT", 0);
8589              ret = EINA_TRUE;
8590           }
8591      }
8592    // if it has preferred rotation angle,
8593    // it will be rotated at border's evaluation time.
8594    // so skip it.
8595    else if (bd->client.e.state.rot.preferred_rot == ang) ret = EINA_TRUE;
8596
8597    return ret;
8598 }
8599
8600 /* check whether virtual keyboard is visible on the zone */
8601 static Eina_Bool
8602 _e_border_is_vkbd(E_Border *bd)
8603 {
8604    if (!e_config->wm_win_rotation) return EINA_FALSE;
8605
8606    if ((rot.vkbd_ctrl_win) &&
8607        (rot.vkbd == bd) &&
8608        (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
8609        (rot.vkbd->visible) &&
8610        (rot.vkbd->zone == bd->zone) &&
8611        (E_INTERSECTS(bd->zone->x, bd->zone->y,
8612                      bd->zone->w, bd->zone->h,
8613                      rot.vkbd->x, rot.vkbd->y,
8614                      rot.vkbd->w, rot.vkbd->h)))
8615      {
8616         return EINA_TRUE;
8617      }
8618    return EINA_FALSE;
8619 }
8620
8621 static Eina_Bool
8622 _e_border_rotation_change_floating_pos(E_Border *bd, int *x, int *y)
8623 {
8624    int new_x, new_y;
8625    int min_title_width=96;
8626
8627    if (!bd) return EINA_FALSE;
8628    if (!x || !y) return EINA_FALSE;
8629
8630    new_x = bd->x;
8631    new_y = bd->y;
8632
8633    // Portrait -> Landscape,  x= pre_x*2, y=pre_y/2
8634    // Landscape -> Portrait,  x= pre_x/2, y=pre_y*2
8635    // guaranteeing the minimum size of titlebar shown, min_title_width
8636    // so user can initiate drag&drop action after rotation changed.
8637    if (bd->client.e.state.rot.curr == 0)
8638      {
8639         if (bd->client.e.state.rot.prev == 90)
8640           {
8641              new_x = (bd->zone->h - bd->h - bd->y) / 2;
8642              new_y = 2 * bd->x;
8643           }
8644         else if (bd->client.e.state.rot.prev == 270)
8645           {
8646              new_x = bd->y / 2;
8647              new_y = (bd->zone->w - bd->w - bd->x) * 2;
8648           }
8649         else if (bd->client.e.state.rot.prev == 180)
8650           {
8651              new_x = bd->zone->w - bd->x - bd->w;
8652              new_y = bd->zone->h - bd->y - bd->h;
8653           }
8654
8655         if(new_x + bd->w < min_title_width)
8656           {
8657              new_x = min_title_width - bd->w;
8658           }
8659         else if(new_x > bd->zone->w - min_title_width)
8660           {
8661              new_x = bd->zone->w - min_title_width;
8662           }
8663      }
8664    else if (bd->client.e.state.rot.curr == 90)
8665      {
8666         if (bd->client.e.state.rot.prev == 0)
8667           {
8668              new_x = bd->y / 2;
8669              new_y = bd->zone->h - (2 * bd->x) - bd->w;
8670           }
8671         else if (bd->client.e.state.rot.prev == 270)
8672           {
8673              new_x = bd->zone->w - bd->x - bd->w;
8674              new_y = bd->zone->h - bd->y - bd->h;
8675           }
8676         else if (bd->client.e.state.rot.prev == 180)
8677           {
8678              new_x = (bd->zone->h - bd->y - bd->h) / 2;
8679              new_y = bd->zone->h - (2 * (bd->zone->w - bd->x - bd->w)) - bd->w;
8680           }
8681
8682         if(new_y > bd->zone->h - min_title_width)
8683           {
8684              new_y = bd->zone->h - min_title_width;
8685           }
8686         else if(new_y < min_title_width - bd->w)
8687           {
8688              new_y = min_title_width - bd->w;
8689           }
8690      }
8691    else if (bd->client.e.state.rot.curr == 270)
8692      {
8693         if (bd->client.e.state.rot.prev == 0)
8694           {
8695              new_x = bd->zone->w - bd->h - (bd->y / 2);
8696              new_y = bd->x * 2;
8697           }
8698         else if (bd->client.e.state.rot.prev == 90)
8699           {
8700              new_x = bd->zone->w - bd->x - bd->w;
8701              new_y = bd->zone->h - bd->y - bd->h;
8702           }
8703         else if (bd->client.e.state.rot.prev == 180)
8704           {
8705              new_x = bd->zone->w - bd->x - bd->w;
8706              new_y = bd->zone->h - bd->y - bd->h;
8707
8708              new_x = bd->zone->w - bd->h - ((bd->zone->h - bd->y - bd->h) / 2);
8709              new_y = (bd->zone->w - bd->x - bd->w) * 2;
8710           }
8711
8712         if(new_y >  bd->zone->h - min_title_width)
8713           {
8714              new_y = bd->zone->h - min_title_width;
8715           }
8716         else if( new_y + bd->w < min_title_width)
8717           {
8718              new_y = min_title_width - bd->w ;
8719           }
8720      }
8721    else if (bd->client.e.state.rot.curr == 180)
8722      {
8723         if (bd->client.e.state.rot.prev == 0)
8724           {
8725              new_x = bd->zone->w - bd->x - bd->w;
8726              new_y = bd->zone->h - bd->y - bd->h;
8727           }
8728         else if (bd->client.e.state.rot.prev == 90)
8729           {
8730              new_x = bd->zone->w - ((bd->zone->h - bd->h - bd->y) / 2) - bd->h;
8731              new_y = bd->zone->h - (2 * bd->x) - bd->w;
8732           }
8733         else if (bd->client.e.state.rot.prev == 270)
8734           {
8735              new_x = bd->zone->w - (bd->y / 2) - bd->h;
8736              new_y = bd->zone->h - ((bd->zone->w - bd->w - bd->x) * 2) - bd->w;
8737           }
8738
8739         if(new_x + bd->w < min_title_width)
8740           {
8741              new_x = min_title_width - bd->w;
8742           }
8743         else if(new_x > bd->zone->w - min_title_width)
8744           {
8745              new_x = bd->zone->w - min_title_width;
8746           }
8747      }
8748
8749    ELBF(ELBT_ROT, 0, bd->client.win,
8750         "Floating Mode. ANGLE (%d->%d), POS (%d,%d) -> (%d,%d)",
8751         bd->client.e.state.rot.prev, bd->client.e.state.rot.curr,
8752         bd->x, bd->y, new_x, new_y);
8753
8754    if ((new_x == *x) &&
8755        (new_y == *y))
8756      {
8757         return EINA_FALSE;
8758      }
8759
8760    *x = new_x;
8761    *y = new_y;
8762
8763    return EINA_TRUE;
8764 }
8765
8766 #define SIZE_EQUAL_TO_ZONE(a, z) \
8767    ((((a)->w) == ((z)->w)) &&    \
8768     (((a)->h) == ((z)->h)))
8769 static Eina_Bool
8770 _e_border_rotation_pre_resize(E_Border *bd, int rotation, int *x, int *y, int *w, int *h)
8771 {
8772    E_Zone *zone = bd->zone;
8773    int rot_dif;
8774    int _x, _y, _w, _h;
8775    Eina_Bool move = EINA_FALSE;
8776    Eina_Bool hint = EINA_FALSE;
8777    Eina_Bool resize = EINA_FALSE;
8778
8779    if (x) *x = bd->x;
8780    if (y) *y = bd->y;
8781    if (w) *w = bd->w;
8782    if (h) *h = bd->h;
8783
8784    if (SIZE_EQUAL_TO_ZONE(bd, zone)) return resize;
8785
8786    ELB(ELBT_ROT, "SIZE DIFF WITH ZONE", 0);
8787    ELBF(ELBT_ROT, 0, bd->client.win, "ORIGIN_SIZE name:%s (%d,%d) %dx%d",
8788         bd->client.icccm.name, bd->x, bd->y, bd->w, bd->h);
8789
8790    hint = _e_border_rotation_geom_get(bd, bd->zone, rotation,
8791                                       &_x, &_y, &_w, &_h, &move);
8792    if (hint)
8793      {
8794         _e_border_move_resize_internal(bd, _x, _y, _w, _h, EINA_TRUE, move);
8795         resize = EINA_TRUE;
8796         ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
8797              bd->client.icccm.name, _x, _y, _w, _h);
8798      }
8799    else
8800      {
8801         _x = bd->x; _y = bd->y;
8802         _w = bd->w; _h = bd->h;
8803
8804         if (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)
8805           move = _e_border_rotation_change_floating_pos(bd, &_x, &_y);
8806         else
8807           move = EINA_FALSE;
8808
8809         rot_dif = bd->client.e.state.rot.prev - rotation;
8810         if (rot_dif < 0) rot_dif = -rot_dif;
8811         if (rot_dif != 180)
8812           {
8813              if (w != h)
8814                {
8815                   _w = bd->h;
8816                   _h = bd->w;
8817                   resize = EINA_TRUE;
8818
8819                   _e_border_move_resize_internal(bd, _x, _y, _w, _h,
8820                                                  EINA_TRUE, EINA_TRUE);
8821                   ELBF(ELBT_ROT, 0, bd->client.win, "MANUAL_RESIZE name:%s (%d,%d) %dx%d",
8822                        bd->client.icccm.name, _x, _y, _w, _h);
8823
8824                }
8825           }
8826
8827         if (!resize && move)
8828           _e_border_move_internal(bd, _x, _y, EINA_TRUE);
8829      }
8830
8831    if (resize)
8832      {
8833         if (x) *x = _x;
8834         if (y) *y = _y;
8835         if (w) *w = _w;
8836         if (h) *h = _h;
8837      }
8838
8839    return resize;
8840 }
8841
8842 static Eina_Bool
8843 _e_border_cb_window_configure(void *data    __UNUSED__,
8844                               int   ev_type __UNUSED__,
8845                               void         *ev)
8846 {
8847    Ecore_X_Event_Window_Configure *e = ev;
8848    E_Border_Rotation_Info *info = NULL;
8849    Eina_List *l;
8850    Eina_Bool found = EINA_FALSE;
8851
8852    if (!e) return ECORE_CALLBACK_PASS_ON;
8853    if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON;
8854
8855    E_Border *bd = e_border_find_by_client_window(e->win);
8856    if (!bd) return ECORE_CALLBACK_PASS_ON;
8857
8858    if (bd->client.e.state.rot.pending_change_request)
8859      {
8860         if ((e->w == bd->w) && (e->h == bd->h))
8861           {
8862              ELB(ELBT_BD, "GET CONFIGURE_NOTI (ROTATION)", bd->client.win);
8863              bd->client.e.state.rot.pending_change_request = 0;
8864
8865              if ((bd->client.e.state.rot.wait_for_done) &&
8866                  (bd->client.e.state.rot.wait_done_ang == bd->client.e.state.rot.curr)) goto end;
8867
8868              // if this window is rotation dependent window and zone is blocked to rotate,
8869              // then skip here, request will be sent after cancel block.
8870              if ((bd->client.e.state.rot.type == E_BORDER_ROTATION_TYPE_DEPENDENT) &&
8871                  (bd->zone->rot.block_count)) goto end;
8872
8873              EINA_LIST_FOREACH(rot.list, l, info)
8874                 if (info->bd == bd) found = EINA_TRUE;
8875              // send request message if it's async rotation window,
8876              // even if wait prepare done.
8877              if ((found) && (rot.wait_prepare_done)) goto end;
8878
8879              ELBF(ELBT_ROT, 0, bd->client.win,
8880                   "SEND ROT_CHANGE_REQUEST a%d %dx%d",
8881                   bd->client.e.state.rot.curr,
8882                   bd->w, bd->h);
8883              ecore_x_e_window_rotation_change_request_send(bd->client.win,
8884                                                            bd->client.e.state.rot.curr);
8885              bd->client.e.state.rot.wait_for_done = 1;
8886              bd->client.e.state.rot.wait_done_ang = bd->client.e.state.rot.curr;
8887           }
8888      }
8889
8890 end:
8891    return ECORE_CALLBACK_PASS_ON;
8892 }
8893
8894 static Eina_Bool
8895 _e_border_rotation_geom_get(E_Border  *bd,
8896                             E_Zone    *zone,
8897                             int        ang,
8898                             int       *x,
8899                             int       *y,
8900                             int       *w,
8901                             int       *h,
8902                             Eina_Bool *move)
8903 {
8904    if (!e_config->wm_win_rotation) return EINA_FALSE;
8905
8906    Eina_Bool res = EINA_FALSE;
8907    Eina_Bool _move = EINA_TRUE;
8908    int _x = bd->x;
8909    int _y = bd->y;
8910    int _w = bd->w;
8911    int _h = bd->h;
8912
8913    if (x) *x = bd->x;
8914    if (y) *y = bd->y;
8915    if (w) *w = bd->w;
8916    if (h) *h = bd->h;
8917    if (move) *move = EINA_TRUE;
8918
8919    if (bd->client.e.state.rot.geom_hint)
8920      {
8921         switch (ang)
8922           {
8923            case   0:
8924               _w = bd->client.e.state.rot.geom[0].w;
8925               _h = bd->client.e.state.rot.geom[0].h;
8926               if (_w == 0) _w = bd->w;
8927               if (_h == 0) _h = bd->h;
8928               _x = 0; _y = zone->h - _h;
8929               break;
8930            case  90:
8931               _w = bd->client.e.state.rot.geom[1].w;
8932               _h = bd->client.e.state.rot.geom[1].h;
8933               if (_w == 0) _w = bd->w;
8934               if (_h == 0) _h = bd->h;
8935               _x = zone->w - _w; _y = 0;
8936               break;
8937            case 180:
8938               _w = bd->client.e.state.rot.geom[2].w;
8939               _h = bd->client.e.state.rot.geom[2].h;
8940               if (_w == 0) _w = bd->w;
8941               if (_h == 0) _h = bd->h;
8942               _x = 0; _y = 0;
8943               break;
8944            case 270:
8945               _w = bd->client.e.state.rot.geom[3].w;
8946               _h = bd->client.e.state.rot.geom[3].h;
8947               if (_w == 0) _w = bd->w;
8948               if (_h == 0) _h = bd->h;
8949               _x = 0; _y = 0;
8950               break;
8951           }
8952
8953         if (x) *x = _x;
8954         if (y) *y = _y;
8955         if (w) *w = _w;
8956         if (h) *h = _h;
8957
8958         if (!((rot.vkbd) && (rot.vkbd == bd)))
8959           {
8960              if (x) *x = bd->x;
8961              if (y) *y = bd->y;
8962              if (move) *move = EINA_FALSE;
8963           }
8964
8965         res = EINA_TRUE;
8966      }
8967
8968    if (res)
8969      {
8970         _x = 0; _y = 0; _w = 0; _h = 0;
8971         if (x) _x = *x;
8972         if (y) _y = *y;
8973         if (w) _w = *w;
8974         if (h) _h = *h;
8975         if (move) _move = *move;
8976
8977         ELBF(ELBT_ROT, 1, bd->client.win,
8978              "GET SIZE_HINT[%d] %d,%d %dx%d move:%d",
8979              ang, _x, _y, _w, _h, _move);
8980      }
8981
8982    return res;
8983 }
8984 #endif
8985
8986 static Eina_Bool
8987 _e_border_post_move_resize_job(void *data)
8988 {
8989    E_Border *bd;
8990
8991    bd = (E_Border *)data;
8992    if (bd->post_move)
8993      {
8994         E_Border *tmp;
8995         Eina_List *l;
8996
8997         EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
8998           ecore_x_window_move(tmp->win,
8999                               bd->x +
9000                               bd->client_inset.l +
9001                               bd->fx.x +
9002                               tmp->client.e.state.video_position.x,
9003                               bd->y +
9004                               bd->client_inset.t +
9005                               bd->fx.y +
9006                               tmp->client.e.state.video_position.y);
9007      }
9008    if (bd->client.e.state.video)
9009      {
9010         E_Border *parent;
9011
9012         parent = bd->client.e.state.video_parent_border;
9013         ecore_x_window_move(bd->win,
9014                             parent->x +
9015                             parent->client_inset.l +
9016                             parent->fx.x +
9017                             bd->client.e.state.video_position.x,
9018                             parent->y +
9019                             parent->client_inset.t +
9020                             parent->fx.y +
9021                             bd->client.e.state.video_position.y);
9022      }
9023    else if ((bd->post_move) && (bd->post_resize))
9024      {
9025         ecore_x_window_move_resize(bd->win,
9026                                    bd->x + bd->fx.x,
9027                                    bd->y + bd->fx.y,
9028                                    bd->w, bd->h);
9029      }
9030    else if (bd->post_move)
9031      {
9032         ecore_x_window_move(bd->win, bd->x + bd->fx.x, bd->y + bd->fx.y);
9033      }
9034    else if (bd->post_resize)
9035      {
9036         ecore_x_window_resize(bd->win, bd->w, bd->h);
9037      }
9038
9039    if (bd->client.e.state.video)
9040      {
9041         fprintf(stderr, "%x: [%i, %i] [%i, %i]\n",
9042                 bd->win,
9043                 bd->client.e.state.video_parent_border->x +
9044                 bd->client.e.state.video_parent_border->client_inset.l +
9045                 bd->client.e.state.video_parent_border->fx.x +
9046                 bd->client.e.state.video_position.x,
9047                 bd->client.e.state.video_parent_border->y +
9048                 bd->client.e.state.video_parent_border->client_inset.t +
9049                 bd->client.e.state.video_parent_border->fx.y +
9050                 bd->client.e.state.video_position.y,
9051                 bd->w, bd->h);
9052      }
9053
9054    if (bd->post_show)
9055      {
9056         if (bd->visible)
9057           {
9058              bd->post_job = NULL;
9059              _e_border_show(bd);
9060           }
9061      }
9062    bd->post_show = 0;
9063    bd->post_move = 0;
9064    bd->post_resize = 0;
9065    bd->post_job = NULL;
9066    return ECORE_CALLBACK_CANCEL;
9067 }
9068
9069 static void
9070 _e_border_container_layout_hook(E_Container *con)
9071 {
9072    _e_border_hook_call(E_BORDER_HOOK_CONTAINER_LAYOUT, con);
9073 }
9074
9075 static void
9076 _e_border_eval0(E_Border *bd)
9077 {
9078    int change_urgent = 0;
9079    int rem_change = 0;
9080 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9081    Eina_Bool need_desk_set = EINA_FALSE;
9082 #endif
9083 #ifdef _F_ZONE_WINDOW_ROTATION_
9084    Eina_Bool need_rotation_set = EINA_FALSE;
9085
9086    if ((e_config->wm_win_rotation) &&
9087        (bd->client.icccm.fetch.transient_for))
9088      {
9089         if (((rot.vkbd) && (rot.vkbd == bd)) ||
9090             ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))
9091           {
9092              need_rotation_set = EINA_TRUE;
9093              ELB(ELBT_BD, "UPDATE TRANSIENT_FOR", bd->client.win);
9094           }
9095      }
9096 #endif
9097
9098    if (e_object_is_del(E_OBJECT(bd)))
9099      {
9100         CRI("_e_border_eval(%p) with deleted border!\n", bd);
9101         bd->changed = 0;
9102         return;
9103      }
9104
9105    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_FETCH, bd);
9106
9107    bd->changes.border = 0;
9108
9109    /* fetch any info queued to be fetched */
9110    if (bd->client.netwm.fetch.state)
9111      {
9112         e_hints_window_state_get(bd);
9113         bd->client.netwm.fetch.state = 0;
9114         rem_change = 1;
9115      }
9116    if (bd->client.icccm.fetch.client_leader)
9117      {
9118         /* TODO: What do to if the client leader isn't mapped yet? */
9119         E_Border *bd_leader = NULL;
9120
9121         bd->client.icccm.client_leader = ecore_x_icccm_client_leader_get(bd->client.win);
9122         if (bd->client.icccm.client_leader)
9123           bd_leader = e_border_find_by_client_window(bd->client.icccm.client_leader);
9124         if (bd->leader)
9125           {
9126              if (bd->leader != bd_leader)
9127                {
9128                   bd->leader->group = eina_list_remove(bd->leader->group, bd);
9129                   if (bd->leader->modal == bd) bd->leader->modal = NULL;
9130                   bd->leader = NULL;
9131                }
9132              else
9133                bd_leader = NULL;
9134           }
9135         /* If this border is the leader of the group, don't register itself */
9136         if ((bd_leader) && (bd_leader != bd))
9137           {
9138              bd_leader->group = eina_list_append(bd_leader->group, bd);
9139              bd->leader = bd_leader;
9140              /* Only set the window modal to the leader it there is no parent */
9141              if ((e_config->modal_windows) && (bd->client.netwm.state.modal) &&
9142                  ((!bd->parent) || (bd->parent->modal != bd)))
9143                {
9144                   bd->leader->modal = bd;
9145                   if (bd->leader->focused)
9146                     e_border_focus_set(bd, 1, 1);
9147                   else
9148                     {
9149                        Eina_List *l;
9150                        E_Border *child;
9151
9152                        EINA_LIST_FOREACH(bd->leader->group, l, child)
9153                          {
9154                             if ((child != bd) && (child->focused))
9155                               e_border_focus_set(bd, 1, 1);
9156                          }
9157                     }
9158                }
9159           }
9160         bd->client.icccm.fetch.client_leader = 0;
9161         rem_change = 1;
9162      }
9163    if (bd->client.icccm.fetch.title)
9164      {
9165         char *title = ecore_x_icccm_title_get(bd->client.win);
9166         eina_stringshare_replace(&bd->client.icccm.title, title);
9167         if (title) free(title);
9168
9169         if (bd->bg_object)
9170           edje_object_part_text_set(bd->bg_object, "e.text.title",
9171                                     bd->client.icccm.title);
9172         bd->client.icccm.fetch.title = 0;
9173         rem_change = 1;
9174      }
9175    if (bd->client.netwm.fetch.name)
9176      {
9177         char *name;
9178         ecore_x_netwm_name_get(bd->client.win, &name);
9179         eina_stringshare_replace(&bd->client.netwm.name, name);
9180         if (name) free(name);
9181
9182         if (bd->bg_object)
9183           edje_object_part_text_set(bd->bg_object, "e.text.title",
9184                                     bd->client.netwm.name);
9185         bd->client.netwm.fetch.name = 0;
9186         rem_change = 1;
9187      }
9188    if (bd->client.icccm.fetch.name_class)
9189      {
9190         const char *pname, *pclass;
9191         char *nname, *nclass;
9192
9193         ecore_x_icccm_name_class_get(bd->client.win, &nname, &nclass);
9194         pname = bd->client.icccm.name;
9195         pclass = bd->client.icccm.class;
9196         bd->client.icccm.name = eina_stringshare_add(nname);
9197         bd->client.icccm.class = eina_stringshare_add(nclass);
9198         if (bd->client.icccm.class && (!strcmp(bd->client.icccm.class, "Vmplayer")))
9199           e_bindings_mapping_change_enable(EINA_FALSE);
9200 #ifdef _F_ZONE_WINDOW_ROTATION_
9201         if (e_config->wm_win_rotation)
9202           {
9203              if ((bd->client.icccm.name) && (bd->client.icccm.class))
9204                {
9205                   if ((!strcmp(bd->client.icccm.name, "Virtual Keyboard")) &&
9206                       (!strcmp(bd->client.icccm.class, "ISF")))
9207                     {
9208                        ELB(ELBT_BD, "SET VKBD", bd->client.win);
9209                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD;
9210                        rot.vkbd = bd;
9211                     }
9212                   else if ((!strcmp(bd->client.icccm.name, "Prediction Window")) &&
9213                            (!strcmp(bd->client.icccm.class, "ISF")))
9214                     {
9215                        ELB(ELBT_BD, "SET PREDICTION", bd->client.win);
9216                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_PREDICTION;
9217                        rot.vkbd_prediction = bd;
9218                     }
9219                   else if ((!strcmp(bd->client.icccm.name, "Key Magnifier")) &&
9220                            (!strcmp(bd->client.icccm.class, "ISF")))
9221                     {
9222                        ELB(ELBT_BD, "SET MAGNIFIER", bd->client.win);
9223                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER;
9224                     }
9225                   else if ((!strcmp(bd->client.icccm.name, "ISF Popup")) &&
9226                            (!strcmp(bd->client.icccm.class, "ISF")))
9227                     {
9228                        ELB(ELBT_BD, "SET VKBD_POPUP", bd->client.win);
9229                        bd->client.vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP;
9230                     }
9231                }
9232           }
9233 #endif
9234         if (nname) free(nname);
9235         if (nclass) free(nclass);
9236
9237         if (!((bd->client.icccm.name == pname) &&
9238               (bd->client.icccm.class == pclass)))
9239           bd->changes.icon = 1;
9240
9241         if (pname) eina_stringshare_del(pname);
9242         if (pclass) eina_stringshare_del(pclass);
9243         bd->client.icccm.fetch.name_class = 0;
9244         bd->changes.icon = 1;
9245         rem_change = 1;
9246      }
9247    if (bd->client.icccm.fetch.state)
9248      {
9249         bd->client.icccm.state = ecore_x_icccm_state_get(bd->client.win);
9250         bd->client.icccm.fetch.state = 0;
9251         rem_change = 1;
9252      }
9253    if (bd->client.e.fetch.state)
9254      {
9255         e_hints_window_e_state_get(bd);
9256         bd->client.e.fetch.state = 0;
9257         rem_change = 1;
9258      }
9259 #ifdef _F_USE_DESK_WINDOW_PROFILE_
9260    if (bd->client.e.fetch.profile_list)
9261      {
9262         const char **profiles = NULL;
9263         const char *str;
9264         int num = 0, i;
9265
9266         if (bd->client.e.state.profile)
9267           eina_stringshare_del(bd->client.e.state.profile);
9268         EINA_LIST_FREE(bd->client.e.state.profiles, str)
9269           {
9270              if (str) eina_stringshare_del(str);
9271           }
9272         bd->client.e.state.profile = NULL;
9273         bd->client.e.state.profiles = NULL;
9274         bd->client.e.state.profile_list = 0;
9275
9276         if (ecore_x_e_window_profile_list_get(bd->client.win,
9277                                               &profiles, &num))
9278           {
9279              bd->client.e.state.profile_list = 1;
9280              for (i = 0; i < num; i++)
9281                {
9282                   str = eina_stringshare_add(profiles[i]);
9283                   bd->client.e.state.profiles = eina_list_append(bd->client.e.state.profiles, str);
9284                }
9285
9286              /* We should set desk to contain given border after creating E_BORDER_ADD event.
9287               * If not, e will have an E_BORDER_SHOW event before E_BORDER_ADD event.
9288               */
9289              need_desk_set = EINA_TRUE;
9290           }
9291         else
9292           {
9293              if (strcmp(bd->desk->window_profile,
9294                         e_config->desktop_default_window_profile) != 0)
9295                {
9296                   ecore_x_e_window_profile_set(bd->client.win,
9297                                                bd->desk->window_profile);
9298                }
9299           }
9300
9301         if (profiles)
9302           {
9303              for (i = 0; i < num; i++)
9304                 if (profiles[i]) free(profiles[i]);
9305              free(profiles);
9306           }
9307
9308         bd->client.e.fetch.profile_list = 0;
9309      }
9310 #endif
9311 #ifdef _F_ZONE_WINDOW_ROTATION_
9312    if ((e_config->wm_win_rotation) &&
9313        (bd->client.e.fetch.rot.support))
9314      {
9315         int ret = 0;
9316         unsigned int support = 0;
9317
9318         ret = ecore_x_window_prop_card32_get
9319           (bd->client.win,
9320           ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
9321           &support, 1);
9322
9323         bd->client.e.state.rot.support = 0;
9324         if ((ret == 1) && (support == 1))
9325           bd->client.e.state.rot.support = 1;
9326
9327         if (bd->client.e.state.rot.support)
9328           need_rotation_set = EINA_TRUE;
9329
9330         bd->client.e.fetch.rot.support = 0;
9331      }
9332    if ((e_config->wm_win_rotation) &&
9333        (bd->client.e.fetch.rot.geom_hint))
9334      {
9335         Eina_Rectangle r[4];
9336         int i, x, y, w, h;
9337         bd->client.e.state.rot.geom_hint = 0;
9338         for (i = 0; i < 4; i++)
9339           {
9340              r[i].x = bd->client.e.state.rot.geom[i].x;
9341              r[i].y = bd->client.e.state.rot.geom[i].y;
9342              r[i].w = bd->client.e.state.rot.geom[i].w;
9343              r[i].h = bd->client.e.state.rot.geom[i].h;
9344
9345              bd->client.e.state.rot.geom[i].x = 0;
9346              bd->client.e.state.rot.geom[i].y = 0;
9347              bd->client.e.state.rot.geom[i].w = 0;
9348              bd->client.e.state.rot.geom[i].h = 0;
9349           }
9350
9351         for (i = 0; i < 4; i++)
9352           {
9353              x = 0; y = 0; w = 0; h = 0;
9354              if (ecore_x_e_window_rotation_geometry_get(bd->client.win, i*90, &x, &y, &w, &h))
9355                {
9356                   bd->client.e.state.rot.geom_hint = 1;
9357                   bd->client.e.state.rot.geom[i].x = x;
9358                   bd->client.e.state.rot.geom[i].y = y;
9359                   bd->client.e.state.rot.geom[i].w = w;
9360                   bd->client.e.state.rot.geom[i].h = h;
9361
9362                   if (!((r[i].x == x) && (r[i].y == y) &&
9363                         (r[i].w == w) && (r[i].h == h)))
9364                     {
9365                        need_rotation_set = EINA_TRUE;
9366                     }
9367                }
9368           }
9369         bd->client.e.fetch.rot.geom_hint = 0;
9370      }
9371    if ((e_config->wm_win_rotation) &&
9372        (bd->client.e.fetch.rot.app_set))
9373      {
9374         ELB(ELBT_ROT, "Fetch ROT_APP_SET", bd->client.win);
9375         unsigned char _prev_app_set = bd->client.e.state.rot.app_set;
9376         bd->client.e.state.rot.app_set = ecore_x_e_window_rotation_app_get(bd->client.win);
9377
9378         if (_prev_app_set != bd->client.e.state.rot.app_set)
9379           need_rotation_set = EINA_TRUE;
9380
9381         bd->client.e.fetch.rot.app_set = 0;
9382      }
9383    if ((e_config->wm_win_rotation) &&
9384        (bd->client.e.fetch.rot.preferred_rot))
9385      {
9386         int r = 0, _prev_preferred_rot;
9387         _prev_preferred_rot = bd->client.e.state.rot.preferred_rot;
9388         bd->client.e.state.rot.preferred_rot = -1;
9389         if (ecore_x_e_window_rotation_preferred_rotation_get(bd->client.win, &r))
9390           {
9391              bd->client.e.state.rot.preferred_rot = r;
9392              ELBF(ELBT_ROT, 0, bd->client.win, "Fetch PREFERRED_ROT:%d", r);
9393           }
9394         else
9395           {
9396              ELB(ELBT_ROT, "Fetch PREFERRED_ROT Del..", bd->client.win);
9397           }
9398
9399         if (_prev_preferred_rot != bd->client.e.state.rot.preferred_rot)
9400           need_rotation_set = EINA_TRUE;
9401
9402         bd->client.e.fetch.rot.preferred_rot = 0;
9403      }
9404    if ((e_config->wm_win_rotation) &&
9405        (bd->client.e.fetch.rot.available_rots))
9406      {
9407         Eina_Bool res, diff = EINA_FALSE;
9408         int *rots = NULL;
9409         unsigned int count = 0, i = 0;
9410         int _prev_rots[4] = { -1, };
9411
9412         if (bd->client.e.state.rot.available_rots)
9413           {
9414              memcpy(_prev_rots,
9415                     bd->client.e.state.rot.available_rots,
9416                     (sizeof(int) * bd->client.e.state.rot.count));
9417
9418              E_FREE(bd->client.e.state.rot.available_rots);
9419           }
9420
9421         bd->client.e.state.rot.count = 0;
9422
9423         res = ecore_x_e_window_rotation_available_rotations_get(bd->client.win,
9424                                                                 &rots, &count);
9425         if ((res) && (count > 0) && (rots))
9426           {
9427              bd->client.e.state.rot.available_rots = rots;
9428              bd->client.e.state.rot.count = count;
9429
9430              for (i = 0; i < count; i++)
9431                {
9432                   ELBF(ELBT_ROT, 0, bd->client.win, "Fetch AVAILABLE_ROTS[%d]:%d", i, rots[i]);
9433                   if ((!diff) && (_prev_rots[i] != rots[i]))
9434                     {
9435                        ELBF(ELBT_ROT, 0, bd->client.win, "count:%d i:%d _prev:%d != rot:%d",
9436                             count, i, _prev_rots[i], rots[i]);
9437                        diff = EINA_TRUE;
9438                     }
9439                }
9440           }
9441         else
9442           {
9443              ELB(ELBT_ROT, "Fetch AVAILABLE_ROTS Del..", bd->client.win);
9444              diff = EINA_TRUE;
9445           }
9446
9447         if (diff) need_rotation_set = EINA_TRUE;
9448         bd->client.e.fetch.rot.available_rots = 0;
9449      }
9450 #endif
9451    if (bd->client.netwm.fetch.type)
9452      {
9453         e_hints_window_type_get(bd);
9454         if ((!bd->lock_border) || (!bd->client.border.name))
9455           bd->client.border.changed = 1;
9456
9457         if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
9458           {
9459              if (!bd->client.netwm.state.skip_pager)
9460                {
9461                   bd->client.netwm.state.skip_pager = 1;
9462                   bd->client.netwm.update.state = 1;
9463                }
9464              if (!bd->client.netwm.state.skip_taskbar)
9465                {
9466                   bd->client.netwm.state.skip_taskbar = 1;
9467                   bd->client.netwm.update.state = 1;
9468                }
9469           }
9470         bd->client.netwm.fetch.type = 0;
9471      }
9472    if (bd->client.icccm.fetch.machine)
9473      {
9474         char *machine = ecore_x_icccm_client_machine_get(bd->client.win);
9475
9476         if ((!machine) && (bd->client.icccm.client_leader))
9477           machine = ecore_x_icccm_client_machine_get(bd->client.icccm.client_leader);
9478
9479         eina_stringshare_replace(&bd->client.icccm.machine, machine);
9480         if (machine) free(machine);
9481
9482         bd->client.icccm.fetch.machine = 0;
9483         rem_change = 1;
9484      }
9485    if (bd->client.icccm.fetch.command)
9486      {
9487         if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
9488           {
9489              int i;
9490
9491              for (i = 0; i < bd->client.icccm.command.argc; i++)
9492                free(bd->client.icccm.command.argv[i]);
9493              free(bd->client.icccm.command.argv);
9494           }
9495         bd->client.icccm.command.argc = 0;
9496         bd->client.icccm.command.argv = NULL;
9497         ecore_x_icccm_command_get(bd->client.win,
9498                                   &(bd->client.icccm.command.argc),
9499                                   &(bd->client.icccm.command.argv));
9500         if ((bd->client.icccm.client_leader) &&
9501             (!bd->client.icccm.command.argv))
9502           ecore_x_icccm_command_get(bd->client.icccm.client_leader,
9503                                     &(bd->client.icccm.command.argc),
9504                                     &(bd->client.icccm.command.argv));
9505         bd->client.icccm.fetch.command = 0;
9506         rem_change = 1;
9507      }
9508    if (bd->client.icccm.fetch.hints)
9509      {
9510         Eina_Bool accepts_focus, is_urgent;
9511
9512         accepts_focus = EINA_TRUE;
9513         is_urgent = EINA_FALSE;
9514         bd->client.icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
9515         if (ecore_x_icccm_hints_get(bd->client.win,
9516                                     &accepts_focus,
9517                                     &bd->client.icccm.initial_state,
9518                                     &bd->client.icccm.icon_pixmap,
9519                                     &bd->client.icccm.icon_mask,
9520                                     &bd->client.icccm.icon_window,
9521                                     &bd->client.icccm.window_group,
9522                                     &is_urgent))
9523           {
9524              bd->client.icccm.accepts_focus = accepts_focus;
9525              if ((bd->client.icccm.urgent != is_urgent) && ((!bd->focused) || (!is_urgent)))
9526                change_urgent = 1;
9527              bd->client.icccm.urgent = is_urgent;
9528
9529              /* If this is a new window, set the state as requested. */
9530              if ((bd->new_client) &&
9531                  (bd->client.icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
9532                {
9533                   e_border_iconify(bd);
9534                   e_border_hide(bd, 1);
9535                }
9536           }
9537         bd->client.icccm.fetch.hints = 0;
9538         rem_change = 1;
9539      }
9540    if (bd->client.icccm.fetch.size_pos_hints)
9541      {
9542         Eina_Bool request_pos;
9543
9544         request_pos = EINA_FALSE;
9545         if (ecore_x_icccm_size_pos_hints_get(bd->client.win,
9546                                              &request_pos,
9547                                              &bd->client.icccm.gravity,
9548                                              &bd->client.icccm.min_w,
9549                                              &bd->client.icccm.min_h,
9550                                              &bd->client.icccm.max_w,
9551                                              &bd->client.icccm.max_h,
9552                                              &bd->client.icccm.base_w,
9553                                              &bd->client.icccm.base_h,
9554                                              &bd->client.icccm.step_w,
9555                                              &bd->client.icccm.step_h,
9556                                              &bd->client.icccm.min_aspect,
9557                                              &bd->client.icccm.max_aspect))
9558           {
9559              bd->client.icccm.request_pos = request_pos;
9560           }
9561         else
9562           {
9563           }
9564         if (bd->client.icccm.min_w > 32767) bd->client.icccm.min_w = 32767;
9565         if (bd->client.icccm.min_h > 32767) bd->client.icccm.min_h = 32767;
9566         if (bd->client.icccm.max_w > 32767) bd->client.icccm.max_w = 32767;
9567         if (bd->client.icccm.max_h > 32767) bd->client.icccm.max_h = 32767;
9568         if (bd->client.icccm.base_w > 32767) bd->client.icccm.base_w = 32767;
9569         if (bd->client.icccm.base_h > 32767) bd->client.icccm.base_h = 32767;
9570         //      if (bd->client.icccm.step_w < 1) bd->client.icccm.step_w = 1;
9571         //      if (bd->client.icccm.step_h < 1) bd->client.icccm.step_h = 1;
9572         // if doing a resize, fix it up
9573         if (bd->resize_mode != RESIZE_NONE)
9574           {
9575              int x, y, w, h, new_w, new_h;
9576
9577              x = bd->x;
9578              y = bd->y;
9579              w = bd->w;
9580              h = bd->h;
9581              new_w = w;
9582              new_h = h;
9583              e_border_resize_limit(bd, &new_w, &new_h);
9584              if ((bd->resize_mode == RESIZE_TL) ||
9585                  (bd->resize_mode == RESIZE_L) ||
9586                  (bd->resize_mode == RESIZE_BL))
9587                x += (w - new_w);
9588              if ((bd->resize_mode == RESIZE_TL) ||
9589                  (bd->resize_mode == RESIZE_T) ||
9590                  (bd->resize_mode == RESIZE_TR))
9591                y += (h - new_h);
9592              e_border_move_resize(bd, x, y, new_w, new_h);
9593           }
9594         bd->client.icccm.fetch.size_pos_hints = 0;
9595         rem_change = 1;
9596      }
9597    if (bd->client.icccm.fetch.protocol)
9598      {
9599         int i, num;
9600         Ecore_X_WM_Protocol *proto;
9601
9602         proto = ecore_x_window_prop_protocol_list_get(bd->client.win, &num);
9603         if (proto)
9604           {
9605              for (i = 0; i < num; i++)
9606                {
9607                   if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
9608                     bd->client.icccm.delete_request = 1;
9609                   else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
9610                     bd->client.icccm.take_focus = 1;
9611                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
9612                     bd->client.netwm.ping = 1;
9613                   else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
9614                     {
9615                        bd->client.netwm.sync.request = 1;
9616                        if (!ecore_x_netwm_sync_counter_get(bd->client.win,
9617                                                            &bd->client.netwm.sync.counter))
9618                          bd->client.netwm.sync.request = 0;
9619                     }
9620                }
9621              free(proto);
9622           }
9623         if (bd->client.netwm.ping)
9624           e_border_ping(bd);
9625         else
9626           {
9627              if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
9628              bd->ping_poller = NULL;
9629           }
9630         bd->client.icccm.fetch.protocol = 0;
9631      }
9632    if (bd->client.icccm.fetch.transient_for)
9633      {
9634         /* TODO: What do to if the transient for isn't mapped yet? */
9635         E_Border *bd_parent = NULL;
9636 #ifdef _F_DEICONIFY_APPROVE_
9637         Eina_Bool change_parent = EINA_FALSE;
9638 #endif
9639
9640         bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win);
9641         if (bd->client.icccm.transient_for)
9642           bd_parent = e_border_find_by_client_window(bd->client.icccm.transient_for);
9643         /* If we already have a parent, remove it */
9644         if (bd->parent)
9645           {
9646              if (bd_parent != bd->parent)
9647                {
9648                   bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
9649                   if (bd->parent->modal == bd) bd->parent->modal = NULL;
9650                   bd->parent = NULL;
9651                }
9652              else
9653                bd_parent = NULL;
9654           }
9655         if ((bd_parent) && (bd_parent != bd) &&
9656             (eina_list_data_find(bd->transients, bd_parent) != bd_parent))
9657           {
9658              bd_parent->transients = eina_list_append(bd_parent->transients, bd);
9659              bd->parent = bd_parent;
9660 #ifdef _F_DEICONIFY_APPROVE_
9661              change_parent = EINA_TRUE;
9662 #endif
9663           }
9664         if (bd->parent)
9665           {
9666              e_border_layer_set(bd, bd->parent->layer);
9667              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
9668                {
9669                   Ecore_X_Window_Attributes attr;
9670                   bd->parent->modal = bd;
9671                   ecore_x_window_attributes_get(bd->parent->client.win, &attr);
9672                   bd->parent->saved.event_mask = attr.event_mask.mine;
9673                   bd->parent->lock_close = 1;
9674                   ecore_x_event_mask_unset(bd->parent->client.win, attr.event_mask.mine);
9675                   ecore_x_event_mask_set(bd->parent->client.win, ECORE_X_EVENT_MASK_WINDOW_DAMAGE | ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
9676                }
9677
9678              if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
9679                  (bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
9680                bd->take_focus = 1;
9681           }
9682
9683 #ifdef _F_DEICONIFY_APPROVE_
9684         if (change_parent)
9685           {
9686              bd->client.e.state.deiconify_approve.render_done = 0;
9687
9688              E_Border *ancestor_bd;
9689              ancestor_bd = bd->client.e.state.deiconify_approve.ancestor;
9690              if ((ancestor_bd) &&
9691                  (!e_object_is_del(E_OBJECT(ancestor_bd))))
9692                {
9693                   ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd);
9694                   bd->client.e.state.deiconify_approve.ancestor = NULL;
9695
9696                   if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) &&
9697                       (ancestor_bd->client.e.state.deiconify_approve.render_done))
9698                     {
9699                        if (ancestor_bd->client.e.state.deiconify_approve.wait_timer)
9700                          {
9701                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
9702                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
9703                             e_border_uniconify(ancestor_bd);
9704                          }
9705                     }
9706                }
9707           }
9708 #endif
9709         bd->client.icccm.fetch.transient_for = 0;
9710         rem_change = 1;
9711      }
9712    if (bd->client.icccm.fetch.window_role)
9713      {
9714         char *role = ecore_x_icccm_window_role_get(bd->client.win);
9715         eina_stringshare_replace(&bd->client.icccm.window_role, role);
9716         if (role) free(role);
9717
9718         bd->client.icccm.fetch.window_role = 0;
9719         rem_change = 1;
9720      }
9721    if (bd->client.icccm.fetch.icon_name)
9722      {
9723         char *icon_name = ecore_x_icccm_icon_name_get(bd->client.win);
9724         eina_stringshare_replace(&bd->client.icccm.icon_name, icon_name);
9725         if (icon_name) free(icon_name);
9726
9727         bd->client.icccm.fetch.icon_name = 0;
9728         rem_change = 1;
9729      }
9730    if (bd->client.netwm.fetch.icon_name)
9731      {
9732         char *icon_name;
9733         ecore_x_netwm_icon_name_get(bd->client.win, &icon_name);
9734         eina_stringshare_replace(&bd->client.netwm.icon_name, icon_name);
9735         if (icon_name) free(icon_name);
9736
9737         bd->client.netwm.fetch.icon_name = 0;
9738         rem_change = 1;
9739      }
9740    if (bd->client.netwm.fetch.icon)
9741      {
9742         int i;
9743         if (bd->client.netwm.icons)
9744           {
9745              for (i = 0; i < bd->client.netwm.num_icons; i++)
9746                {
9747                   free(bd->client.netwm.icons[i].data);
9748                   bd->client.netwm.icons[i].data = NULL;
9749                }
9750              free(bd->client.netwm.icons);
9751           }
9752         bd->client.netwm.icons = NULL;
9753         bd->client.netwm.num_icons = 0;
9754         if (ecore_x_netwm_icons_get(bd->client.win,
9755                                      &bd->client.netwm.icons,
9756                                      &bd->client.netwm.num_icons))
9757           {
9758              // unless the rest of e17 uses border icons OTHER than icon #0
9759              // then free the rest that we don't need anymore.
9760              for (i = 1; i < bd->client.netwm.num_icons; i++)
9761                {
9762                   free(bd->client.netwm.icons[i].data);
9763                   bd->client.netwm.icons[i].data = NULL;
9764                }
9765              bd->client.netwm.num_icons = 1;
9766              bd->changes.icon = 1;
9767           }
9768         bd->client.netwm.fetch.icon = 0;
9769      }
9770    if (bd->client.netwm.fetch.user_time)
9771      {
9772         ecore_x_netwm_user_time_get(bd->client.win, &bd->client.netwm.user_time);
9773         bd->client.netwm.fetch.user_time = 0;
9774      }
9775    if (bd->client.netwm.fetch.strut)
9776      {
9777         if (!ecore_x_netwm_strut_partial_get(bd->client.win,
9778                                              &bd->client.netwm.strut.left,
9779                                              &bd->client.netwm.strut.right,
9780                                              &bd->client.netwm.strut.top,
9781                                              &bd->client.netwm.strut.bottom,
9782                                              &bd->client.netwm.strut.left_start_y,
9783                                              &bd->client.netwm.strut.left_end_y,
9784                                              &bd->client.netwm.strut.right_start_y,
9785                                              &bd->client.netwm.strut.right_end_y,
9786                                              &bd->client.netwm.strut.top_start_x,
9787                                              &bd->client.netwm.strut.top_end_x,
9788                                              &bd->client.netwm.strut.bottom_start_x,
9789                                              &bd->client.netwm.strut.bottom_end_x))
9790           {
9791              ecore_x_netwm_strut_get(bd->client.win,
9792                                      &bd->client.netwm.strut.left, &bd->client.netwm.strut.right,
9793                                      &bd->client.netwm.strut.top, &bd->client.netwm.strut.bottom);
9794
9795              bd->client.netwm.strut.left_start_y = 0;
9796              bd->client.netwm.strut.left_end_y = 0;
9797              bd->client.netwm.strut.right_start_y = 0;
9798              bd->client.netwm.strut.right_end_y = 0;
9799              bd->client.netwm.strut.top_start_x = 0;
9800              bd->client.netwm.strut.top_end_x = 0;
9801              bd->client.netwm.strut.bottom_start_x = 0;
9802              bd->client.netwm.strut.bottom_end_x = 0;
9803           }
9804         bd->client.netwm.fetch.strut = 0;
9805      }
9806    if (bd->client.qtopia.fetch.soft_menu)
9807      {
9808         e_hints_window_qtopia_soft_menu_get(bd);
9809         bd->client.qtopia.fetch.soft_menu = 0;
9810         rem_change = 1;
9811      }
9812    if (bd->client.qtopia.fetch.soft_menus)
9813      {
9814         e_hints_window_qtopia_soft_menus_get(bd);
9815         bd->client.qtopia.fetch.soft_menus = 0;
9816         rem_change = 1;
9817      }
9818    if (bd->client.vkbd.fetch.state)
9819      {
9820         e_hints_window_virtual_keyboard_state_get(bd);
9821         bd->client.vkbd.fetch.state = 0;
9822         rem_change = 1;
9823      }
9824    if (bd->client.vkbd.fetch.vkbd)
9825      {
9826         e_hints_window_virtual_keyboard_get(bd);
9827         bd->client.vkbd.fetch.vkbd = 0;
9828         rem_change = 1;
9829      }
9830    if (bd->client.illume.conformant.fetch.conformant)
9831      {
9832         bd->client.illume.conformant.conformant =
9833           ecore_x_e_illume_conformant_get(bd->client.win);
9834         bd->client.illume.conformant.fetch.conformant = 0;
9835      }
9836    if (bd->client.illume.quickpanel.fetch.state)
9837      {
9838         bd->client.illume.quickpanel.state =
9839           ecore_x_e_illume_quickpanel_state_get(bd->client.win);
9840         bd->client.illume.quickpanel.fetch.state = 0;
9841      }
9842    if (bd->client.illume.quickpanel.fetch.quickpanel)
9843      {
9844         bd->client.illume.quickpanel.quickpanel =
9845           ecore_x_e_illume_quickpanel_get(bd->client.win);
9846         bd->client.illume.quickpanel.fetch.quickpanel = 0;
9847      }
9848    if (bd->client.illume.quickpanel.fetch.priority.major)
9849      {
9850         bd->client.illume.quickpanel.priority.major =
9851           ecore_x_e_illume_quickpanel_priority_major_get(bd->client.win);
9852         bd->client.illume.quickpanel.fetch.priority.major = 0;
9853      }
9854    if (bd->client.illume.quickpanel.fetch.priority.minor)
9855      {
9856         bd->client.illume.quickpanel.priority.minor =
9857           ecore_x_e_illume_quickpanel_priority_minor_get(bd->client.win);
9858         bd->client.illume.quickpanel.fetch.priority.minor = 0;
9859      }
9860    if (bd->client.illume.quickpanel.fetch.zone)
9861      {
9862         bd->client.illume.quickpanel.zone =
9863           ecore_x_e_illume_quickpanel_zone_get(bd->client.win);
9864         bd->client.illume.quickpanel.fetch.zone = 0;
9865      }
9866    if (bd->client.illume.drag.fetch.drag)
9867      {
9868         bd->client.illume.drag.drag =
9869           ecore_x_e_illume_drag_get(bd->client.win);
9870         bd->client.illume.drag.fetch.drag = 0;
9871      }
9872    if (bd->client.illume.drag.fetch.locked)
9873      {
9874         bd->client.illume.drag.locked =
9875           ecore_x_e_illume_drag_locked_get(bd->client.win);
9876         bd->client.illume.drag.fetch.locked = 0;
9877      }
9878    if (bd->client.illume.win_state.fetch.state)
9879      {
9880         bd->client.illume.win_state.state =
9881            ecore_x_e_illume_window_state_get(bd->client.win);
9882         bd->client.illume.win_state.fetch.state = 0;
9883      }
9884    if (bd->changes.shape)
9885      {
9886         Ecore_X_Rectangle *rects;
9887         int num;
9888
9889         bd->changes.shape = 0;
9890         rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
9891         if (rects)
9892           {
9893              int cw = 0, ch = 0;
9894
9895              /* This doesn't fix the race, but makes it smaller. we detect
9896               * this and if cw and ch != client w/h then mark this as needing
9897               * a shape change again to fixup next event loop.
9898               */
9899              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9900              if ((cw != bd->client.w) || (ch != bd->client.h))
9901                bd->changes.shape = 1;
9902              if ((num == 1) &&
9903                  (rects[0].x == 0) &&
9904                  (rects[0].y == 0) &&
9905                  ((int)rects[0].width == cw) &&
9906                  ((int)rects[0].height == ch))
9907                {
9908                   if (bd->client.shaped)
9909                     {
9910                        bd->client.shaped = 0;
9911                        if (!bd->bordername)
9912                          bd->client.border.changed = 1;
9913                     }
9914                }
9915              else
9916                {
9917                   if (!bd->client.shaped)
9918                     {
9919                        bd->client.shaped = 1;
9920                        if (!bd->bordername)
9921                          bd->client.border.changed = 1;
9922                     }
9923                }
9924              free(rects);
9925           }
9926         else
9927           {
9928              // FIXME: no rects i think can mean... totally empty window
9929              bd->client.shaped = 0;
9930              if (!bd->bordername)
9931                bd->client.border.changed = 1;
9932           }
9933         bd->need_shape_merge = 1;
9934      }
9935    if (bd->changes.shape_input)
9936      {
9937         Ecore_X_Rectangle *rects;
9938         int num;
9939
9940         bd->changes.shape_input = 0;
9941         rects = ecore_x_window_shape_input_rectangles_get(bd->client.win, &num);
9942         if (rects)
9943           {
9944              int cw = 0, ch = 0;
9945
9946              /* This doesn't fix the race, but makes it smaller. we detect
9947               * this and if cw and ch != client w/h then mark this as needing
9948               * a shape change again to fixup next event loop.
9949               */
9950              ecore_x_window_size_get(bd->client.win, &cw, &ch);
9951              if ((cw != bd->client.w) || (ch != bd->client.h))
9952                bd->changes.shape_input = 1;
9953              if ((num == 1) &&
9954                  (rects[0].x == 0) &&
9955                  (rects[0].y == 0) &&
9956                  ((int)rects[0].width == cw) &&
9957                  ((int)rects[0].height == ch))
9958                {
9959                   if (bd->shaped_input)
9960                     {
9961                        bd->shaped_input = 0;
9962                        if (!bd->bordername)
9963                          bd->client.border.changed = 1;
9964                     }
9965                }
9966              else
9967                {
9968                   if (!bd->shaped_input)
9969                     {
9970                        bd->shaped_input = 1;
9971                        if (!bd->bordername)
9972                          bd->client.border.changed = 1;
9973                     }
9974                }
9975              free(rects);
9976           }
9977         else
9978           {
9979              bd->shaped_input = 1;
9980              if (!bd->bordername)
9981                bd->client.border.changed = 1;
9982           }
9983         bd->need_shape_merge = 1;
9984      }
9985    if (bd->client.mwm.fetch.hints)
9986      {
9987         int pb;
9988
9989         bd->client.mwm.exists =
9990           ecore_x_mwm_hints_get(bd->client.win,
9991                                 &bd->client.mwm.func,
9992                                 &bd->client.mwm.decor,
9993                                 &bd->client.mwm.input);
9994         pb = bd->client.mwm.borderless;
9995         bd->client.mwm.borderless = 0;
9996         if (bd->client.mwm.exists)
9997           {
9998              if ((!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
9999                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
10000                  (!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
10001                bd->client.mwm.borderless = 1;
10002           }
10003         if (bd->client.mwm.borderless != pb)
10004           {
10005              if ((!bd->lock_border) || (!bd->client.border.name))
10006                bd->client.border.changed = 1;
10007           }
10008         bd->client.mwm.fetch.hints = 0;
10009         rem_change = 1;
10010      }
10011    if (bd->client.e.fetch.video_parent)
10012      {
10013         /* unlinking child/parent */
10014         if (bd->client.e.state.video_parent_border != NULL)
10015           {
10016              bd->client.e.state.video_parent_border->client.e.state.video_child =
10017                eina_list_remove
10018                (bd->client.e.state.video_parent_border->client.e.state.video_child,
10019                    bd);
10020           }
10021
10022         ecore_x_window_prop_card32_get(bd->client.win,
10023                                        ECORE_X_ATOM_E_VIDEO_PARENT,
10024                                        &bd->client.e.state.video_parent,
10025                                        1);
10026
10027         /* linking child/parent */
10028         if (bd->client.e.state.video_parent != 0)
10029           {
10030              E_Border *tmp;
10031              Eina_List *l;
10032
10033              EINA_LIST_FOREACH(borders, l, tmp)
10034                if (tmp->client.win == bd->client.e.state.video_parent)
10035                  {
10036                     /* fprintf(stderr, "child added to parent \\o/\n"); */
10037                     bd->client.e.state.video_parent_border = tmp;
10038                     tmp->client.e.state.video_child = eina_list_append(tmp->client.e.state.video_child,
10039                                                                        bd);
10040                     if (bd->desk != tmp->desk)
10041                       e_border_desk_set(bd, tmp->desk);
10042                     break;
10043                  }
10044           }
10045
10046         /* fprintf(stderr, "new parent %x => %p\n", bd->client.e.state.video_parent, bd->client.e.state.video_parent_border); */
10047
10048         if (bd->client.e.state.video_parent_border) bd->client.e.fetch.video_parent = 0;
10049         rem_change = 1;
10050      }
10051    if (bd->client.e.fetch.video_position && bd->client.e.fetch.video_parent == 0)
10052      {
10053         unsigned int xy[2];
10054
10055         ecore_x_window_prop_card32_get(bd->client.win,
10056                                        ECORE_X_ATOM_E_VIDEO_POSITION,
10057                                        xy,
10058                                        2);
10059         bd->client.e.state.video_position.x = xy[0];
10060         bd->client.e.state.video_position.y = xy[1];
10061         bd->client.e.state.video_position.updated = 1;
10062         bd->client.e.fetch.video_position = 0;
10063         bd->x = bd->client.e.state.video_position.x;
10064         bd->y = bd->client.e.state.video_position.y;
10065
10066         fprintf(stderr, "internal position has been updated [%i, %i]\n", bd->client.e.state.video_position.x, bd->client.e.state.video_position.y);
10067      }
10068    if (bd->client.netwm.update.state)
10069      {
10070         e_hints_window_state_set(bd);
10071         /* Some stats might change the border, like modal */
10072         if (((!bd->lock_border) || (!bd->client.border.name)) &&
10073             (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10074           {
10075              bd->client.border.changed = 1;
10076           }
10077         if (bd->parent)
10078           {
10079              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
10080                {
10081                   bd->parent->modal = bd;
10082                   if (bd->parent->focused)
10083                     e_border_focus_set(bd, 1, 1);
10084                }
10085           }
10086         else if (bd->leader)
10087           {
10088              if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
10089                {
10090                   bd->leader->modal = bd;
10091                   if (bd->leader->focused)
10092                     e_border_focus_set(bd, 1, 1);
10093                   else
10094                     {
10095                        Eina_List *l;
10096                        E_Border *child;
10097
10098                        EINA_LIST_FOREACH(bd->leader->group, l, child)
10099                          {
10100                             if ((child != bd) && (child->focused))
10101                               e_border_focus_set(bd, 1, 1);
10102                          }
10103                     }
10104                }
10105           }
10106         bd->client.netwm.update.state = 0;
10107      }
10108
10109    if (bd->new_client)
10110      {
10111         E_Event_Border_Add *ev;
10112         E_Exec_Instance *inst;
10113
10114         ev = E_NEW(E_Event_Border_Add, 1);
10115         ev->border = bd;
10116         e_object_ref(E_OBJECT(bd));
10117         //      e_object_breadcrumb_add(E_OBJECT(bd), "border_add_event");
10118         ecore_event_add(E_EVENT_BORDER_ADD, ev, _e_border_event_border_add_free, NULL);
10119
10120         if ((!bd->lock_border) || (!bd->client.border.name))
10121           bd->client.border.changed = 1;
10122
10123           {
10124              char *str = NULL;
10125
10126              if ((ecore_x_netwm_startup_id_get(bd->client.win, &str) && (str)) ||
10127                  ((bd->client.icccm.client_leader > 0) &&
10128                      ecore_x_netwm_startup_id_get(bd->client.icccm.client_leader, &str) && (str))
10129                 )
10130                {
10131                   if (!strncmp(str, "E_START|", 8))
10132                     {
10133                        int id;
10134
10135                        id = atoi(str + 8);
10136                        if (id > 0) bd->client.netwm.startup_id = id;
10137                     }
10138                   free(str);
10139                }
10140           }
10141         /* It's ok not to have fetch flag, should only be set on startup
10142          *     * and not changed. */
10143         if (!ecore_x_netwm_pid_get(bd->client.win, &bd->client.netwm.pid))
10144           {
10145              if (bd->client.icccm.client_leader)
10146                {
10147                   if (!ecore_x_netwm_pid_get(bd->client.icccm.client_leader, &bd->client.netwm.pid))
10148                     bd->client.netwm.pid = -1;
10149                }
10150              else
10151                bd->client.netwm.pid = -1;
10152           }
10153
10154         if (!bd->re_manage)
10155           {
10156              inst = e_exec_startup_id_pid_instance_find(bd->client.netwm.startup_id,
10157                                                         bd->client.netwm.pid);
10158              if ((inst) && (inst->used == 0))
10159                {
10160                   E_Zone *zone;
10161                   E_Desk *desk;
10162
10163                   inst->used++;
10164                   zone = e_container_zone_number_get(bd->zone->container,
10165                                                      inst->screen);
10166                   if (zone) e_border_zone_set(bd, zone);
10167                   desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
10168                                           inst->desk_y);
10169                   if (desk) e_border_desk_set(bd, desk);
10170                   e_exec_instance_found(inst);
10171                }
10172
10173              if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
10174                {
10175                   E_Border *bdl = NULL;
10176
10177                   bdl = bd->parent;
10178                   if (!bdl)
10179                     {
10180                        if (bd->leader) bdl = bd->leader;
10181                     }
10182                   if (!bdl)
10183                     {
10184                        E_Border *child;
10185                        E_Border_List *bl;
10186
10187                        bl = e_container_border_list_first(bd->zone->container);
10188                        while ((child = e_container_border_list_next(bl)))
10189                          {
10190                             if (child == bd) continue;
10191                             if (e_object_is_del(E_OBJECT(child))) continue;
10192                             if ((bd->client.icccm.client_leader) &&
10193                                 (child->client.icccm.client_leader ==
10194                                     bd->client.icccm.client_leader))
10195                               {
10196                                  bdl = child;
10197                                  break;
10198                               }
10199                          }
10200                        e_container_border_list_free(bl);
10201                     }
10202                   if (bdl)
10203                     {
10204                        if (bdl->zone)
10205                          e_border_zone_set(bd, bdl->zone);
10206                        if (bdl->desk)
10207                          e_border_desk_set(bd, bdl->desk);
10208                        else
10209                          e_border_stick(bd);
10210                     }
10211                }
10212           }
10213      }
10214
10215 #ifdef _F_USE_DESK_WINDOW_PROFILE_
10216    if (need_desk_set)
10217      {
10218         E_Container *con = bd->zone->container;
10219         E_Desk *desk = NULL;
10220         Eina_List *l;
10221         const char *str;
10222         EINA_LIST_FOREACH(bd->client.e.state.profiles, l, str)
10223           {
10224              desk = e_container_desk_window_profile_get(con, str);
10225              if (desk)
10226                {
10227                   if (bd->desk != desk)
10228                     {
10229                        bd->client.e.state.profile = eina_stringshare_add(str);
10230                        if (bd->zone != desk->zone)
10231                          e_border_zone_set(bd, desk->zone);
10232                        e_border_desk_set(bd, desk);
10233                     }
10234                   break;
10235                }
10236           }
10237      }
10238 #endif
10239
10240    /* PRE_POST_FETCH calls e_remember apply for new client */
10241    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd);
10242    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd);
10243    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd);
10244
10245 #ifdef _F_ZONE_WINDOW_ROTATION_
10246    if (e_config->wm_win_rotation)
10247      {
10248         if (need_rotation_set)
10249           {
10250              Eina_Bool hint = EINA_FALSE;
10251              int ang = 0;
10252              int x, y, w, h, move;
10253
10254              ELB(ELBT_ROT, "NEED ROT", bd->client.win);
10255              bd->client.e.state.rot.changes = _e_border_rotation_angle_get(bd);
10256
10257              if (bd->client.e.state.rot.changes != -1)
10258                {
10259                   ang = bd->client.e.state.rot.changes;
10260                   bd->changed = 1;
10261                }
10262              else ang = bd->client.e.state.rot.curr;
10263
10264              hint = _e_border_rotation_geom_get(bd, bd->zone, ang, &x, &y, &w, &h, &move);
10265              if (hint)
10266                {
10267                   _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);
10268                   ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d",
10269                        bd->client.icccm.name, x, y, w, h);
10270                }
10271           }
10272      }
10273 #endif
10274
10275    if (bd->need_reparent)
10276      {
10277         if (!bd->internal)
10278           ecore_x_window_save_set_add(bd->client.win);
10279         ecore_x_window_reparent(bd->client.win, bd->client.shell_win, 0, 0);
10280         if (bd->visible)
10281           {
10282              if ((bd->new_client) && (bd->internal) &&
10283                  (bd->internal_ecore_evas))
10284                ecore_evas_show(bd->internal_ecore_evas);
10285              ecore_x_window_show(bd->client.win);
10286           }
10287         bd->need_reparent = 0;
10288      }
10289
10290    if ((bd->client.border.changed) && (!bd->shaded) &&
10291        (!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
10292      {
10293         const char *bordername;
10294
10295         if (bd->fullscreen)
10296           bordername = "borderless";
10297         else if (bd->bordername)
10298           bordername = bd->bordername;
10299         else if ((bd->client.mwm.borderless) || (bd->borderless))
10300           bordername = "borderless";
10301         else if (((bd->client.icccm.transient_for != 0) ||
10302                   (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)) &&
10303                  (bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10304                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10305           bordername = "noresize_dialog";
10306         else if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
10307                  (bd->client.icccm.min_h == bd->client.icccm.max_h))
10308           bordername = "noresize";
10309         else if (bd->client.shaped)
10310           bordername = "shaped";
10311         else if ((!bd->client.icccm.accepts_focus) &&
10312                  (!bd->client.icccm.take_focus))
10313           bordername = "nofocus";
10314         else if (bd->client.icccm.urgent)
10315           bordername = "urgent";
10316         else if ((bd->client.icccm.transient_for != 0) ||
10317                  (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10318           bordername = "dialog";
10319         else if (bd->client.netwm.state.modal)
10320           bordername = "modal";
10321         else if ((bd->client.netwm.state.skip_taskbar) ||
10322                  (bd->client.netwm.state.skip_pager))
10323           bordername = "skipped";
10324         else if ((bd->internal) && (bd->client.icccm.class) &&
10325                  (!strncmp(bd->client.icccm.class, "e_fwin", 6)))
10326           bordername = "internal_fileman";
10327         else
10328           bordername = e_config->theme_default_border_style;
10329         if (!bordername) bordername = "default";
10330
10331         if ((!bd->client.border.name) || (strcmp(bd->client.border.name, bordername)))
10332           {
10333              Evas_Object *o;
10334              char buf[4096];
10335              int ok;
10336
10337              bd->changes.border = 1;
10338              eina_stringshare_replace(&bd->client.border.name, bordername);
10339
10340              if (bd->bg_object)
10341                {
10342                   bd->w -= (bd->client_inset.l + bd->client_inset.r);
10343                   bd->h -= (bd->client_inset.t + bd->client_inset.b);
10344                   bd->changes.size = 1;
10345                   evas_object_del(bd->bg_object);
10346                }
10347              o = edje_object_add(bd->bg_evas);
10348              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
10349              ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10350              if ((!ok) && (strcmp(bd->client.border.name, "borderless")))
10351                {
10352                   if (bd->client.border.name != e_config->theme_default_border_style)
10353                     {
10354                        snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
10355                        ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
10356                     }
10357                   if (!ok)
10358                     {
10359                        ok = e_theme_edje_object_set(o, "base/theme/borders",
10360                                                     "e/widgets/border/default/border");
10361                        if (ok)
10362                          {
10363                             /* Reset default border style to default */
10364                             eina_stringshare_replace(&e_config->theme_default_border_style, "default");
10365                             e_config_save_queue();
10366                          }
10367                     }
10368                }
10369
10370              bd->shaped = 0;
10371              if (ok)
10372                {
10373                   const char *shape_option, *argb_option;
10374                   int use_argb = 0;
10375
10376                   bd->bg_object = o;
10377
10378                   if ((e_config->use_composite) && (!bd->client.argb))
10379                     {
10380                        argb_option = edje_object_data_get(o, "argb");
10381                        if ((argb_option) && (!strcmp(argb_option, "1")))
10382                          use_argb = 1;
10383
10384                        if (use_argb != bd->argb)
10385                          _e_border_frame_replace(bd, use_argb);
10386
10387                        o = bd->bg_object;
10388                     }
10389
10390                   if (!bd->argb)
10391                     {
10392                        shape_option = edje_object_data_get(o, "shaped");
10393                        if ((shape_option) && (!strcmp(shape_option, "1")))
10394                          bd->shaped = 1;
10395                     }
10396
10397                   if (bd->client.netwm.name)
10398                     edje_object_part_text_set(o, "e.text.title",
10399                                               bd->client.netwm.name);
10400                   else if (bd->client.icccm.title)
10401                     edje_object_part_text_set(o, "e.text.title",
10402                                               bd->client.icccm.title);
10403                }
10404              else
10405                {
10406                   evas_object_del(o);
10407                   bd->bg_object = NULL;
10408                }
10409
10410              _e_border_client_inset_calc(bd);
10411
10412              bd->w += (bd->client_inset.l + bd->client_inset.r);
10413              bd->h += (bd->client_inset.t + bd->client_inset.b);
10414              ecore_evas_shaped_set(bd->bg_ecore_evas, bd->shaped);
10415              bd->changes.size = 1;
10416              /*  really needed ? */
10417              ecore_x_window_move(bd->client.shell_win,
10418                                  bd->client_inset.l,
10419                                  bd->client_inset.t);
10420
10421              if (bd->maximized != E_MAXIMIZE_NONE)
10422                {
10423                   E_Maximize maximized = bd->maximized;
10424
10425                   /* to force possible resizes */
10426                   bd->maximized = E_MAXIMIZE_NONE;
10427
10428                   _e_border_maximize(bd, maximized);
10429
10430                   /* restore maximized state */
10431                   bd->maximized = maximized;
10432
10433                   e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
10434                                                bd->maximized & E_MAXIMIZE_VERTICAL);
10435                }
10436              if (bd->bg_object)
10437                {
10438                   edje_object_signal_callback_add(bd->bg_object, "*", "*",
10439                                                   _e_border_cb_signal_bind, bd);
10440                   if (bd->focused)
10441                     {
10442                        edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
10443                        if (bd->icon_object)
10444                          edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
10445                     }
10446                   if (bd->shaded)
10447                     edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
10448                   if (bd->sticky)
10449                     edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
10450                   if (bd->hung)
10451                     edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
10452                   // FIXME: in eval -do differently
10453                   //         edje_object_message_signal_process(bd->bg_object);
10454                   //         e_border_frame_recalc(bd);
10455
10456                   evas_object_move(bd->bg_object, 0, 0);
10457                   evas_object_resize(bd->bg_object, bd->w, bd->h);
10458                   evas_object_show(bd->bg_object);
10459                }
10460           }
10461         bd->client.border.changed = 0;
10462
10463         if (bd->icon_object)
10464           {
10465              if (bd->bg_object)
10466                {
10467                   evas_object_show(bd->icon_object);
10468                   edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
10469                }
10470              else
10471                evas_object_hide(bd->icon_object);
10472           }
10473      }
10474
10475    if (rem_change) e_remember_update(bd);
10476
10477    if (change_urgent)
10478      {
10479         E_Event_Border_Urgent_Change *ev;
10480
10481         if (bd->client.icccm.urgent)
10482           edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
10483         else
10484           edje_object_signal_emit(bd->bg_object, "e,state,not_urgent", "e");
10485
10486         ev = E_NEW(E_Event_Border_Urgent_Change, 1);
10487         ev->border = bd;
10488         e_object_ref(E_OBJECT(bd));
10489         ecore_event_add(E_EVENT_BORDER_URGENT_CHANGE, ev,
10490                         _e_border_event_border_urgent_change_free, NULL);
10491      }
10492
10493    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, bd);
10494 }
10495
10496 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
10497 static void
10498 _e_border_latest_stacked_focus_check_set(E_Border *bd)
10499 {
10500    E_Border* temp_bd = NULL;
10501    E_Border* top_focusable_bd = NULL;
10502    Eina_Bool is_fully_obscured = EINA_FALSE;
10503    Ecore_X_XRegion *visible_region = NULL;
10504    Ecore_X_XRegion *win_region = NULL;
10505    Ecore_X_Rectangle visible_rect, win_rect;
10506    E_Border_List *bl;
10507
10508    // set the entire visible region as a root geometry
10509    visible_rect.x = bd->zone->x;
10510    visible_rect.y = bd->zone->y;
10511    visible_rect.width = bd->zone->w;
10512    visible_rect.height = bd->zone->h;
10513
10514    visible_region = ecore_x_xregion_new();
10515    if (!visible_region) return;
10516
10517    ecore_x_xregion_union_rect(visible_region, visible_region, &visible_rect);
10518
10519    bl = e_container_border_list_last(bd->zone->container);
10520    while ((temp_bd = e_container_border_list_prev(bl)))
10521      {
10522         if (temp_bd == bd) break;
10523
10524         if (temp_bd == focused) continue;
10525         if ((temp_bd->x >= bd->zone->w) || (temp_bd->y >= bd->zone->h)) continue;
10526         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10527         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10528             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10529             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10530             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10531             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10532             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10533             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10534           {
10535              if (!top_focusable_bd)
10536                {
10537                   top_focusable_bd = temp_bd;
10538                }
10539
10540              win_rect.x = temp_bd->x;
10541              win_rect.y = temp_bd->y;
10542              win_rect.width = temp_bd->w;
10543              win_rect.height = temp_bd->h;
10544
10545              // if it stick out or is bigger than the entire visible region,
10546              // clip it by the entire visible's geometry.
10547              E_RECTS_CLIP_TO_RECT(win_rect.x, win_rect.y,
10548                                   win_rect.width, win_rect.height,
10549                                   visible_rect.x, visible_rect.y,
10550                                   (int)(visible_rect.width), (int)(visible_rect.height));
10551
10552              if (ecore_x_xregion_rect_contain(visible_region, &win_rect))
10553                {
10554                   win_region = ecore_x_xregion_new();
10555                   if (win_region)
10556                     {
10557                        ecore_x_xregion_union_rect(win_region, win_region, &win_rect);
10558                        ecore_x_xregion_subtract(visible_region, visible_region, win_region);
10559                        ecore_x_xregion_free(win_region);
10560                        win_region = NULL;
10561
10562                        if (ecore_x_xregion_is_empty(visible_region))
10563                          {
10564                             is_fully_obscured = EINA_TRUE;
10565                             break;
10566                          }
10567                     }
10568                }
10569           }
10570      }
10571
10572    if (is_fully_obscured == EINA_TRUE)
10573      {
10574         e_border_focus_set(top_focusable_bd, 1, 1);
10575      }
10576    else
10577      {
10578         e_border_focus_set(bd, 1, 1);
10579      }
10580
10581    if (visible_region) ecore_x_xregion_free(visible_region);
10582    e_container_border_list_free(bl);
10583 }
10584
10585 static void
10586 _e_border_latest_stacked_focus(E_Border *bd)
10587 {
10588    E_Border *temp_bd;
10589    int root_w, root_h;
10590
10591    root_w = bd->zone->w;
10592    root_h = bd->zone->h;
10593
10594    Eina_List *l;
10595    EINA_LIST_FOREACH(focus_stack, l, temp_bd)
10596      {
10597         if (bd == temp_bd) continue;
10598         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10599         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10600
10601         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10602             (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10603             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10604             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10605             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10606             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10607             (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10608           {
10609              _e_border_latest_stacked_focus_check_set(temp_bd);
10610              break;
10611           }
10612      }
10613 }
10614
10615 static void
10616 _e_border_check_stack (E_Border *bd)
10617 {
10618    E_Border* temp_bd = NULL;
10619    E_Border* top_bd = NULL;
10620    int passed_focus = 0;
10621    int passed = 0;
10622    int root_w = bd->zone->w;
10623    int root_h = bd->zone->h;
10624
10625    E_Border_List *bl;
10626    bl = e_container_border_list_last(bd->zone->container);
10627    while ((temp_bd = e_container_border_list_prev(bl)))
10628      {
10629         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10630         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10631         if ((temp_bd != bd) &&
10632             (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) continue;
10633
10634         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10635            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10636            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10637            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10638            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10639            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10640            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10641           {
10642              if (bd == temp_bd)
10643                {
10644                   if (!passed)
10645                     {
10646                        e_border_focus_set_with_pointer(bd);
10647                        break;
10648                     }
10649                   else
10650                     {
10651                        if (!passed_focus)
10652                          {
10653                             e_border_focus_set_with_pointer(top_bd);
10654                          }
10655                        break;
10656                     }
10657                }
10658              else
10659                {
10660                   if (!passed)
10661                     {
10662                        if ((bd->client.icccm.accepts_focus) || (bd->client.icccm.take_focus))
10663                          {
10664                             if (!bd->lock_focus_out)
10665                               {
10666                                  e_border_focus_latest_set(bd);
10667                               }
10668                          }
10669                     }
10670                }
10671
10672              if (!passed)
10673                {
10674                   passed = 1;
10675                   top_bd = temp_bd;
10676                }
10677
10678              if (temp_bd == focused)
10679                {
10680                   passed_focus = 1;
10681                }
10682           }
10683      }
10684    e_container_border_list_free(bl);
10685 }
10686
10687 static void
10688 _e_border_focus_top_stack_set(E_Border* bd)
10689 {
10690    E_Border *temp_bd;
10691    int root_w, root_h;
10692
10693    root_w = bd->zone->w;
10694    root_h = bd->zone->h;
10695
10696    E_Border_List *bl;
10697    bl = e_container_border_list_last(bd->zone->container);
10698    while ((temp_bd = e_container_border_list_prev(bl)))
10699      {
10700         if ((temp_bd->x >= root_w) || (temp_bd->y >= root_h)) continue;
10701         if (((temp_bd->x + temp_bd->w) <= 0) || ((temp_bd->y + temp_bd->h) <= 0)) continue;
10702         if (temp_bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING) continue;
10703
10704         if ((!temp_bd->iconic) && (temp_bd->visible) && (temp_bd->desk == bd->desk) &&
10705            (temp_bd->client.icccm.accepts_focus || temp_bd->client.icccm.take_focus) &&
10706            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DOCK) &&
10707            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_TOOLBAR) &&
10708            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_MENU) &&
10709            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_SPLASH) &&
10710            (temp_bd->client.netwm.type != ECORE_X_WINDOW_TYPE_DESKTOP))
10711           {
10712              if (!temp_bd->focused)
10713                {
10714                   /* this border is the top of the latest stack */
10715                   e_border_focus_set (temp_bd, 1, 1);
10716                }
10717              break;
10718           }
10719      }
10720    e_container_border_list_free(bl);
10721 }
10722 #endif
10723
10724 static void
10725 _e_border_eval(E_Border *bd)
10726 {
10727    E_Event_Border_Property *event;
10728    E_Border_Pending_Move_Resize *pnd;
10729    int rem_change = 0;
10730    int send_event = 1;
10731
10732    if (e_object_is_del(E_OBJECT(bd)))
10733      {
10734         CRI("_e_border_eval(%p) with deleted border! - %d\n", bd, bd->new_client);
10735         bd->changed = 0;
10736         return;
10737      }
10738
10739    _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_NEW_BORDER, bd);
10740
10741    if (bd->new_client)
10742      {
10743         int zx = 0, zy = 0, zw = 0, zh = 0;
10744
10745         if (bd->zone)
10746           e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
10747
10748         /*
10749          * Limit maximum size of windows to useful geometry
10750          */
10751         // TODO: temoporary limited maximize algorithm
10752         // ->
10753         /*if (bd->w > zw)
10754           rw = zw;
10755           else
10756           rw = bd->w;
10757
10758           if (bd->h > zh)
10759           rh = zh;
10760           else
10761           rh = bd->h;
10762
10763           if ((rw != bd->w) || (rh != bd->h))
10764           {
10765           bd->w = rw;
10766           bd->h = rh;
10767           e_border_resize (bd, bd->w, bd->h);
10768           }*/
10769         // <-
10770
10771         if (bd->re_manage)
10772           {
10773              bd->x -= bd->client_inset.l;
10774              bd->y -= bd->client_inset.t;
10775              bd->changes.pos = 1;
10776              bd->placed = 1;
10777           }
10778         else if ((!bd->placed) && (bd->client.icccm.request_pos))
10779           {
10780
10781              Ecore_X_Window_Attributes *att;
10782              int bw;
10783
10784              att = &bd->client.initial_attributes;
10785              bw = att->border * 2;
10786              switch (bd->client.icccm.gravity)
10787                {
10788                 case ECORE_X_GRAVITY_N:
10789                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10790                    bd->y = att->y;
10791                    break;
10792
10793                 case ECORE_X_GRAVITY_NE:
10794                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10795                    bd->y = att->y;
10796                    break;
10797
10798                 case ECORE_X_GRAVITY_E:
10799                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10800                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10801                    break;
10802
10803                 case ECORE_X_GRAVITY_SE:
10804                    bd->x = (att->x - (bw)) - (bd->client_inset.l);
10805                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10806                    break;
10807
10808                 case ECORE_X_GRAVITY_S:
10809                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10810                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10811                    break;
10812
10813                 case ECORE_X_GRAVITY_SW:
10814                    bd->x = att->x;
10815                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10816                    break;
10817
10818                 case ECORE_X_GRAVITY_W:
10819                    bd->x = att->x;
10820                    bd->y = (att->y - (bw)) - (bd->client_inset.t);
10821                    break;
10822
10823                 case ECORE_X_GRAVITY_CENTER:
10824                    bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
10825                    bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
10826                    break;
10827
10828                 case ECORE_X_GRAVITY_NW:
10829                 default:
10830                    bd->x = att->x;
10831                    bd->y = att->y;
10832                }
10833
10834              /*
10835               * This ensures that windows that like to open with a x/y
10836               * position smaller than returned by e_zone_useful_geometry_get()
10837               * are moved to useful positions.
10838               */
10839              // ->
10840              if (e_config->geometry_auto_move)
10841                {
10842                   if (bd->x < zx)
10843                     bd->x = zx;
10844
10845                   if (bd->y < zy)
10846                     bd->y = zy;
10847
10848                   if (bd->x + bd->w > zx + zw)
10849                     bd->x = zx + zw - bd->w;
10850
10851                   if (bd->y + bd->h > zy + zh)
10852                     bd->y = zy + zh - bd->h;
10853                   // <--
10854
10855                   if (bd->zone && e_container_zone_at_point_get(bd->zone->container, bd->x, bd->y))
10856                     {
10857                        bd->changes.pos = 1;
10858                        bd->placed = 1;
10859                     }
10860                }
10861              else
10862                {
10863                   bd->changes.pos = 1;
10864                   bd->placed = 1;
10865                }
10866           }
10867         if (!bd->placed)
10868           {
10869              /* FIXME: special placement for dialogs etc. etc. etc goes
10870               * here */
10871              /* FIXME: what if parent is not on this desktop - or zone? */
10872              if ((bd->parent) && (bd->parent->visible))
10873                {
10874                   bd->x = bd->parent->x + ((bd->parent->w - bd->w) / 2);
10875                   bd->y = bd->parent->y + ((bd->parent->h - bd->h) / 2);
10876                   bd->changes.pos = 1;
10877                   bd->placed = 1;
10878                }
10879 #if 0
10880              else if ((bd->leader) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
10881                {
10882                   /* TODO: Place in center of group */
10883                }
10884 #endif
10885              else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
10886                {
10887                   bd->x = zx + ((zw - bd->w) / 2);
10888                   bd->y = zy + ((zh - bd->h) / 2);
10889                   bd->changes.pos = 1;
10890                   bd->placed = 1;
10891                }
10892           }
10893         if (!bd->placed)
10894           {
10895              Eina_List *skiplist = NULL;
10896              int new_x, new_y;
10897
10898              if (zw > bd->w)
10899                new_x = zx + (rand() % (zw - bd->w));
10900              else
10901                new_x = zx;
10902              if (zh > bd->h)
10903                new_y = zy + (rand() % (zh - bd->h));
10904              else
10905                new_y = zy;
10906
10907              if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
10908                {
10909                   skiplist = eina_list_append(skiplist, bd);
10910                   if (bd->desk)
10911                     e_place_desk_region_smart(bd->desk, skiplist,
10912                                               bd->x, bd->y, bd->w, bd->h,
10913                                               &new_x, &new_y);
10914                   else
10915                     e_place_zone_region_smart(bd->zone, skiplist,
10916                                               bd->x, bd->y, bd->w, bd->h,
10917                                               &new_x, &new_y);
10918                   eina_list_free(skiplist);
10919                }
10920              else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
10921                {
10922                   e_place_zone_manual(bd->zone, bd->w, bd->client_inset.t,
10923                                       &new_x, &new_y);
10924                }
10925              else
10926                {
10927                   e_place_zone_cursor(bd->zone, bd->x, bd->y, bd->w, bd->h,
10928                                       bd->client_inset.t, &new_x, &new_y);
10929                }
10930              bd->x = new_x;
10931              bd->y = new_y;
10932              bd->changes.pos = 1;
10933           }
10934
10935         EINA_LIST_FREE(bd->pending_move_resize, pnd)
10936           {
10937              if ((!bd->lock_client_location) && (pnd->move))
10938                {
10939                   bd->x = pnd->x;
10940                   bd->y = pnd->y;
10941                   bd->changes.pos = 1;
10942                   bd->placed = 1;
10943                   if (pnd->without_border)
10944                     {
10945                        bd->x -= bd->client_inset.l;
10946                        bd->y -= bd->client_inset.t;
10947                     }
10948                }
10949              if ((!bd->lock_client_size) && (pnd->resize))
10950                {
10951                   bd->w = pnd->w + (bd->client_inset.l + bd->client_inset.r);
10952                   bd->h = pnd->h + (bd->client_inset.t + bd->client_inset.b);
10953                   bd->client.w = pnd->w;
10954                   bd->client.h = pnd->h;
10955                   bd->changes.size = 1;
10956                }
10957
10958              free(pnd);
10959           }
10960
10961         /* Recreate state */
10962         e_hints_window_init(bd);
10963         if ((bd->client.e.state.centered) &&
10964             ((!bd->remember) ||
10965              ((bd->remember) && (!(bd->remember->apply & E_REMEMBER_APPLY_POS)))))
10966           {
10967              bd->x = zx + (zw - bd->w) / 2;
10968              bd->y = zy + (zh - bd->h) / 2;
10969              bd->changes.pos = 1;
10970              bd->placed = 1;
10971           }
10972
10973         _e_border_client_move_resize_send(bd);
10974
10975         /* if the explicit geometry request asks for the app to be
10976          * in another zone - well move it there */
10977         {
10978            E_Zone *zone;
10979
10980            zone = e_container_zone_at_point_get(bd->zone->container,
10981                                                 bd->x + (bd->w / 2),
10982                                                 bd->y + (bd->h / 2));
10983            if (!zone)
10984              zone = e_container_zone_at_point_get(bd->zone->container,
10985                                                   bd->x,
10986                                                   bd->y);
10987            if (!zone)
10988              zone = e_container_zone_at_point_get(bd->zone->container,
10989                                                   bd->x + bd->w - 1,
10990                                                   bd->y);
10991            if (!zone)
10992              zone = e_container_zone_at_point_get(bd->zone->container,
10993                                                   bd->x + bd->w - 1,
10994                                                   bd->y + bd->h - 1);
10995            if (!zone)
10996              zone = e_container_zone_at_point_get(bd->zone->container,
10997                                                   bd->x,
10998                                                   bd->y + bd->h - 1);
10999            if ((zone) && (zone != bd->zone))
11000              e_border_zone_set(bd, zone);
11001         }
11002      }
11003
11004    _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_NEW_BORDER, bd);
11005
11006    /* effect changes to the window border itself */
11007    if ((bd->changes.shading))
11008      {
11009         /*  show at start of unshade (but don't hide until end of shade) */
11010         if (bd->shaded)
11011           ecore_x_window_raise(bd->client.shell_win);
11012         bd->changes.shading = 0;
11013         rem_change = 1;
11014      }
11015    if ((bd->changes.shaded) && (bd->changes.pos) && (bd->changes.size))
11016      {
11017         if (bd->shaded)
11018           ecore_x_window_lower(bd->client.shell_win);
11019         else
11020           ecore_x_window_raise(bd->client.shell_win);
11021         bd->changes.shaded = 0;
11022         rem_change = 1;
11023      }
11024    else if ((bd->changes.shaded) && (bd->changes.pos))
11025      {
11026         if (bd->shaded)
11027           ecore_x_window_lower(bd->client.shell_win);
11028         else
11029           ecore_x_window_raise(bd->client.shell_win);
11030         bd->changes.size = 1;
11031         bd->changes.shaded = 0;
11032         rem_change = 1;
11033      }
11034    else if ((bd->changes.shaded) && (bd->changes.size))
11035      {
11036         if (bd->shaded)
11037           ecore_x_window_lower(bd->client.shell_win);
11038         else
11039           ecore_x_window_raise(bd->client.shell_win);
11040         bd->changes.shaded = 0;
11041         rem_change = 1;
11042      }
11043    else if (bd->changes.shaded)
11044      {
11045         if (bd->shaded)
11046           ecore_x_window_lower(bd->client.shell_win);
11047         else
11048           ecore_x_window_raise(bd->client.shell_win);
11049         bd->changes.size = 1;
11050         bd->changes.shaded = 0;
11051         rem_change = 1;
11052      }
11053
11054    if (bd->changes.size)
11055      {
11056         int x = 0, y = 0, xx = 0, yy = 0;
11057
11058         if ((bd->shaded) && (!bd->shading))
11059           {
11060              evas_obscured_clear(bd->bg_evas);
11061           }
11062         else
11063           {
11064              xx = bd->w - (bd->client_inset.l + bd->client_inset.r);
11065              yy = bd->h - (bd->client_inset.t + bd->client_inset.b);
11066
11067              evas_obscured_clear(bd->bg_evas);
11068              evas_obscured_rectangle_add(bd->bg_evas,
11069                                          bd->client_inset.l, bd->client_inset.t, xx, yy);
11070
11071              if (bd->shading)
11072                {
11073                   if (bd->shade.dir == E_DIRECTION_UP)
11074                     {
11075                        y = yy - bd->client.h;
11076                     }
11077                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11078                     {
11079                        x = xx - bd->client.w;
11080                     }
11081                }
11082           }
11083
11084         if (bd->client.e.state.video)
11085           {
11086              if (bd->client.e.state.video_position.updated)
11087                {
11088                   ecore_x_window_move(bd->win,
11089                                       bd->client.e.state.video_parent_border->x +
11090                                       bd->client.e.state.video_parent_border->client_inset.l +
11091                                       bd->client.e.state.video_parent_border->fx.x +
11092                                       bd->client.e.state.video_position.x,
11093                                       bd->client.e.state.video_parent_border->y +
11094                                       bd->client.e.state.video_parent_border->client_inset.t +
11095                                       bd->client.e.state.video_parent_border->fx.y +
11096                                       bd->client.e.state.video_position.y);
11097                   bd->client.e.state.video_position.updated = 0;
11098                }
11099           }
11100         else if (!bd->changes.pos)
11101           {
11102              if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
11103              bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
11104              bd->post_resize = 1;
11105           }
11106         else
11107           {
11108              E_Border *tmp;
11109              Eina_List *l;
11110
11111              ecore_x_window_move_resize(bd->win,
11112                                         bd->x + bd->fx.x,
11113                                         bd->y + bd->fx.y,
11114                                         bd->w, bd->h);
11115
11116              EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
11117                ecore_x_window_move(tmp->win,
11118                                    bd->x + bd->fx.x + bd->client_inset.l + tmp->client.e.state.video_position.x,
11119                                    bd->y + bd->fx.y + bd->client_inset.t + tmp->client.e.state.video_position.y);
11120           }
11121
11122         ecore_x_window_move_resize(bd->event_win, 0, 0, bd->w, bd->h);
11123
11124         if ((!bd->shaded) || (bd->shading))
11125           ecore_x_window_move_resize(bd->client.shell_win,
11126                                      bd->client_inset.l, bd->client_inset.t, xx, yy);
11127
11128         if (bd->internal_ecore_evas)
11129           ecore_evas_move_resize(bd->internal_ecore_evas, x, y, bd->client.w, bd->client.h);
11130         else if (!bd->client.e.state.video)
11131           ecore_x_window_move_resize(bd->client.win, x, y, bd->client.w, bd->client.h);
11132
11133         ecore_evas_move_resize(bd->bg_ecore_evas, 0, 0, bd->w, bd->h);
11134         evas_object_resize(bd->bg_object, bd->w, bd->h);
11135         e_container_shape_resize(bd->shape, bd->w, bd->h);
11136         if (bd->changes.pos)
11137           e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
11138
11139         _e_border_client_move_resize_send(bd);
11140
11141         bd->changes.pos = 0;
11142         bd->changes.size = 0;
11143         rem_change = 1;
11144      }
11145    else if (bd->changes.pos)
11146      {
11147         if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
11148         bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
11149         bd->post_move = 1;
11150
11151         e_container_shape_move(bd->shape, bd->x + bd->fx.x, bd->y + bd->fx.y);
11152
11153         _e_border_client_move_resize_send(bd);
11154
11155         bd->changes.pos = 0;
11156         rem_change = 1;
11157      }
11158
11159    if (bd->changes.reset_gravity)
11160      {
11161         GRAV_SET(bd, ECORE_X_GRAVITY_NW);
11162         bd->changes.reset_gravity = 0;
11163         rem_change = 1;
11164      }
11165
11166    if (bd->need_shape_merge)
11167      {
11168         _e_border_shape_input_rectangle_set(bd);
11169         if ((bd->shaped) || (bd->client.shaped))
11170           {
11171              Ecore_X_Window twin, twin2;
11172              int x, y;
11173
11174              twin = ecore_x_window_override_new
11175                (bd->zone->container->scratch_win, 0, 0, bd->w, bd->h);
11176              if (bd->shaped)
11177                ecore_x_window_shape_window_set(twin, bd->bg_win);
11178              else
11179                {
11180                   Ecore_X_Rectangle rects[4];
11181
11182                   rects[0].x = 0;
11183                   rects[0].y = 0;
11184                   rects[0].width = bd->w;
11185                   rects[0].height = bd->client_inset.t;
11186                   rects[1].x = 0;
11187                   rects[1].y = bd->client_inset.t;
11188                   rects[1].width = bd->client_inset.l;
11189                   rects[1].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11190                   rects[2].x = bd->w - bd->client_inset.r;
11191                   rects[2].y = bd->client_inset.t;
11192                   rects[2].width = bd->client_inset.r;
11193                   rects[2].height = bd->h - bd->client_inset.t - bd->client_inset.b;
11194                   rects[3].x = 0;
11195                   rects[3].y = bd->h - bd->client_inset.b;
11196                   rects[3].width = bd->w;
11197                   rects[3].height = bd->client_inset.b;
11198                   ecore_x_window_shape_rectangles_set(twin, rects, 4);
11199                }
11200              twin2 = ecore_x_window_override_new
11201                (bd->zone->container->scratch_win, 0, 0,
11202                 bd->w - bd->client_inset.l - bd->client_inset.r,
11203                 bd->h - bd->client_inset.t - bd->client_inset.b);
11204              x = 0;
11205              y = 0;
11206              if ((bd->shading) || (bd->shaded))
11207                {
11208                   if (bd->shade.dir == E_DIRECTION_UP)
11209                     y = bd->h - bd->client_inset.t - bd->client_inset.b - bd->client.h;
11210                   else if (bd->shade.dir == E_DIRECTION_LEFT)
11211                     x = bd->w - bd->client_inset.l - bd->client_inset.r - bd->client.w;
11212                }
11213              ecore_x_window_shape_window_set_xy(twin2, bd->client.win,
11214                                                 x, y);
11215              ecore_x_window_shape_rectangle_clip(twin2, 0, 0,
11216                                                  bd->w - bd->client_inset.l - bd->client_inset.r,
11217                                                  bd->h - bd->client_inset.t - bd->client_inset.b);
11218              ecore_x_window_shape_window_add_xy(twin, twin2,
11219                                                 bd->client_inset.l,
11220                                                 bd->client_inset.t);
11221              ecore_x_window_free(twin2);
11222              ecore_x_window_shape_window_set(bd->win, twin);
11223              ecore_x_window_free(twin);
11224           }
11225         else
11226           ecore_x_window_shape_mask_set(bd->win, 0);
11227         //      bd->need_shape_export = 1;
11228         bd->need_shape_merge = 0;
11229      }
11230
11231    if (bd->need_shape_export)
11232      {
11233         Ecore_X_Rectangle *rects, *orects;
11234         int num;
11235
11236         rects = ecore_x_window_shape_rectangles_get(bd->win, &num);
11237         if (rects)
11238           {
11239              int changed;
11240
11241              changed = 1;
11242              if ((num == bd->shape_rects_num) && (bd->shape_rects))
11243                {
11244                   int i;
11245
11246                   orects = bd->shape_rects;
11247                   changed = 0;
11248                   for (i = 0; i < num; i++)
11249                     {
11250                        if (rects[i].x < 0)
11251                          {
11252                             rects[i].width -= rects[i].x;
11253                             rects[i].x = 0;
11254                          }
11255                        if ((rects[i].x + (int)rects[i].width) > bd->w)
11256                          rects[i].width = rects[i].width - rects[i].x;
11257                        if (rects[i].y < 0)
11258                          {
11259                             rects[i].height -= rects[i].y;
11260                             rects[i].y = 0;
11261                          }
11262                        if ((rects[i].y + (int)rects[i].height) > bd->h)
11263                          rects[i].height = rects[i].height - rects[i].y;
11264
11265                        if ((orects[i].x != rects[i].x) ||
11266                            (orects[i].y != rects[i].y) ||
11267                            (orects[i].width != rects[i].width) ||
11268                            (orects[i].height != rects[i].height))
11269                          {
11270                             changed = 1;
11271                             break;
11272                          }
11273                     }
11274                }
11275              if (changed)
11276                {
11277                   if (bd->client.shaped)
11278                     e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
11279                   else
11280                     e_container_shape_solid_rect_set(bd->shape, bd->client_inset.l, bd->client_inset.t, bd->client.w, bd->client.h);
11281                   E_FREE(bd->shape_rects);
11282                   bd->shape_rects = rects;
11283                   bd->shape_rects_num = num;
11284                   e_container_shape_rects_set(bd->shape, rects, num);
11285                }
11286              else
11287                free(rects);
11288           }
11289         else
11290           {
11291              E_FREE(bd->shape_rects);
11292              bd->shape_rects = NULL;
11293              bd->shape_rects_num = 0;
11294              e_container_shape_rects_set(bd->shape, NULL, 0);
11295           }
11296         bd->need_shape_export = 0;
11297      }
11298
11299    if ((bd->changes.visible) && (bd->visible) && (bd->new_client))
11300      {
11301         int x, y;
11302
11303         ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
11304         if ((!bd->placed) && (!bd->re_manage) &&
11305             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
11306             (!((bd->client.icccm.transient_for != 0) ||
11307                (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) &&
11308             (!bdmove) && (!bdresize))
11309           {
11310              /* Set this window into moving state */
11311
11312              bd->cur_mouse_action = e_action_find("window_move");
11313              if (bd->cur_mouse_action)
11314                {
11315                   if ((!bd->cur_mouse_action->func.end_mouse) &&
11316                       (!bd->cur_mouse_action->func.end))
11317                     bd->cur_mouse_action = NULL;
11318                   if (bd->cur_mouse_action)
11319                     {
11320                        bd->x = x - (bd->w >> 1);
11321                        bd->y = y - (bd->client_inset.t >> 1);
11322                        bd->changed = 1;
11323                        bd->changes.pos = 1;
11324
11325                        _e_border_client_move_resize_send(bd);
11326                     }
11327                }
11328           }
11329
11330         _e_border_show(bd);
11331
11332         if (bd->cur_mouse_action)
11333           {
11334              bd->moveinfo.down.x = bd->x + bd->fx.x;
11335              bd->moveinfo.down.y = bd->y + bd->fx.y;
11336              bd->moveinfo.down.w = bd->w;
11337              bd->moveinfo.down.h = bd->h;
11338              bd->mouse.current.mx = x;
11339              bd->mouse.current.my = y;
11340              bd->moveinfo.down.button = 0;
11341              bd->moveinfo.down.mx = x;
11342              bd->moveinfo.down.my = y;
11343
11344              grabbed = 1;
11345              e_object_ref(E_OBJECT(bd->cur_mouse_action));
11346              bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
11347              if (e_config->border_raise_on_mouse_action)
11348                e_border_raise(bd);
11349              e_border_focus_set(bd, 1, 1);
11350           }
11351         bd->changes.visible = 0;
11352         rem_change = 1;
11353      }
11354
11355    if (bd->changes.icon)
11356      {
11357         if (bd->desktop)
11358           {
11359              efreet_desktop_free(bd->desktop);
11360              bd->desktop = NULL;
11361           }
11362         if (bd->icon_object)
11363           {
11364              evas_object_del(bd->icon_object);
11365              bd->icon_object = NULL;
11366           }
11367         if (bd->remember && bd->remember->prop.desktop_file)
11368           {
11369              const char *desktop = bd->remember->prop.desktop_file;
11370
11371              bd->desktop = efreet_desktop_get(desktop);
11372              if (!bd->desktop)
11373                bd->desktop = efreet_util_desktop_name_find(desktop);
11374           }
11375         if (!bd->desktop)
11376           {
11377              if ((bd->client.icccm.name) && (bd->client.icccm.class))
11378                bd->desktop = efreet_util_desktop_wm_class_find(bd->client.icccm.name,
11379                                                                bd->client.icccm.class);
11380           }
11381         if (!bd->desktop)
11382           {
11383              /* libreoffice and maybe others match window class
11384                 with .desktop file name */
11385              if (bd->client.icccm.class)
11386                {
11387                   char buf[128];
11388                   snprintf(buf, sizeof(buf), "%s.desktop", bd->client.icccm.class);
11389                   bd->desktop = efreet_util_desktop_file_id_find(buf);
11390                }
11391           }
11392         if (!bd->desktop)
11393           {
11394              bd->desktop = e_exec_startup_id_pid_find(bd->client.netwm.startup_id,
11395                                                       bd->client.netwm.pid);
11396              if (bd->desktop) efreet_desktop_ref(bd->desktop);
11397           }
11398         if (!bd->desktop && bd->client.icccm.name)
11399           {
11400              /* this works for most cases as fallback. useful when app is
11401                 run from a shell  */
11402              bd->desktop = efreet_util_desktop_exec_find(bd->client.icccm.name);
11403           }
11404         if (!bd->desktop && bd->client.icccm.transient_for)
11405           {
11406              E_Border *bd2 = e_border_find_by_client_window(bd->client.icccm.transient_for);
11407              if (bd2 && bd2->desktop)
11408                {
11409                   efreet_desktop_ref(bd2->desktop);
11410                   bd->desktop = bd2->desktop;
11411                }
11412           }
11413         if (bd->desktop)
11414           {
11415              ecore_x_window_prop_string_set(bd->client.win, E_ATOM_DESKTOP_FILE,
11416                                             bd->desktop->orig_path);
11417           }
11418
11419         bd->icon_object = e_border_icon_add(bd, bd->bg_evas);
11420         if ((bd->focused) && (bd->icon_object))
11421           edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
11422         if (bd->bg_object)
11423           {
11424              evas_object_show(bd->icon_object);
11425              edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
11426           }
11427         else
11428           evas_object_hide(bd->icon_object);
11429
11430         {
11431            E_Event_Border_Icon_Change *ev;
11432
11433            ev = E_NEW(E_Event_Border_Icon_Change, 1);
11434            ev->border = bd;
11435            e_object_ref(E_OBJECT(bd));
11436            //        e_object_breadcrumb_add(E_OBJECT(bd), "border_icon_change_event");
11437            ecore_event_add(E_EVENT_BORDER_ICON_CHANGE, ev,
11438                            _e_border_event_border_icon_change_free, NULL);
11439         }
11440         bd->changes.icon = 0;
11441      }
11442
11443    bd->new_client = 0;
11444    bd->changed = 0;
11445    bd->changes.stack = 0;
11446    bd->changes.prop = 0;
11447
11448    if (bd->client.e.state.rot.changes != -1)
11449      {
11450         e_border_rotation_set(bd, bd->client.e.state.rot.changes);
11451         bd->client.e.state.rot.changes = -1;
11452      }
11453
11454    if ((bd->take_focus) || (bd->want_focus))
11455      {
11456         bd->take_focus = 0;
11457 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11458         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
11459             (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK) ||
11460             (bd->want_focus))
11461 #else // original
11462         if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (bd->want_focus))
11463 #endif
11464           {
11465              bd->want_focus = 0;
11466 #ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
11467              if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
11468                 _e_border_check_stack(bd);
11469              else
11470 #endif
11471              e_border_focus_set_with_pointer(bd);
11472           }
11473         else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
11474           {
11475              if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
11476                  ((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
11477                   (e_border_find_by_client_window(bd->client.icccm.transient_for) ==
11478                    e_border_focused_get())))
11479                {
11480                   e_border_focus_set_with_pointer(bd);
11481                }
11482           }
11483         else
11484           {
11485              /* focus window by default when it is the only one on desk */
11486              E_Border *bd2 = NULL;
11487              Eina_List *l;
11488              EINA_LIST_FOREACH(focus_stack, l, bd2)
11489                {
11490                   if (bd == bd2) continue;
11491                   if ((!bd2->iconic) && (bd2->visible) &&
11492                       ((bd->desk == bd2->desk) || bd2->sticky))
11493                     break;
11494                }
11495
11496              if (!bd2)
11497                {
11498                   e_border_focus_set_with_pointer(bd);
11499                }
11500           }
11501      }
11502
11503    if (bd->need_maximize)
11504      {
11505         E_Maximize max;
11506         max = bd->maximized;
11507         bd->maximized = E_MAXIMIZE_NONE;
11508         e_border_maximize(bd, max);
11509         bd->need_maximize = 0;
11510      }
11511
11512    if (bd->need_fullscreen)
11513      {
11514         e_border_fullscreen(bd, e_config->fullscreen_policy);
11515         bd->need_fullscreen = 0;
11516      }
11517
11518    if (rem_change)
11519      e_remember_update(bd);
11520
11521    if (send_event) // FIXME: send only if a property changed - above need to
11522      { // check on that. for now - always send.
11523         event = E_NEW(E_Event_Border_Property, 1);
11524         event->border = bd;
11525         e_object_ref(E_OBJECT(bd));
11526         ecore_event_add(E_EVENT_BORDER_PROPERTY, event, _e_border_event_border_property_free, NULL);
11527      }
11528    _e_border_hook_call(E_BORDER_HOOK_EVAL_END, bd);
11529 }
11530
11531 static void
11532 _e_border_moveinfo_gather(E_Border   *bd,
11533                           const char *source)
11534 {
11535    if (e_util_glob_match(source, "mouse,*,1")) bd->moveinfo.down.button = 1;
11536    else if (e_util_glob_match(source, "mouse,*,2"))
11537      bd->moveinfo.down.button = 2;
11538    else if (e_util_glob_match(source, "mouse,*,3"))
11539      bd->moveinfo.down.button = 3;
11540    else bd->moveinfo.down.button = 0;
11541    if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
11542      {
11543         bd->moveinfo.down.mx = bd->mouse.last_down[bd->moveinfo.down.button - 1].mx;
11544         bd->moveinfo.down.my = bd->mouse.last_down[bd->moveinfo.down.button - 1].my;
11545      }
11546    else
11547      {
11548         bd->moveinfo.down.mx = bd->mouse.current.mx;
11549         bd->moveinfo.down.my = bd->mouse.current.my;
11550      }
11551 }
11552
11553 static void
11554 _e_border_resize_handle(E_Border *bd)
11555 {
11556    int x, y, w, h;
11557    int new_x, new_y, new_w, new_h;
11558    int tw, th;
11559    Eina_List *skiplist = NULL;
11560
11561    x = bd->x;
11562    y = bd->y;
11563    w = bd->w;
11564    h = bd->h;
11565
11566    if ((bd->resize_mode == RESIZE_TR) ||
11567        (bd->resize_mode == RESIZE_R) ||
11568        (bd->resize_mode == RESIZE_BR))
11569      {
11570         if ((bd->moveinfo.down.button >= 1) &&
11571             (bd->moveinfo.down.button <= 3))
11572           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w +
11573             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11574         else
11575           w = bd->moveinfo.down.w + (bd->mouse.current.mx - bd->moveinfo.down.mx);
11576      }
11577    else if ((bd->resize_mode == RESIZE_TL) ||
11578             (bd->resize_mode == RESIZE_L) ||
11579             (bd->resize_mode == RESIZE_BL))
11580      {
11581         if ((bd->moveinfo.down.button >= 1) &&
11582             (bd->moveinfo.down.button <= 3))
11583           w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w -
11584             (bd->mouse.current.mx - bd->moveinfo.down.mx);
11585         else
11586           w = bd->moveinfo.down.w - (bd->mouse.current.mx - bd->moveinfo.down.mx);
11587      }
11588
11589    if ((bd->resize_mode == RESIZE_TL) ||
11590        (bd->resize_mode == RESIZE_T) ||
11591        (bd->resize_mode == RESIZE_TR))
11592      {
11593         if ((bd->moveinfo.down.button >= 1) &&
11594             (bd->moveinfo.down.button <= 3))
11595           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h -
11596             (bd->mouse.current.my - bd->moveinfo.down.my);
11597         else
11598           h = bd->moveinfo.down.h - (bd->mouse.current.my - bd->moveinfo.down.my);
11599      }
11600    else if ((bd->resize_mode == RESIZE_BL) ||
11601             (bd->resize_mode == RESIZE_B) ||
11602             (bd->resize_mode == RESIZE_BR))
11603      {
11604         if ((bd->moveinfo.down.button >= 1) &&
11605             (bd->moveinfo.down.button <= 3))
11606           h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h +
11607             (bd->mouse.current.my - bd->moveinfo.down.my);
11608         else
11609           h = bd->moveinfo.down.h + (bd->mouse.current.my - bd->moveinfo.down.my);
11610      }
11611
11612    tw = bd->w;
11613    th = bd->h;
11614
11615    if ((bd->resize_mode == RESIZE_TL) ||
11616        (bd->resize_mode == RESIZE_L) ||
11617        (bd->resize_mode == RESIZE_BL))
11618      x += (tw - w);
11619    if ((bd->resize_mode == RESIZE_TL) ||
11620        (bd->resize_mode == RESIZE_T) ||
11621        (bd->resize_mode == RESIZE_TR))
11622      y += (th - h);
11623
11624    skiplist = eina_list_append(skiplist, bd);
11625    e_resist_container_border_position(bd->zone->container, skiplist,
11626                                       bd->x, bd->y, bd->w, bd->h,
11627                                       x, y, w, h,
11628                                       &new_x, &new_y, &new_w, &new_h);
11629    eina_list_free(skiplist);
11630
11631    w = new_w;
11632    h = new_h;
11633    e_border_resize_limit(bd, &new_w, &new_h);
11634    if ((bd->resize_mode == RESIZE_TL) ||
11635        (bd->resize_mode == RESIZE_L) ||
11636        (bd->resize_mode == RESIZE_BL))
11637      new_x += (w - new_w);
11638    if ((bd->resize_mode == RESIZE_TL) ||
11639        (bd->resize_mode == RESIZE_T) ||
11640        (bd->resize_mode == RESIZE_TR))
11641      new_y += (h - new_h);
11642
11643    e_border_move_resize(bd, new_x, new_y, new_w, new_h);
11644 }
11645
11646 static Eina_Bool
11647 _e_border_shade_animator(void *data)
11648 {
11649    E_Border *bd = data;
11650    double dt, val;
11651    double dur = bd->client.h / e_config->border_shade_speed;
11652
11653    dt = ecore_loop_time_get() - bd->shade.start;
11654    val = dt / dur;
11655
11656    if (val < 0.0) val = 0.0;
11657    else if (val > 1.0) val = 1.0;
11658
11659    if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
11660      {
11661         bd->shade.val =
11662            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL, 0.0, 0.0);
11663         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11664      }
11665    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE)
11666      {
11667         bd->shade.val =
11668            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
11669         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11670      }
11671    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE)
11672      {
11673         bd->shade.val =
11674            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
11675         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11676      }
11677    else if (e_config->border_shade_transition == E_TRANSITION_LINEAR)
11678      {
11679         bd->shade.val =
11680            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11681         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11682      }
11683    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE_LOTS)
11684      {
11685         bd->shade.val =
11686            ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE_FACTOR, 1.7, 0.0);
11687         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11688      }
11689    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE_LOTS)
11690      {
11691         bd->shade.val =
11692            ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE_FACTOR, 1.7, 0.0);
11693         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11694      }
11695    else if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL_LOTS)
11696      {
11697         bd->shade.val =
11698            ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL_FACTOR, 1.7, 0.0);
11699         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11700      }
11701    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE)
11702      {
11703         bd->shade.val =
11704            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 3.0);
11705         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11706      }
11707    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE_LOTS)
11708      {
11709         bd->shade.val =
11710            ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 5.0);
11711         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11712      }
11713    else
11714      {
11715         bd->shade.val =
11716            ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
11717         if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
11718      }
11719
11720    /* due to M_PI's innacuracy, cos(M_PI/2) != 0.0, so we need this */
11721    if (bd->shade.val < 0.001) bd->shade.val = 0.0;
11722    else if (bd->shade.val > .999)
11723      bd->shade.val = 1.0;
11724
11725    if (bd->shade.dir == E_DIRECTION_UP)
11726      bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11727    else if (bd->shade.dir == E_DIRECTION_DOWN)
11728      {
11729         bd->h = bd->client_inset.t + bd->client_inset.b + bd->client.h * bd->shade.val;
11730         bd->y = bd->shade.y + bd->client.h * (1 - bd->shade.val);
11731         bd->changes.pos = 1;
11732      }
11733    else if (bd->shade.dir == E_DIRECTION_LEFT)
11734      bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11735    else if (bd->shade.dir == E_DIRECTION_RIGHT)
11736      {
11737         bd->w = bd->client_inset.l + bd->client_inset.r + bd->client.w * bd->shade.val;
11738         bd->x = bd->shade.x + bd->client.w * (1 - bd->shade.val);
11739         bd->changes.pos = 1;
11740      }
11741
11742    if ((bd->shaped) || (bd->client.shaped))
11743      {
11744         bd->need_shape_merge = 1;
11745         bd->need_shape_export = 1;
11746      }
11747    if (bd->shaped_input)
11748      {
11749         bd->need_shape_merge = 1;
11750      }
11751    bd->changes.size = 1;
11752    bd->changed = 1;
11753
11754    /* we're done */
11755    if (val == 1)
11756      {
11757         E_Event_Border_Resize *ev;
11758
11759         bd->shading = 0;
11760         bd->shaded = !(bd->shaded);
11761         bd->changes.size = 1;
11762         bd->changes.shaded = 1;
11763         bd->changes.shading = 1;
11764         bd->changed = 1;
11765         bd->shade.anim = NULL;
11766
11767         if (bd->shaded)
11768           edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
11769         else
11770           edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
11771         edje_object_message_signal_process(bd->bg_object);
11772         e_border_frame_recalc(bd);
11773
11774         ecore_x_window_gravity_set(bd->client.win, ECORE_X_GRAVITY_NW);
11775         ev = E_NEW(E_Event_Border_Resize, 1);
11776         ev->border = bd;
11777         e_object_ref(E_OBJECT(bd));
11778 //      e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
11779         ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
11780         return ECORE_CALLBACK_CANCEL;
11781      }
11782    return ECORE_CALLBACK_RENEW;
11783 }
11784
11785 static void
11786 _e_border_event_border_resize_free(void *data __UNUSED__,
11787                                    void      *ev)
11788 {
11789    E_Event_Border_Resize *e;
11790
11791    e = ev;
11792 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_resize_event");
11793    e_object_unref(E_OBJECT(e->border));
11794    E_FREE(e);
11795 }
11796
11797 static void
11798 _e_border_event_border_move_free(void *data __UNUSED__,
11799                                  void      *ev)
11800 {
11801    E_Event_Border_Move *e;
11802
11803    e = ev;
11804 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_move_event");
11805    e_object_unref(E_OBJECT(e->border));
11806    E_FREE(e);
11807 }
11808
11809 static void
11810 _e_border_event_border_add_free(void *data __UNUSED__,
11811                                 void      *ev)
11812 {
11813    E_Event_Border_Add *e;
11814
11815    e = ev;
11816 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_add_event");
11817    e_object_unref(E_OBJECT(e->border));
11818    E_FREE(e);
11819 }
11820
11821 static void
11822 _e_border_event_border_remove_free(void *data __UNUSED__,
11823                                    void      *ev)
11824 {
11825    E_Event_Border_Remove *e;
11826
11827    e = ev;
11828 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_remove_event");
11829    e_object_unref(E_OBJECT(e->border));
11830    E_FREE(e);
11831 }
11832
11833 static void
11834 _e_border_event_border_show_free(void *data __UNUSED__,
11835                                  void      *ev)
11836 {
11837    E_Event_Border_Show *e;
11838
11839    e = ev;
11840 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_show_event");
11841    e_object_unref(E_OBJECT(e->border));
11842    E_FREE(e);
11843 }
11844
11845 static void
11846 _e_border_event_border_hide_free(void *data __UNUSED__,
11847                                  void      *ev)
11848 {
11849    E_Event_Border_Hide *e;
11850
11851    e = ev;
11852 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_hide_event");
11853    e_object_unref(E_OBJECT(e->border));
11854    E_FREE(e);
11855 }
11856
11857 static void
11858 _e_border_event_border_iconify_free(void *data __UNUSED__,
11859                                     void      *ev)
11860 {
11861    E_Event_Border_Iconify *e;
11862
11863    e = ev;
11864 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_iconify_event");
11865    e_object_unref(E_OBJECT(e->border));
11866    E_FREE(e);
11867 }
11868
11869 static void
11870 _e_border_event_border_uniconify_free(void *data __UNUSED__,
11871                                       void      *ev)
11872 {
11873    E_Event_Border_Uniconify *e;
11874
11875    e = ev;
11876 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_uniconify_event");
11877    e_object_unref(E_OBJECT(e->border));
11878    E_FREE(e);
11879 }
11880
11881 static void
11882 _e_border_event_border_stick_free(void *data __UNUSED__,
11883                                   void      *ev)
11884 {
11885    E_Event_Border_Stick *e;
11886
11887    e = ev;
11888 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_stick_event");
11889    e_object_unref(E_OBJECT(e->border));
11890    E_FREE(e);
11891 }
11892
11893 static void
11894 _e_border_event_border_unstick_free(void *data __UNUSED__,
11895                                     void      *ev)
11896 {
11897    E_Event_Border_Unstick *e;
11898
11899    e = ev;
11900 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unstick_event");
11901    e_object_unref(E_OBJECT(e->border));
11902    E_FREE(e);
11903 }
11904
11905 static void
11906 _e_border_event_border_zone_set_free(void *data __UNUSED__,
11907                                      void      *ev)
11908 {
11909    E_Event_Border_Zone_Set *e;
11910
11911    e = ev;
11912 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_zone_set_event");
11913    e_object_unref(E_OBJECT(e->border));
11914    e_object_unref(E_OBJECT(e->zone));
11915    E_FREE(e);
11916 }
11917
11918 static void
11919 _e_border_event_border_desk_set_free(void *data __UNUSED__,
11920                                      void      *ev)
11921 {
11922    E_Event_Border_Desk_Set *e;
11923
11924    e = ev;
11925 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_desk_set_event");
11926    e_object_unref(E_OBJECT(e->border));
11927    e_object_unref(E_OBJECT(e->desk));
11928    E_FREE(e);
11929 }
11930
11931 static void
11932 _e_border_event_border_stack_free(void *data __UNUSED__,
11933                                   void      *ev)
11934 {
11935    E_Event_Border_Stack *e;
11936
11937    e = ev;
11938 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_raise_event");
11939    e_object_unref(E_OBJECT(e->border));
11940    if (e->stack)
11941      {
11942 //      e_object_breadcrumb_del(E_OBJECT(e->above), "border_raise_event.above");
11943           e_object_unref(E_OBJECT(e->stack));
11944      }
11945    E_FREE(e);
11946 }
11947
11948 static void
11949 _e_border_event_border_icon_change_free(void *data __UNUSED__,
11950                                         void      *ev)
11951 {
11952    E_Event_Border_Icon_Change *e;
11953
11954    e = ev;
11955 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
11956    e_object_unref(E_OBJECT(e->border));
11957    E_FREE(e);
11958 }
11959
11960 static void
11961 _e_border_event_border_urgent_change_free(void *data __UNUSED__,
11962                                           void      *ev)
11963 {
11964    E_Event_Border_Urgent_Change *e;
11965
11966    e = ev;
11967    e_object_unref(E_OBJECT(e->border));
11968    E_FREE(e);
11969 }
11970
11971 static void
11972 _e_border_event_border_focus_in_free(void *data __UNUSED__,
11973                                      void      *ev)
11974 {
11975    E_Event_Border_Focus_In *e;
11976
11977    e = ev;
11978    e_object_unref(E_OBJECT(e->border));
11979    E_FREE(e);
11980 }
11981
11982 static void
11983 _e_border_event_border_focus_out_free(void *data __UNUSED__,
11984                                       void      *ev)
11985 {
11986    E_Event_Border_Focus_Out *e;
11987
11988    e = ev;
11989    e_object_unref(E_OBJECT(e->border));
11990    E_FREE(e);
11991 }
11992
11993 static void
11994 _e_border_event_border_property_free(void *data __UNUSED__,
11995                                      void      *ev)
11996 {
11997    E_Event_Border_Property *e;
11998
11999    e = ev;
12000    e_object_unref(E_OBJECT(e->border));
12001    E_FREE(e);
12002 }
12003
12004 static void
12005 _e_border_event_border_fullscreen_free(void *data __UNUSED__,
12006                                        void      *ev)
12007 {
12008    E_Event_Border_Fullscreen *e;
12009
12010    e = ev;
12011 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_fullscreen_event");
12012    e_object_unref(E_OBJECT(e->border));
12013    E_FREE(e);
12014 }
12015
12016 static void
12017 _e_border_event_border_unfullscreen_free(void *data __UNUSED__,
12018                                          void      *ev)
12019 {
12020    E_Event_Border_Unfullscreen *e;
12021
12022    e = ev;
12023 //   e_object_breadcrumb_del(E_OBJECT(e->border), "border_unfullscreen_event");
12024    e_object_unref(E_OBJECT(e->border));
12025    E_FREE(e);
12026 }
12027
12028 #ifdef _F_ZONE_WINDOW_ROTATION_
12029 static void
12030 _e_border_event_border_rotation_change_begin_free(void *data __UNUSED__,
12031                                                   void      *ev)
12032 {
12033    E_Event_Border_Rotation_Change_Begin *e;
12034    e = ev;
12035    e_object_unref(E_OBJECT(e->border));
12036    E_FREE(e);
12037 }
12038
12039 static void
12040 _e_border_event_border_rotation_change_cancel_free(void *data __UNUSED__,
12041                                                    void      *ev)
12042 {
12043    E_Event_Border_Rotation_Change_Cancel *e;
12044    e = ev;
12045    e_object_unref(E_OBJECT(e->border));
12046    E_FREE(e);
12047 }
12048
12049 static void
12050 _e_border_event_border_rotation_change_end_free(void *data __UNUSED__,
12051                                                 void      *ev)
12052 {
12053    E_Event_Border_Rotation_Change_End *e;
12054    e = ev;
12055    e_object_unref(E_OBJECT(e->border));
12056    E_FREE(e);
12057 }
12058
12059 static void
12060 _e_border_event_border_rotation_change_begin_send(E_Border *bd)
12061 {
12062    E_Event_Border_Rotation_Change_Begin *ev = NULL;
12063    ev = E_NEW(E_Event_Border_Rotation_Change_End, 1);
12064    if (ev)
12065      {
12066         ev->border = bd;
12067         e_object_ref(E_OBJECT(bd));
12068         ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_BEGIN,
12069                         ev,
12070                         _e_border_event_border_rotation_change_begin_free,
12071                         NULL);
12072      }
12073 }
12074 #endif
12075
12076 static void
12077 _e_border_zone_update(E_Border *bd)
12078 {
12079    E_Container *con;
12080    Eina_List *l;
12081    E_Zone *zone;
12082
12083    /* still within old zone - leave it there */
12084    if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
12085                     bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
12086 #if _F_BORDER_CLIP_TO_ZONE_
12087      {
12088         _e_border_shape_input_clip_to_zone(bd);
12089         return;
12090      }
12091 #else
12092      return;
12093 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
12094    /* find a new zone */
12095    con = bd->zone->container;
12096    EINA_LIST_FOREACH(con->zones, l, zone)
12097      {
12098         if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
12099                          zone->x, zone->y, zone->w, zone->h))
12100           {
12101              e_border_zone_set(bd, zone);
12102 #if _F_BORDER_CLIP_TO_ZONE_
12103              _e_border_shape_input_clip_to_zone(bd);
12104 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
12105              return;
12106           }
12107      }
12108 }
12109
12110 static int
12111 _e_border_resize_begin(E_Border *bd)
12112 {
12113    int ret;
12114
12115    if (!bd->lock_user_stacking)
12116      {
12117         if (e_config->border_raise_on_mouse_action)
12118           e_border_raise(bd);
12119      }
12120    if ((bd->shaded) || (bd->shading) ||
12121        (bd->fullscreen) || (bd->lock_user_size))
12122      return 0;
12123
12124    if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
12125      ret = e_grabinput_get(bd->win, 0, bd->win);
12126    else
12127      ret = e_grabinput_get(bd->win, 0, 0);
12128
12129    if (grabbed && !ret)
12130      {
12131         grabbed = 0;
12132         return 0;
12133      }
12134
12135    if (bd->client.netwm.sync.request)
12136      {
12137         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12138         bd->client.netwm.sync.serial = 1;
12139         bd->client.netwm.sync.wait = 0;
12140         bd->client.netwm.sync.send_time = ecore_loop_time_get();
12141      }
12142
12143    _e_border_hook_call(E_BORDER_HOOK_RESIZE_BEGIN, bd);
12144
12145    bdresize = bd;
12146    return 1;
12147 }
12148
12149 static int
12150 _e_border_resize_end(E_Border *bd)
12151 {
12152    if (grabbed)
12153      {
12154         e_grabinput_release(bd->win, bd->win);
12155         grabbed = 0;
12156      }
12157    if (bd->client.netwm.sync.alarm)
12158      {
12159         E_Border_Pending_Move_Resize *pnd;
12160
12161         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12162         bd->client.netwm.sync.alarm = 0;
12163         /* resize to last geometry if sync alarm for it was not yet handled */
12164         if (bd->pending_move_resize)
12165           {
12166              bd->changed = 1;
12167              bd->changes.pos = 1;
12168              bd->changes.size = 1;
12169              _e_border_client_move_resize_send(bd);
12170           }
12171
12172         EINA_LIST_FREE(bd->pending_move_resize, pnd)
12173           E_FREE(pnd);
12174      }
12175
12176    _e_border_hook_call(E_BORDER_HOOK_RESIZE_END, bd);
12177
12178    bdresize = NULL;
12179
12180    /* If this border was maximized, we need to unset Maximized state or
12181     * on restart, E still thinks it's maximized */
12182    if (bd->maximized != E_MAXIMIZE_NONE)
12183      e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_NONE,
12184                                   bd->maximized & E_MAXIMIZE_NONE);
12185    return 1;
12186 }
12187
12188 static void
12189 _e_border_resize_update(E_Border *bd)
12190 {
12191    _e_border_hook_call(E_BORDER_HOOK_RESIZE_UPDATE, bd);
12192 }
12193
12194 static int
12195 _e_border_move_begin(E_Border *bd)
12196 {
12197    int ret;
12198    if (!bd->lock_user_stacking)
12199      {
12200         if (e_config->border_raise_on_mouse_action)
12201           e_border_raise(bd);
12202      }
12203    if ((bd->fullscreen) || (bd->lock_user_location))
12204      return 0;
12205
12206    if (bd->client.icccm.accepts_focus || bd->client.icccm.take_focus)
12207      ret = e_grabinput_get(bd->win, 0, bd->win);
12208    else
12209      ret = e_grabinput_get(bd->win, 0, 0);
12210
12211    if (grabbed && !ret)
12212      {
12213         grabbed = 0;
12214         return 0;
12215      }
12216 #if 0
12217    if (bd->client.netwm.sync.request)
12218      {
12219         bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
12220         bd->client.netwm.sync.serial = 0;
12221         bd->client.netwm.sync.wait = 0;
12222         bd->client.netwm.sync.time = ecore_loop_time_get();
12223      }
12224 #endif
12225    _e_border_hook_call(E_BORDER_HOOK_MOVE_BEGIN, bd);
12226
12227    bdmove = bd;
12228    return 1;
12229 }
12230
12231 static int
12232 _e_border_move_end(E_Border *bd)
12233 {
12234    if (grabbed)
12235      {
12236         e_grabinput_release(bd->win, bd->win);
12237         grabbed = 0;
12238      }
12239 #if 0
12240    if (bd->client.netwm.sync.alarm)
12241      {
12242         ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
12243         bd->client.netwm.sync.alarm = 0;
12244      }
12245 #endif
12246    _e_border_hook_call(E_BORDER_HOOK_MOVE_END, bd);
12247
12248    bdmove = NULL;
12249    return 1;
12250 }
12251
12252 static void
12253 _e_border_move_update(E_Border *bd)
12254 {
12255    _e_border_hook_call(E_BORDER_HOOK_MOVE_UPDATE, bd);
12256 }
12257
12258 static Eina_Bool
12259 _e_border_cb_ping_poller(void *data)
12260 {
12261    E_Border *bd;
12262
12263    bd = data;
12264    if (bd->ping_ok)
12265      {
12266         if (bd->hung)
12267           {
12268              bd->hung = 0;
12269              edje_object_signal_emit(bd->bg_object, "e,state,unhung", "e");
12270              if (bd->kill_timer)
12271                {
12272                   ecore_timer_del(bd->kill_timer);
12273                   bd->kill_timer = NULL;
12274                }
12275           }
12276      }
12277    else
12278      {
12279         /* if time between last ping and now is greater
12280          * than half the ping interval... */
12281         if ((ecore_loop_time_get() - bd->ping) >
12282             ((e_config->ping_clients_interval *
12283               ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
12284           {
12285              if (!bd->hung)
12286                {
12287                   bd->hung = 1;
12288                   edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
12289                   /* FIXME: if below dialog is up - hide it now */
12290                }
12291              if (bd->delete_requested)
12292                {
12293                   /* FIXME: pop up dialog saying app is hung - kill client, or pid */
12294                   e_border_act_kill_begin(bd);
12295                }
12296           }
12297      }
12298    bd->ping_poller = NULL;
12299    e_border_ping(bd);
12300    return ECORE_CALLBACK_CANCEL;
12301 }
12302
12303 static Eina_Bool
12304 _e_border_cb_kill_timer(void *data)
12305 {
12306    E_Border *bd;
12307
12308    bd = data;
12309 // dont wait until it's hung -
12310 //   if (bd->hung)
12311 //     {
12312         if (bd->client.netwm.pid > 1)
12313           kill(bd->client.netwm.pid, SIGKILL);
12314 //     }
12315    bd->kill_timer = NULL;
12316    return ECORE_CALLBACK_CANCEL;
12317 }
12318
12319 static void
12320 _e_border_pointer_resize_begin(E_Border *bd)
12321 {
12322    switch (bd->resize_mode)
12323      {
12324       case RESIZE_TL:
12325         e_pointer_type_push(bd->pointer, bd, "resize_tl");
12326         break;
12327
12328       case RESIZE_T:
12329         e_pointer_type_push(bd->pointer, bd, "resize_t");
12330         break;
12331
12332       case RESIZE_TR:
12333         e_pointer_type_push(bd->pointer, bd, "resize_tr");
12334         break;
12335
12336       case RESIZE_R:
12337         e_pointer_type_push(bd->pointer, bd, "resize_r");
12338         break;
12339
12340       case RESIZE_BR:
12341         e_pointer_type_push(bd->pointer, bd, "resize_br");
12342         break;
12343
12344       case RESIZE_B:
12345         e_pointer_type_push(bd->pointer, bd, "resize_b");
12346         break;
12347
12348       case RESIZE_BL:
12349         e_pointer_type_push(bd->pointer, bd, "resize_bl");
12350         break;
12351
12352       case RESIZE_L:
12353         e_pointer_type_push(bd->pointer, bd, "resize_l");
12354         break;
12355      }
12356 }
12357
12358 static void
12359 _e_border_pointer_resize_end(E_Border *bd)
12360 {
12361    switch (bd->resize_mode)
12362      {
12363       case RESIZE_TL:
12364         e_pointer_type_pop(bd->pointer, bd, "resize_tl");
12365         break;
12366
12367       case RESIZE_T:
12368         e_pointer_type_pop(bd->pointer, bd, "resize_t");
12369         break;
12370
12371       case RESIZE_TR:
12372         e_pointer_type_pop(bd->pointer, bd, "resize_tr");
12373         break;
12374
12375       case RESIZE_R:
12376         e_pointer_type_pop(bd->pointer, bd, "resize_r");
12377         break;
12378
12379       case RESIZE_BR:
12380         e_pointer_type_pop(bd->pointer, bd, "resize_br");
12381         break;
12382
12383       case RESIZE_B:
12384         e_pointer_type_pop(bd->pointer, bd, "resize_b");
12385         break;
12386
12387       case RESIZE_BL:
12388         e_pointer_type_pop(bd->pointer, bd, "resize_bl");
12389         break;
12390
12391       case RESIZE_L:
12392         e_pointer_type_pop(bd->pointer, bd, "resize_l");
12393         break;
12394      }
12395 }
12396
12397 static void
12398 _e_border_pointer_move_begin(E_Border *bd)
12399 {
12400    e_pointer_type_push(bd->pointer, bd, "move");
12401 }
12402
12403 static void
12404 _e_border_pointer_move_end(E_Border *bd)
12405 {
12406    e_pointer_type_pop(bd->pointer, bd, "move");
12407 }
12408
12409 static Eina_List *_e_border_hooks = NULL;
12410 static int _e_border_hooks_delete = 0;
12411 static int _e_border_hooks_walking = 0;
12412
12413 static void
12414 _e_border_hooks_clean(void)
12415 {
12416    Eina_List *l, *ln;
12417    E_Border_Hook *bh;
12418
12419    EINA_LIST_FOREACH_SAFE(_e_border_hooks, l, ln, bh)
12420      {
12421         if (bh->delete_me)
12422           {
12423              _e_border_hooks = eina_list_remove_list(_e_border_hooks, l);
12424              free(bh);
12425           }
12426      }
12427 }
12428
12429 static void
12430 _e_border_hook_call(E_Border_Hook_Point hookpoint,
12431                     void               *bd)
12432 {
12433    Eina_List *l;
12434    E_Border_Hook *bh;
12435
12436    _e_border_hooks_walking++;
12437    EINA_LIST_FOREACH(_e_border_hooks, l, bh)
12438      {
12439         if (bh->delete_me) continue;
12440         if (bh->hookpoint == hookpoint) bh->func(bh->data, bd);
12441      }
12442    _e_border_hooks_walking--;
12443    if ((_e_border_hooks_walking == 0) && (_e_border_hooks_delete > 0))
12444      _e_border_hooks_clean();
12445 }
12446
12447 EAPI E_Border_Hook *
12448 e_border_hook_add(E_Border_Hook_Point               hookpoint,
12449                   void                              (*func)(void *data,
12450                                               void *bd),
12451                   void                             *data)
12452 {
12453    E_Border_Hook *bh;
12454
12455    bh = E_NEW(E_Border_Hook, 1);
12456    if (!bh) return NULL;
12457    bh->hookpoint = hookpoint;
12458    bh->func = func;
12459    bh->data = data;
12460    _e_border_hooks = eina_list_append(_e_border_hooks, bh);
12461    return bh;
12462 }
12463
12464 EAPI void
12465 e_border_hook_del(E_Border_Hook *bh)
12466 {
12467    bh->delete_me = 1;
12468    if (_e_border_hooks_walking == 0)
12469      {
12470         _e_border_hooks = eina_list_remove(_e_border_hooks, bh);
12471         free(bh);
12472      }
12473    else
12474      _e_border_hooks_delete++;
12475 }
12476
12477 EAPI void
12478 e_border_focus_track_freeze(void)
12479 {
12480    focus_track_frozen++;
12481 }
12482
12483 EAPI void
12484 e_border_focus_track_thaw(void)
12485 {
12486    focus_track_frozen--;
12487 }
12488
12489 EAPI E_Border *
12490 e_border_under_pointer_get(E_Desk   *desk,
12491                            E_Border *exclude)
12492 {
12493    E_Border *bd = NULL, *cbd;
12494    Eina_List *l;
12495    int x, y;
12496
12497    /* We need to ensure that we can get the container window for the
12498     * zone of either the given desk or the desk of the excluded
12499     * window, so return if neither is given */
12500    if (desk)
12501      ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
12502    else if (exclude)
12503      ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
12504    else
12505      return NULL;
12506
12507    EINA_LIST_FOREACH(e_border_raise_stack_get(), l, cbd)
12508      {
12509         if (!cbd) continue;
12510         /* If a border was specified which should be excluded from the list
12511          * (because it will be closed shortly for example), skip */
12512         if ((exclude) && (cbd == exclude)) continue;
12513         if ((desk) && (cbd->desk != desk)) continue;
12514         if (!E_INSIDE(x, y, cbd->x, cbd->y, cbd->w, cbd->h))
12515           continue;
12516         /* If the layer is higher, the position of the window is higher
12517          * (always on top vs always below) */
12518         if (!bd || (cbd->layer > bd->layer))
12519           {
12520              bd = cbd;
12521              break;
12522           }
12523      }
12524    return bd;
12525 }
12526
12527 static Eina_Bool
12528 _e_border_pointer_warp_to_center_timer(void *data __UNUSED__)
12529 {
12530    if (warp_to)
12531      {
12532         int x, y;
12533         double spd;
12534
12535         ecore_x_pointer_xy_get(warp_to_win, &x, &y);
12536         if ((x - warp_x) > 5 || (x - warp_x) < -5 ||
12537             (y - warp_y) > 5 || (y - warp_y) < -5)
12538           {
12539              /* User moved the mouse, so stop warping */
12540              warp_to = 0;
12541              goto cleanup;
12542           }
12543
12544         /* We just use the same warp speed as configured
12545          * for the windowlist */
12546         spd = e_config->winlist_warp_speed;
12547         x = warp_x;
12548         y = warp_y;
12549         warp_x = (x * (1.0 - spd)) + (warp_to_x * spd);
12550         warp_y = (y * (1.0 - spd)) + (warp_to_y * spd);
12551         if (warp_x == x && warp_y == y)
12552           {
12553              warp_x = warp_to_x;
12554              warp_y = warp_to_y;
12555              warp_to = 0;
12556              goto cleanup;
12557           }
12558         ecore_x_pointer_warp(warp_to_win, warp_x, warp_y);
12559         return ECORE_CALLBACK_RENEW;
12560      }
12561  cleanup:
12562    ecore_timer_del(warp_timer);
12563    warp_timer = NULL;
12564    return ECORE_CALLBACK_CANCEL;
12565 }
12566
12567 EAPI int
12568 e_border_pointer_warp_to_center(E_Border *bd)
12569 {
12570    int x, y;
12571
12572    /* Do not slide pointer when disabled (probably breaks focus
12573     * on sloppy/mouse focus but requested by users). */
12574    if (!e_config->pointer_slide) return 0;
12575    /* Only warp the pointer if it is not already in the area of
12576     * the given border */
12577    ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
12578    if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
12579        (y >= bd->y) && (y <= (bd->y + bd->h)))
12580      return 0;
12581
12582    warp_to_x = bd->x + (bd->w / 2);
12583    if (warp_to_x < (bd->zone->x + 1))
12584      warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
12585    else if (warp_to_x > (bd->zone->x + bd->zone->w))
12586      warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
12587
12588    warp_to_y = bd->y + (bd->h / 2);
12589    if (warp_to_y < (bd->zone->y + 1))
12590      warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
12591    else if (warp_to_y > (bd->zone->y + bd->zone->h))
12592      warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
12593
12594    warp_to = 1;
12595    warp_to_win = bd->zone->container->win;
12596    ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x, &warp_y);
12597    if (!warp_timer)
12598      warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, (const void *)bd);
12599    return 1;
12600 }
12601
12602 EAPI void
12603 e_border_comp_hidden_set(E_Border *bd,
12604                          Eina_Bool hidden)
12605 {
12606    E_Border *tmp;
12607    Eina_List *l;
12608
12609    E_OBJECT_CHECK(bd);
12610    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12611
12612    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12613      {
12614        if (hidden)
12615          ecore_x_window_hide(tmp->win);
12616        else
12617          ecore_x_window_show(tmp->win);
12618      }
12619
12620    if (bd->comp_hidden == hidden) return;
12621
12622    bd->comp_hidden = hidden;
12623
12624    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12625      {
12626         ecore_x_composite_window_events_disable(bd->win);
12627         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12628      }
12629    else
12630      {
12631         _e_border_shape_input_rectangle_set(bd);
12632         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12633      }
12634 }
12635
12636 EAPI void
12637 e_border_tmp_input_hidden_push(E_Border *bd)
12638 {
12639    E_Border *tmp;
12640    Eina_List *l;
12641
12642    E_OBJECT_CHECK(bd);
12643    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12644
12645    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12646      e_border_tmp_input_hidden_push(tmp);
12647
12648    bd->tmp_input_hidden++;
12649    if (bd->tmp_input_hidden != 1) return;
12650
12651    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12652      {
12653         ecore_x_composite_window_events_disable(bd->win);
12654         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12655      }
12656    else
12657      {
12658         _e_border_shape_input_rectangle_set(bd);
12659         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12660      }
12661 }
12662
12663 EAPI void
12664 e_border_tmp_input_hidden_pop(E_Border *bd)
12665 {
12666    E_Border *tmp;
12667    Eina_List *l;
12668
12669    E_OBJECT_CHECK(bd);
12670    E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
12671
12672    EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
12673      e_border_tmp_input_hidden_pop(tmp);
12674
12675    bd->tmp_input_hidden--;
12676    if (bd->tmp_input_hidden != 0) return;
12677
12678    if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
12679      {
12680         ecore_x_composite_window_events_disable(bd->win);
12681         ecore_x_window_ignore_set(bd->win, EINA_TRUE);
12682      }
12683    else
12684      {
12685         _e_border_shape_input_rectangle_set(bd);
12686         ecore_x_window_ignore_set(bd->win, EINA_FALSE);
12687      }
12688 }
12689
12690 EAPI void
12691 e_border_activate(E_Border *bd, Eina_Bool just_do_it)
12692 {
12693    if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
12694        ((bd->parent) &&
12695         ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
12696          ((bd->parent->focused) &&
12697           (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))) ||
12698        (just_do_it))
12699      {
12700         if (bd->iconic)
12701           {
12702              if (e_config->clientlist_warp_to_iconified_desktop == 1)
12703                e_desk_show(bd->desk);
12704              
12705              if (!bd->lock_user_iconify)
12706                e_border_uniconify(bd);
12707           }
12708         if ((!bd->iconic) && (!bd->sticky))
12709           e_desk_show(bd->desk);
12710         if (!bd->lock_user_stacking) e_border_raise(bd);
12711         if (!bd->lock_focus_out)
12712           {
12713              /* XXX ooffice does send this request for
12714               config dialogs when the main window gets focus.
12715               causing the pointer to jump back and forth.  */
12716              if ((e_config->focus_policy != E_FOCUS_CLICK) &&
12717                  !(bd->client.icccm.name && !strcmp(bd->client.icccm.name, "VCLSalFrame")))
12718                ecore_x_pointer_warp(bd->zone->container->win,
12719                                     bd->x + (bd->w / 2), bd->y + (bd->h / 2));
12720              e_border_focus_set(bd, 1, 1);
12721           }
12722      }
12723 }
12724 /*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/